사용자 지정 Qt Quick Controls
Qt Quick Controls 는 항목의 계층 구조(트리)로 구성됩니다. 사용자 지정 모양과 느낌을 제공하기 위해 각 항목의 기본 QML 구현을 사용자 지정으로 바꿀 수 있습니다.
컨트롤 사용자 지정하기
때로는 UI의 특정 부분에 대해 "일회성" 모양을 만들고 다른 모든 곳에 완전한 스타일을 사용하고 싶을 때가 있습니다. 현재 사용 중인 스타일에 만족하지만 특별한 의미가 있는 특정 버튼이 있을 수도 있습니다.
이 버튼을 만드는 첫 번째 방법은 필요한 위치에 간단히 정의하는 것입니다. 예를 들어 기본 스타일의 버튼 모서리가 사각형인 것이 마음에 들지 않을 수 있습니다. 모서리를 둥글게 만들려면 background 항목을 재정의하고 직사각형의 반지름 속성을 설정하면 됩니다:
import QtQuick import QtQuick.Controls.Basic ApplicationWindow { width: 400 height: 400 visible: true Button { id: button text: "A Special Button" background: Rectangle { implicitWidth: 100 implicitHeight: 40 color: button.down ? "#d6d6d6" : "#f6f6f6" border.color: "#26282a" border.width: 1 radius: 4 } } }
참고: 특정 스타일의 컨트롤을 구성하는 여러 항목이 함께 작동하도록 설계되었으므로 원하는 모양을 얻으려면 다른 항목을 재정의해야 할 수도 있습니다. 또한 모든 스타일을 사용자 지정할 수 있는 것은 아닙니다. 자세한 내용은 사용자 지정 참조의 메모를 참조하세요.
둥근 버튼을 여러 곳에서 사용하려는 경우 버튼을 만드는 두 번째 방법이 좋습니다. 이 방법은 코드를 프로젝트 내의 자체 QML 파일로 이동하는 것입니다.
이 접근 방식에서는 기본 스타일의 Button.qml
에서 배경 코드를 복사합니다. 이 파일은 Qt 설치의 다음 경로에서 찾을 수 있습니다:
$QTDIR/qml/QtQuick/Controls/Basic/Button.qml
그런 다음 다음 줄을 추가하기만 하면 됩니다:
radius: 4
모듈 자체의 컨트롤과 혼동을 피하기 위해 파일을 MyButton.qml
이라고 부를 것입니다. 애플리케이션에서 컨트롤을 사용하려면 파일 이름으로 해당 컨트롤을 참조하세요:
import QtQuick.Controls.Basic ApplicationWindow { MyButton { text: qsTr("A Special Button") } }
세 번째 버튼 생성 방법은 파일이 파일 시스템에서 어디에 위치하는지, 그리고 QML에서 어떻게 사용되는지 측면에서 좀 더 구조화되어 있습니다. 먼저 위에서 한 것처럼 기존 파일을 복사하되 이번에는 프로젝트의 하위 폴더(예: controls
)에 파일을 넣습니다. 컨트롤을 사용하려면 먼저 폴더를 네임스페이스로 가져옵니다:
import QtQuick.Controls.Basic import "controls" as MyControls ApplicationWindow { MyControls.Button { text: qsTr("A Special Button") } }
이제 MyControls
네임스페이스가 생겼으므로 Qt Quick Controls 모듈에 있는 실제 컨트롤의 이름을 따서 컨트롤의 이름을 지정할 수 있습니다. 추가하려는 모든 컨트롤에 대해 이 과정을 반복할 수 있습니다.
이 세 가지 방법의 또 다른 장점은 템플릿을 처음부터 구현할 필요가 없다는 것입니다.
참고: 여기에 언급된 세 가지 방법은 내부적으로 만든 공유 항목이므로 첨부된 ToolTip 을 사용자 지정하는 데는 사용할 수 없습니다. ToolTip
을 일회성으로 사용자 지정하려면 Custom Tool Tips 을 참조하세요. 첨부된 ToolTip
을 사용자 지정하려면 고유한 스타일의 일부로 제공해야 합니다.
사용자 정의 스타일 만들기
나만의 스타일을 만드는 방법에는 여러 가지가 있습니다. 아래에서 다양한 접근 방식에 대해 설명합니다.
스타일의 정의
Qt Quick Controls 에서 스타일은 기본적으로 단일 디렉터리 내의 QML 파일 집합입니다. 스타일을 사용할 수 있으려면 네 가지 요구 사항이 있습니다:
- 이름이 컨트롤(예:
Button.qml
)과 일치하는 QML 파일이 하나 이상 존재해야 합니다. - 각 QML 파일에는 QtQuick.Templates 가져오기의 관련 유형이 루트 항목으로 포함되어 있어야 합니다. 예를 들어 Button.qml에는 Button 템플릿이 루트 항목으로 포함되어야 합니다.
이전 섹션에서와 같이 QtQuick.Controls 임포트에서 해당 유형을 대신 사용하면 정의한 컨트롤이 자체에서 파생하려고 시도하므로 작동하지 않습니다.
- QML 파일과 함께 qmldir 파일이 존재해야 합니다. 아래는 버튼을 제공하는 스타일에 대한 간단한
qmldir
파일의 예시입니다:module MyStyle Button 2.15 Button.qml
컴파일 시 스타일 선택을 사용하는 경우 qmldir은 폴백 스타일도 가져와야 합니다:
# ... import QtQuick.Controls.Basic auto
예를 들어 QQuickStyle::setFallbackStyle()를 사용하는 대신 런타임 스타일 선택에 대해서도 이 작업을 수행할 수 있습니다.
이러한 스타일의 디렉토리 구조는 다음과 같습니다:
MyStyle ├─── Button.qml └─── qmldir
- 파일은 QML 가져오기 경로를 통해 찾을 수 있는 디렉토리에 있어야 합니다.
예를 들어 위에서 언급한 MyStyle 디렉터리 경로가
/home/user/MyApp/MyStyle
인 경우/home/user/MyApp
을 QML 가져오기 경로에 추가해야 합니다.MyApp에서 MyStyle을 사용하려면 이름으로 참조합니다:
./MyApp -style MyStyle
스타일 이름은 스타일 디렉터리의 대소문자와 일치해야 하며, mystyle 또는 MYSTYLE을 전달하는 것은 지원되지 않습니다.
기본적으로 스타일링 시스템은 구현되지 않은 컨트롤에 대해 기본 스타일을 폴백으로 사용합니다. 다른 기본 제공 스타일을 사용자 정의하거나 확장하려면 QQuickStyle 을 사용하여 다른 대체 스타일을 지정할 수 있습니다.
즉, 사용자 지정 스타일에 원하는 만큼의 컨트롤을 구현하고 거의 모든 곳에 배치할 수 있습니다. 또한 사용자가 애플리케이션에 대한 자신만의 스타일을 만들 수도 있습니다.
Qt Quick 디자이너에서 사용자 정의 스타일 미리보기
위의 방법을 사용하여 Qt Quick 디자이너에서 사용자 정의 스타일을 미리 볼 수 있습니다. 이렇게 하려면 프로젝트에 qtquickcontrols2.conf 파일이 있고 다음 항목이 있는지 확인합니다:
[Controls] Style=MyStyle
자세한 내용은 플랫 스타일 예제를 참조하세요.
스타일별 C++ 확장
사용자 정의 스타일을 확장하기 위해 C++를 사용해야 하는 경우가 있습니다.
- 해당 스타일을 사용하는 스타일이 애플리케이션에서 사용하는 유일한 스타일인 경우 QML_ELEMENT 매크로를 추가하고 파일을 QML 모듈의 일부로 만들어 QML 엔진에 해당 스타일을 등록합니다:
qmake#tab-qmakeqt_add_qml_module(ACoolItem URI MyItems VERSION 1.0 SOURCES acoolcppitem.cpp acoolcppitem.h )
CONFIG += qmltypes QML_IMPORT_NAME = MyItems QML_IMPORT_MAJOR_VERSION = 1
클래스가 선언된 헤더가 프로젝트의 include 경로에서 액세스할 수 없는 경우, 생성된 등록 코드를 컴파일할 수 있도록 include 경로를 수정해야 할 수 있습니다.
INCLUDEPATH += MyItems
자세한 내용은 C++에서 QML 유형 정의하기 및 QML 애플리케이션 빌드하기를 참조하세요.
- 해당 유형을 사용하는 스타일이 애플리케이션에서 사용하는 여러 스타일 중 하나인 경우 각 스타일을 별도의 모듈에 넣는 것이 좋습니다. 그러면 모듈이 필요할 때 로드됩니다.
사용자 정의 스타일에 대한 고려 사항
자신만의 스타일을 구현하고 컨트롤을 사용자 지정할 때 애플리케이션의 성능을 최대한 발휘할 수 있도록 몇 가지 유의해야 할 사항이 있습니다.
스타일의 항목 델리게이트 구현에 ID를 할당하지 마세요.
스타일 정의에서 설명한 대로 컨트롤에 대한 고유한 스타일을 구현할 때는 해당 컨트롤에 대한 관련 템플릿으로 시작합니다. 예를 들어 스타일의 Button.qml
구조는 이와 유사하게 구성됩니다:
T.Button { // ... background: Rectangle { // ... } contentItem: Text { // ... } // ... }
애플리케이션에서 버튼을 사용하면 background
및 contentItem
항목이 만들어지고 루트 Button
항목에 부모가 됩니다:
// Creates the Button root item, the Rectangle background, // and the Text contentItem. Button { text: qsTr("Confirm") }
그런 다음 버튼의 일회성 사용자 지정( 컨트롤 사용자 지정에 설명된 대로)을 수행해야 한다고 가정해 보겠습니다:
import QtQuick import QtQuick.Controls.Basic ApplicationWindow { width: 400 height: 400 visible: true Button { id: button text: "A Special Button" background: Rectangle { implicitWidth: 100 implicitHeight: 40 color: button.down ? "#d6d6d6" : "#f6f6f6" border.color: "#26282a" border.width: 1 radius: 4 } } }
QML에서는 일반적으로 기본 background
구현과 일회성 사용자 지정 background
항목이 모두 생성됩니다. Qt Quick Controls 는 두 항목을 모두 생성하지 않고 대신 사용자 지정 background
만 생성하는 기술을 사용하여 컨트롤의 생성 성능을 크게 향상시킵니다.
이 기법은 해당 항목의 스타일 구현에 ID가 없는 경우에 의존합니다. ID가 할당되어 있으면 이 기법이 작동하지 않으며 두 항목이 모두 생성됩니다. 예를 들어 파일 내의 다른 객체가 해당 항목을 참조할 수 있도록 background
또는 contentItem
에 ID를 할당하고 싶을 수 있습니다:
T.Button { // ... background: Rectangle { id: backgroundRect // ... } contentItem: Text { // Use backgroundRect in some way... } // ... }
이 코드를 사용하면 사용자 정의 배경이 있는 버튼 인스턴스가 생성될 때마다 두 배경이 모두 생성되므로 생성 성능이 최적화되지 않습니다.
Qt 5.15 이전에는 사용하지 않는 오래된 배경을 삭제하여 관련 리소스를 해제했습니다. 그러나 컨트롤이 해당 항목을 소유하지 않으므로 삭제해서는 안 됩니다. Qt 5.15부터 이전 항목은 더 이상 삭제되지 않으므로 backgroundRect
항목은 일반적으로 애플리케이션이 종료될 때까지 필요 이상으로 오래 유지됩니다. 이전 항목은 숨겨지고 컨트롤에서 시각적으로 부모가 없으며 접근성 트리에서 제거되지만, 이러한 상황에서 ID를 할당할 때는 사용하지 않는 항목의 생성 시간과 메모리 사용량을 염두에 두는 것이 중요합니다.
사용자 지정 항목의 필수 할당 피하기
위 섹션에서 언급한 기술은 항목이 처음으로 선언적으로 할당될 때만 작동하므로 명령형 할당은 고아가 된 항목을 만들게 됩니다. 가능하면 항상 선언적 바인딩을 사용하여 사용자 지정 항목을 할당하세요.
QML 구현에서 QtQuick.Controls 임포트하지 않기
스타일의 컨트롤 구현을 위한 QML을 작성할 때 QtQuick.Controls
을 임포트하지 않는 것이 중요합니다. 그렇게 하면 QML 컴파일러가 QML을 컴파일하지 못하게 됩니다.
다른 유형에서 사용하는 유형 구현하기
애플리케이션에서 스크롤 뷰를 사용하고 있는데 스크롤 막대를 사용자 정의하고 싶다고 가정해 보겠습니다. 사용자 지정 ScrollBar.qml을 구현하고 ScrollView 이 사용자 지정 ScrollBar 을 자동으로 선택하도록 하고 싶을 수도 있습니다. 하지만 이렇게 하면 작동하지 않습니다. ScrollBar . qml과 ScrollView.qml을 모두 구현해야 합니다.
첨부된 속성
스타일에는 모든 컨트롤에 적용되는 특정 속성이나 속성이 있는 것이 일반적입니다. 첨부 프로퍼티는 해당 항목에 속하는 기존 C++를 수정하지 않고도 QML에서 항목을 확장할 수 있는 좋은 방법입니다. 예를 들어 Material 및 Universal 스타일에는 항목과 그 자식을 밝은 테마로 렌더링할지 어두운 테마로 렌더링할지를 제어하는 첨부 테마 속성이 있습니다.
예를 들어 높낮이를 제어하는 프로퍼티를 추가해 보겠습니다. 이 스타일은 그림자를 사용하여 고도를 나타내며, 고도가 높을수록 그림자가 커집니다.
첫 번째 단계는 Qt Creator 에서 새 Qt Quick Controls 애플리케이션을 만드는 것입니다. 그런 다음 고도를 저장하는 C++ 타입을 추가합니다. 이 유형은 스타일에서 지원하는 모든 컨트롤에 사용되며 나중에 다른 첨부 프로퍼티를 추가할 수 있으므로 MyStyle이라고 부르겠습니다. 여기 MyStyle.h
:
#ifndef MYSTYLE_H #define MYSTYLE_H #include <QObject> #include <QtQml> class MyStyle : public QObject { Q_OBJECT Q_PROPERTY(int elevation READ elevation WRITE setElevation NOTIFY elevationChanged) public: explicit MyStyle(QObject *parent = nullptr); static MyStyle *qmlAttachedProperties(QObject *object); int elevation() const; void setElevation(int elevation); signals: void elevationChanged(); private: int m_elevation; }; QML_DECLARE_TYPEINFO(MyStyle, QML_HAS_ATTACHED_PROPERTIES) #endif // MYSTYLE_H
MyStyle.cpp
:
#include "mystyle.h" MyStyle::MyStyle(QObject *parent) : QObject(parent), m_elevation(0) { } MyStyle *MyStyle::qmlAttachedProperties(QObject *object) { return new MyStyle(object); } int MyStyle::elevation() const { return m_elevation; } void MyStyle::setElevation(int elevation) { if (elevation == m_elevation) return; m_elevation = elevation; emit elevationChanged(); }
MyStyle
유형은 인스턴스화되지 않고 첨부된 프로퍼티에 사용되어야 한다는 점에서 특별합니다. 따라서 main.cpp
에 다음과 같은 방식으로 등록합니다:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "mystyle.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterUncreatableType<MyStyle>("MyStyle", 1, 0, "MyStyle", "MyStyle is an attached property"); QQmlApplicationEngine engine; // Make the directory containing our style known to the QML engine. engine.addImportPath(":/"); engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
그런 다음 $QTDIR/qml/QtQuick/Controls/Basic/
의 기본 스타일에서 Button.qml
을 프로젝트 디렉토리의 새 myproject
폴더에 복사합니다. 새로 복사한 Button.qml
을 QML 파일이 들어 있는 리소스 파일인 qml.qrc
에 추가합니다.
다음으로 버튼의 background 델리게이트에 그림자를 추가합니다:
// ... import QtQuick.Effects import MyStyle // ... background: Rectangle { // ... layer.enabled: control.enabled && control.MyStyle.elevation > 0 layer.effect: MultiEffect { shadowEnabled: true shadowHorizontalOffset: 3 shadowVerticalOffset: 3 shadowColor: control.visualFocus ? "#330066ff" : "#aaaaaa" shadowBlur: control.pressed ? 0.8 : 0.4 } }
참고하세요:
- 고도가 다음과 같을 때 그림자를 사용하지 마십시오.
0
- 버튼에 초점이 있는지 여부에 따라 그림자의 색상을 변경합니다.
- 그림자의 크기를 높이에 따라 다르게 만들기
첨부된 프로퍼티를 사용해 보기 위해 main.qml
에 버튼 두 개가 있는 Row 을 만듭니다:
import QtQuick import QtQuick.Controls import MyStyle 1.0 ApplicationWindow { id: window width: 400 height: 400 visible: true Row { spacing: 20 anchors.centerIn: parent Button { text: "Button 1" } Button { text: "Button 2" MyStyle.elevation: 10 } } }
한 버튼은 높이가 없고 다른 버튼은 10
의 높이를 갖습니다.
이제 예제를 실행할 수 있습니다. 애플리케이션에 새 스타일을 사용하도록 하기 위해 애플리케이션 인수로 -style MyStyle
을 전달하지만, 사용할 스타일을 지정하는 방법에는 여러 가지가 있습니다.
최종 결과물입니다:
import MyStyle 1.0
문은 MyStyle
에 속하는 첨부 프로퍼티를 사용하기 때문에 필요합니다. 가져오기를 제거하더라도 두 버튼 모두 사용자 정의 스타일을 사용합니다.
사용자 정의 참조
다음 코드 조각은 컨트롤 사용자 지정하기 섹션과 동일한 접근 방식을 사용하여 기본 스타일의 컨트롤을 사용자 지정한 예제입니다. 이 코드는 사용자 지정 모양과 느낌을 구현하기 위한 시작점으로 사용할 수 있습니다.
참고: macOS 및 Windows 스타일은 사용자 지정에 적합하지 않습니다. 대신 항상 모든 플랫폼에서 사용할 수 있는 단일 스타일(예: 기본 스타일, 퓨전 스타일, 상상 스타일, 머티리얼 스타일, 유니버설 스타일)을 기반으로 사용자 지정 컨트롤을 만드는 것이 좋습니다. 이렇게 하면 애플리케이션이 어떤 스타일로 실행되든 항상 동일하게 보이도록 보장할 수 있습니다. 다른 스타일을 사용하는 방법을 알아보려면 Qt Quick Controls 에서 스타일 사용을 참조하세요. 또는 자신만의 스타일을 만들 수도 있습니다.
ApplicationWindow 사용자 지정
ApplicationWindow 는 하나의 시각적 항목으로 구성됩니다: background.
import QtQuick import QtQuick.Controls.Basic ApplicationWindow { visible: true background: Rectangle { gradient: Gradient { GradientStop { position: 0; color: "#ffffff" } GradientStop { position: 1; color: "#c1bbf9" } } } }
바쁨 표시기 사용자 지정하기
BusyIndicator 는 background 과 contentItem 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic BusyIndicator { id: control contentItem: Item { implicitWidth: 64 implicitHeight: 64 Item { id: item x: parent.width / 2 - 32 y: parent.height / 2 - 32 width: 64 height: 64 opacity: control.running ? 1 : 0 Behavior on opacity { OpacityAnimator { duration: 250 } } RotationAnimator { target: item running: control.visible && control.running from: 0 to: 360 loops: Animation.Infinite duration: 1250 } Repeater { id: repeater model: 6 Rectangle { id: delegate x: item.width / 2 - width / 2 y: item.height / 2 - height / 2 implicitWidth: 10 implicitHeight: 10 radius: 5 color: "#21be2b" required property int index transform: [ Translate { y: -Math.min(item.width, item.height) * 0.5 + 5 }, Rotation { angle: delegate.index / repeater.count * 360 origin.x: 5 origin.y: 5 } ] } } } } }
사용자 지정 버튼
버튼은 background 와 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic Button { id: control text: qsTr("Button") contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 100 implicitHeight: 40 opacity: enabled ? 1 : 0.3 border.color: control.down ? "#17a81a" : "#21be2b" border.width: 1 radius: 2 } }
체크박스 사용자 지정하기
CheckBox 는 세 가지 시각적 항목으로 구성됩니다: background, contentItem 및 indicator 입니다.
import QtQuick import QtQuick.Controls.Basic CheckBox { id: control text: qsTr("CheckBox") checked: true indicator: Rectangle { implicitWidth: 26 implicitHeight: 26 x: control.leftPadding y: parent.height / 2 - height / 2 radius: 3 border.color: control.down ? "#17a81a" : "#21be2b" Rectangle { width: 14 height: 14 x: 6 y: 6 radius: 2 color: control.down ? "#17a81a" : "#21be2b" visible: control.checked } } contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" verticalAlignment: Text.AlignVCenter leftPadding: control.indicator.width + control.spacing } }
체크 델리게이트 사용자 지정하기
CheckDelegate 는 세 가지 시각적 항목으로 구성됩니다: background, contentItem 및 indicator.
import QtQuick import QtQuick.Controls.Basic CheckDelegate { id: control text: qsTr("CheckDelegate") checked: true contentItem: Text { rightPadding: control.indicator.width + control.spacing text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } indicator: Rectangle { implicitWidth: 26 implicitHeight: 26 x: control.width - width - control.rightPadding y: control.topPadding + control.availableHeight / 2 - height / 2 radius: 3 color: "transparent" border.color: control.down ? "#17a81a" : "#21be2b" Rectangle { width: 14 height: 14 x: 6 y: 6 radius: 2 color: control.down ? "#17a81a" : "#21be2b" visible: control.checked } } background: Rectangle { implicitWidth: 100 implicitHeight: 40 visible: control.down || control.highlighted color: control.down ? "#bdbebf" : "#eeeeee" } }
콤보박스 사용자 지정하기
ComboBox 는 background, content item, popup, indicator, delegate 로 구성됩니다.
pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls.Basic ComboBox { id: control model: ["First", "Second", "Third"] delegate: ItemDelegate { id: delegate required property var model required property int index width: control.width contentItem: Text { text: delegate.model[control.textRole] color: "#21be2b" font: control.font elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } highlighted: control.highlightedIndex === index } indicator: Canvas { id: canvas x: control.width - width - control.rightPadding y: control.topPadding + (control.availableHeight - height) / 2 width: 12 height: 8 contextType: "2d" Connections { target: control function onPressedChanged() { canvas.requestPaint(); } } onPaint: { context.reset(); context.moveTo(0, 0); context.lineTo(width, 0); context.lineTo(width / 2, height); context.closePath(); context.fillStyle = control.pressed ? "#17a81a" : "#21be2b"; context.fill(); } } contentItem: Text { leftPadding: 0 rightPadding: control.indicator.width + control.spacing text: control.displayText font: control.font color: control.pressed ? "#17a81a" : "#21be2b" verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 120 implicitHeight: 40 border.color: control.pressed ? "#17a81a" : "#21be2b" border.width: control.visualFocus ? 2 : 1 radius: 2 } popup: Popup { y: control.height - 1 width: control.width height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin) padding: 1 contentItem: ListView { clip: true implicitHeight: contentHeight model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex ScrollIndicator.vertical: ScrollIndicator { } } background: Rectangle { border.color: "#21be2b" radius: 2 } } }
ComboBox Model Roles, ComboBox 에서 설명한 대로 여러 유형의 모델을 지원합니다.
모든 모델은 modelData
으로 익명 속성을 제공하므로 다음 표현식은 모든 경우에 올바른 텍스트를 검색합니다:
text: model[control.textRole]
특정 textRole
과 선택한 역할을 제공하는 구조화된 데이터를 모델에 제공하는 경우 이 표현식은 일반 속성 조회입니다. 문자열 목록과 같은 단수 데이터와 빈 textRole
을 모델에 제공하면 이 표현식은 modelData
을 검색합니다.
DelayButton 사용자 지정하기
DelayButton 은 background 와 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic DelayButton { id: control checked: true text: qsTr("Delay\nButton") contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 100 implicitHeight: 100 opacity: enabled ? 1 : 0.3 color: control.down ? "#17a81a" : "#21be2b" radius: size / 2 readonly property real size: Math.min(control.width, control.height) width: size height: size anchors.centerIn: parent Canvas { id: canvas anchors.fill: parent Connections { target: control function onProgressChanged() { canvas.requestPaint(); } } onPaint: { var ctx = getContext("2d") ctx.clearRect(0, 0, width, height) ctx.strokeStyle = "white" ctx.lineWidth = parent.size / 20 ctx.beginPath() var startAngle = Math.PI / 5 * 3 var endAngle = startAngle + control.progress * Math.PI / 5 * 9 ctx.arc(width / 2, height / 2, width / 2 - ctx.lineWidth / 2 - 2, startAngle, endAngle) ctx.stroke() } } } }
다이얼 사용자 지정하기
다이얼은 background 과 handle 의 두 가지 시각적 항목으로 구성됩니다.
QtQuick 임포트QtQuick.Controls.Basic 임포트Dial { id: 컨트롤 배경: 직사각형 { x: control.width / 2 - 너비 / 2 y: control.height / 2 - 높이 / 2 implicitWidth: 140 implicitHeight: 140 width: Math.max(64, Math.min(control.width, control.height)) height: width color: "투명" radius: width / 2 border.color: control.pressed? "#17a81a": "#21be2b" opacity: control.enabled? 1: 0.3} 핸들: 직사각형 { id: handleItemx : control.background.x + control.background.width / 2 - 너비 / 2y : control.background.y + control.background.height / 2 - 높이 / 2 너비: 16 높이: 16 color: control.pressed? "#17a81a": "#21be2b" radius: 8 앤티앨리어싱: true 불투명도: control.enabled? 1: 0.3 변형: [ Translate { y: -Math.min(control.background.width, control.background.height) * 0.4 + handleItem.height / 2}, Rotation { angle: control.angle origin.x: handleItem.width / 2 origin.y: handleItem.height / 2} ] } }
서랍 커스터마이징하기
드로어에는 시각적 background 항목이 있을 수 있습니다.
background: Rectangle { Rectangle { x: parent.width - 1 width: 1 height: parent.height color: "#21be2b" } }
프레임 사용자 지정하기
프레임은 하나의 시각적 항목으로 구성됩니다: background.
import QtQuick import QtQuick.Controls.Basic Frame { background: Rectangle { color: "transparent" border.color: "#21be2b" radius: 2 } Label { text: qsTr("Content goes here!") } }
GroupBox 사용자 지정하기
GroupBox 는 background 와 label 두 개의 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic GroupBox { id: control title: qsTr("GroupBox") background: Rectangle { y: control.topPadding - control.bottomPadding width: parent.width height: parent.height - control.topPadding + control.bottomPadding color: "transparent" border.color: "#21be2b" radius: 2 } label: Label { x: control.leftPadding width: control.availableWidth text: control.title color: "#21be2b" elide: Text.ElideRight } Label { text: qsTr("Content goes here!") } }
ItemDelegate 커스터마이징하기
ItemDelegate 는 background 와 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ItemDelegate { id: control text: qsTr("ItemDelegate") contentItem: Text { rightPadding: control.spacing text: control.text font: control.font color: control.enabled ? (control.down ? "#17a81a" : "#21be2b") : "#bdbebf" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitWidth: 100 implicitHeight: 40 opacity: enabled ? 1 : 0.3 color: control.down ? "#dddedf" : "#eeeeee" Rectangle { width: parent.width height: 1 color: control.down ? "#17a81a" : "#21be2b" anchors.bottom: parent.bottom } } }
레이블 사용자 지정하기
레이블에는 시각적 background 항목이 있을 수 있습니다.
import QtQuick import QtQuick.Controls.Basic Label { text: qsTr("Label") color: "#21be2b" }
메뉴 사용자 지정하기
- Menu 는 시각적 background 항목으로 구성됩니다.
- MenuItem 는 네 가지 시각적 항목으로 구성됩니다: background, content item, indicator, arrow.
- MenuSeparator 비주얼 background 과 content item 으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic Menu { id: menu Action { text: qsTr("Tool Bar"); checkable: true } Action { text: qsTr("Side Bar"); checkable: true; checked: true } Action { text: qsTr("Status Bar"); checkable: true; checked: true } MenuSeparator { contentItem: Rectangle { implicitWidth: 200 implicitHeight: 1 color: "#21be2b" } } Menu { title: qsTr("Advanced") // ... } topPadding: 2 bottomPadding: 2 delegate: MenuItem { id: menuItem implicitWidth: 200 implicitHeight: 40 arrow: Canvas { x: parent.width - width implicitWidth: 40 implicitHeight: 40 visible: menuItem.subMenu onPaint: { var ctx = getContext("2d") ctx.fillStyle = menuItem.highlighted ? "#ffffff" : "#21be2b" ctx.moveTo(15, 15) ctx.lineTo(width - 15, height / 2) ctx.lineTo(15, height - 15) ctx.closePath() ctx.fill() } } indicator: Item { implicitWidth: 40 implicitHeight: 40 Rectangle { width: 26 height: 26 anchors.centerIn: parent visible: menuItem.checkable border.color: "#21be2b" radius: 3 Rectangle { width: 14 height: 14 anchors.centerIn: parent visible: menuItem.checked color: "#21be2b" radius: 2 } } } contentItem: Text { leftPadding: menuItem.indicator.width rightPadding: menuItem.arrow.width text: menuItem.text font: menuItem.font opacity: enabled ? 1.0 : 0.3 color: menuItem.highlighted ? "#ffffff" : "#21be2b" horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 200 implicitHeight: 40 opacity: enabled ? 1 : 0.3 color: menuItem.highlighted ? "#21be2b" : "transparent" } } background: Rectangle { implicitWidth: 200 implicitHeight: 40 color: "#ffffff" border.color: "#21be2b" radius: 2 } }
메뉴바 커스터마이징하기
MenuBar 는 시각적 background 항목을 가질 수 있으며 MenuBarItem 은 background 과 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic MenuBar { id: menuBar Menu { title: qsTr("File") } Menu { title: qsTr("Edit") } Menu { title: qsTr("View") } Menu { title: qsTr("Help") } delegate: MenuBarItem { id: menuBarItem contentItem: Text { text: menuBarItem.text font: menuBarItem.font opacity: enabled ? 1.0 : 0.3 color: menuBarItem.highlighted ? "#ffffff" : "#21be2b" horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 40 implicitHeight: 40 opacity: enabled ? 1 : 0.3 color: menuBarItem.highlighted ? "#21be2b" : "transparent" } } background: Rectangle { implicitWidth: 40 implicitHeight: 40 color: "#ffffff" Rectangle { color: "#21be2b" width: parent.width height: 1 anchors.bottom: parent.bottom } } }
페이지 표시기 사용자 지정하기
PageIndicator 는 background, content item, delegate 로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic PageIndicator { id: control count: 5 currentIndex: 2 delegate: Rectangle { implicitWidth: 8 implicitHeight: 8 radius: width / 2 color: "#21be2b" opacity: index === control.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 required property int index Behavior on opacity { OpacityAnimator { duration: 100 } } } }
창 사용자 지정하기
창은 background 으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic Pane { background: Rectangle { color: "#eeeeee" } Label { text: qsTr("Content goes here!") } }
팝업 사용자 지정
팝업은 background 과 content item 으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic Popup { id: popup background: Rectangle { implicitWidth: 200 implicitHeight: 200 border.color: "#444" } contentItem: Column {} }
진행률 표시줄 사용자 지정하기
ProgressBar 는 background 와 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ProgressBar { id: control value: 0.5 padding: 2 background: Rectangle { implicitWidth: 200 implicitHeight: 6 color: "#e6e6e6" radius: 3 } contentItem: Item { implicitWidth: 200 implicitHeight: 4 // Progress indicator for determinate state. Rectangle { width: control.visualPosition * parent.width height: parent.height radius: 2 color: "#17a81a" visible: !control.indeterminate } // Scrolling animation for indeterminate state. Item { anchors.fill: parent visible: control.indeterminate clip: true Row { spacing: 20 Repeater { model: control.width / 40 + 1 Rectangle { color: "#17a81a" width: 20 height: control.height } } XAnimator on x { from: 0 to: -40 loops: Animation.Infinite running: control.indeterminate } } } } }
위에서는 콘텐츠 항목에 애니메이션을 적용하여 indeterminate 진행률 표시줄 상태를 나타냅니다.
라디오 버튼 사용자 지정
RadioButton 은 세 가지 시각적 항목으로 구성됩니다: background, content item 및 indicator 입니다.
import QtQuick import QtQuick.Controls.Basic RadioButton { id: control text: qsTr("RadioButton") checked: true indicator: Rectangle { implicitWidth: 26 implicitHeight: 26 x: control.leftPadding y: parent.height / 2 - height / 2 radius: 13 border.color: control.down ? "#17a81a" : "#21be2b" Rectangle { width: 14 height: 14 x: 6 y: 6 radius: 7 color: control.down ? "#17a81a" : "#21be2b" visible: control.checked } } contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" verticalAlignment: Text.AlignVCenter leftPadding: control.indicator.width + control.spacing } }
라디오 델리게이트 커스터마이징
RadioDelegate 는 세 가지 시각적 항목으로 구성됩니다: background, contentItem 및 indicator.
import QtQuick import QtQuick.Controls.Basic RadioDelegate { id: control text: qsTr("RadioDelegate") checked: true contentItem: Text { rightPadding: control.indicator.width + control.spacing text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } indicator: Rectangle { implicitWidth: 26 implicitHeight: 26 x: control.width - width - control.rightPadding y: parent.height / 2 - height / 2 radius: 13 color: "transparent" border.color: control.down ? "#17a81a" : "#21be2b" Rectangle { width: 14 height: 14 x: 6 y: 6 radius: 7 color: control.down ? "#17a81a" : "#21be2b" visible: control.checked } } background: Rectangle { implicitWidth: 100 implicitHeight: 40 visible: control.down || control.highlighted color: control.down ? "#bdbebf" : "#eeeeee" } }
범위 슬라이더 커스터마이징
RangeSlider 는 세 가지 시각적 항목으로 구성됩니다: background, first.handle 및 second.handle.
import QtQuick import QtQuick.Controls.Basic RangeSlider { id: control first.value: 0.25 second.value: 0.75 background: Rectangle { x: control.leftPadding y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 200 implicitHeight: 4 width: control.availableWidth height: implicitHeight radius: 2 color: "#bdbebf" Rectangle { x: control.first.visualPosition * parent.width width: control.second.visualPosition * parent.width - x height: parent.height color: "#21be2b" radius: 2 } } first.handle: Rectangle { x: control.leftPadding + control.first.visualPosition * (control.availableWidth - width) y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 26 implicitHeight: 26 radius: 13 color: control.first.pressed ? "#f0f0f0" : "#f6f6f6" border.color: "#bdbebf" } second.handle: Rectangle { x: control.leftPadding + control.second.visualPosition * (control.availableWidth - width) y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 26 implicitHeight: 26 radius: 13 color: control.second.pressed ? "#f0f0f0" : "#f6f6f6" border.color: "#bdbebf" } }
라운드 버튼 사용자 지정
RoundButton 은 버튼과 같은 방식으로 사용자 정의할 수 있습니다.
스크롤바 사용자 지정
ScrollBar 는 background 과 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ScrollBar { id: control size: 0.3 position: 0.2 active: true orientation: Qt.Vertical contentItem: Rectangle { implicitWidth: 6 implicitHeight: 100 radius: width / 2 color: control.pressed ? "#81e889" : "#c2f4c6" // Hide the ScrollBar when it's not needed. opacity: control.policy === ScrollBar.AlwaysOn || (control.active && control.size < 1.0) ? 0.75 : 0 // Animate the changes in opacity (default duration is 250 ms). Behavior on opacity { NumberAnimation {} } } }
스크롤 표시기 사용자 지정
ScrollIndicator 는 background 과 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ScrollIndicator { id: control size: 0.3 position: 0.2 active: true orientation: Qt.Vertical contentItem: Rectangle { implicitWidth: 2 implicitHeight: 100 color: "#c2f4c6" } }
스크롤뷰 사용자 지정
ScrollView 는 background 항목과 가로 및 세로 스크롤 막대로 구성됩니다.
ScrollView { id: control width: 200 height: 200 focus: true Label { text: "ABC" font.pixelSize: 224 } ScrollBar.vertical: ScrollBar { parent: control x: control.mirrored ? 0 : control.width - width y: control.topPadding height: control.availableHeight active: control.ScrollBar.horizontal.active } ScrollBar.horizontal: ScrollBar { parent: control x: control.leftPadding y: control.height - height width: control.availableWidth active: control.ScrollBar.vertical.active } background: Rectangle { border.color: control.activeFocus ? "#21be2b" : "#bdbebf" } }
슬라이더 사용자 지정하기
슬라이더는 두 개의 시각적 항목으로 구성됩니다: background 및 handle.
import QtQuick import QtQuick.Controls.Basic Slider { id: control value: 0.5 background: Rectangle { x: control.leftPadding y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 200 implicitHeight: 4 width: control.availableWidth height: implicitHeight radius: 2 color: "#bdbebf" Rectangle { width: control.visualPosition * parent.width height: parent.height color: "#21be2b" radius: 2 } } handle: Rectangle { x: control.leftPadding + control.visualPosition * (control.availableWidth - width) y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 26 implicitHeight: 26 radius: 13 color: control.pressed ? "#f0f0f0" : "#f6f6f6" border.color: "#bdbebf" } }
스핀박스 사용자 지정
SpinBox 는 네 가지 시각적 항목으로 구성됩니다: background, contentItem, up indicator, down indicator.
import QtQuick import QtQuick.Controls.Basic SpinBox { id: control value: 50 editable: true contentItem: TextInput { z: 2 text: control.textFromValue(control.value, control.locale) font: control.font color: "#21be2b" selectionColor: "#21be2b" selectedTextColor: "#ffffff" horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter readOnly: !control.editable validator: control.validator inputMethodHints: Qt.ImhFormattedNumbersOnly } up.indicator: Rectangle { x: control.mirrored ? 0 : parent.width - width height: parent.height implicitWidth: 40 implicitHeight: 40 color: control.up.pressed ? "#e4e4e4" : "#f6f6f6" border.color: enabled ? "#21be2b" : "#bdbebf" Text { text: "+" font.pixelSize: control.font.pixelSize * 2 color: "#21be2b" anchors.fill: parent fontSizeMode: Text.Fit horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } } down.indicator: Rectangle { x: control.mirrored ? parent.width - width : 0 height: parent.height implicitWidth: 40 implicitHeight: 40 color: control.down.pressed ? "#e4e4e4" : "#f6f6f6" border.color: enabled ? "#21be2b" : "#bdbebf" Text { text: "-" font.pixelSize: control.font.pixelSize * 2 color: "#21be2b" anchors.fill: parent fontSizeMode: Text.Fit horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } } background: Rectangle { implicitWidth: 140 border.color: "#bdbebf" } }
SplitView 사용자 지정
SplitView 는 시각적 handle 델리게이트로 구성됩니다.
SplitView { id: splitView anchors.fill: parent handle: Rectangle { implicitWidth: 4 implicitHeight: 4 color: SplitHandle.pressed ? "#81e889" : (SplitHandle.hovered ? Qt.lighter("#c2f4c6", 1.1) : "#c2f4c6") } Rectangle { implicitWidth: 150 color: "#444" } Rectangle { implicitWidth: 50 color: "#666" } }
스택뷰 사용자 지정하기
StackView 는 시각적 background 항목을 가질 수 있으며 푸시, 팝, 바꾸기 작업에 사용되는 전환을 사용자 지정할 수 있습니다.
import QtQuick import QtQuick.Controls.Basic StackView { id: control popEnter: Transition { XAnimator { from: (control.mirrored ? -1 : 1) * -control.width to: 0 duration: 400 easing.type: Easing.OutCubic } } popExit: Transition { XAnimator { from: 0 to: (control.mirrored ? -1 : 1) * control.width duration: 400 easing.type: Easing.OutCubic } } }
스와이프 델리게이트 사용자 지정
SwipeDelegate 는 6개의 시각적 항목으로 구성됩니다: background, content item, indicator, swipe.left
, swipe.right
, 그리고 swipe.behind
입니다.
import QtQuick import QtQuick.Controls.Basic SwipeDelegate { id: control text: qsTr("SwipeDelegate") Component { id: component Rectangle { color: SwipeDelegate.pressed ? "#333" : "#444" width: parent.width height: parent.height clip: true Label { text: qsTr("Press me!") color: "#21be2b" anchors.centerIn: parent } } } swipe.left: component swipe.right: component contentItem: Text { text: control.text font: control.font color: control.enabled ? (control.down ? "#17a81a" : "#21be2b") : "#bdbebf" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter Behavior on x { enabled: !control.down NumberAnimation { easing.type: Easing.InOutCubic duration: 400 } } } }
스와이프뷰 사용자 지정
SwipeView 는 시각적 background 항목을 가질 수 있습니다. 탐색은 content item 으로 구현됩니다.
import QtQuick import QtQuick.Controls.Basic SwipeView { id: control background: Rectangle { color: "#eeeeee" } }
스위치 사용자 지정
스위치는 세 가지 시각적 항목으로 구성됩니다: background, content item 및 indicator 입니다.
import QtQuick import QtQuick.Controls.Basic Switch { id: control text: qsTr("Switch") indicator: Rectangle { implicitWidth: 48 implicitHeight: 26 x: control.leftPadding y: parent.height / 2 - height / 2 radius: 13 color: control.checked ? "#17a81a" : "#ffffff" border.color: control.checked ? "#17a81a" : "#cccccc" Rectangle { x: control.checked ? parent.width - width : 0 width: 26 height: 26 radius: 13 color: control.down ? "#cccccc" : "#ffffff" border.color: control.checked ? (control.down ? "#17a81a" : "#21be2b") : "#999999" } } contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" verticalAlignment: Text.AlignVCenter leftPadding: control.indicator.width + control.spacing } }
스위치 델리게이트 커스터마이징
SwitchDelegate 는 세 가지 시각적 항목으로 구성됩니다: background, contentItem 및 indicator.
import QtQuick import QtQuick.Controls.Basic SwitchDelegate { id: control text: qsTr("SwitchDelegate") checked: true contentItem: Text { rightPadding: control.indicator.width + control.spacing text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } indicator: Rectangle { implicitWidth: 48 implicitHeight: 26 x: control.width - width - control.rightPadding y: parent.height / 2 - height / 2 radius: 13 color: control.checked ? "#17a81a" : "transparent" border.color: control.checked ? "#17a81a" : "#cccccc" Rectangle { x: control.checked ? parent.width - width : 0 width: 26 height: 26 radius: 13 color: control.down ? "#cccccc" : "#ffffff" border.color: control.checked ? (control.down ? "#17a81a" : "#21be2b") : "#999999" } } background: Rectangle { implicitWidth: 100 implicitHeight: 40 visible: control.down || control.highlighted color: control.down ? "#bdbebf" : "#eeeeee" } }
탭바 커스터마이징
TabBar 는 두 개의 시각적 항목으로 구성됩니다: background 와 contentItem 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic TabBar { id: control background: Rectangle { color: "#eeeeee" } TabButton { text: qsTr("Home") } TabButton { text: qsTr("Discover") } TabButton { text: qsTr("Activity") } }
탭 버튼 사용자 지정
TabButton 은 버튼과 동일한 방식으로 사용자 정의할 수 있습니다.
텍스트 영역 사용자 지정
TextArea 는 background 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic TextArea { id: control placeholderText: qsTr("Enter description") background: Rectangle { implicitWidth: 200 implicitHeight: 40 border.color: control.enabled ? "#21be2b" : "transparent" } }
텍스트 필드 사용자 지정
TextField 는 background 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic TextField { id: control placeholderText: qsTr("Enter description") background: Rectangle { implicitWidth: 200 implicitHeight: 40 color: control.enabled ? "transparent" : "#353637" border.color: control.enabled ? "#21be2b" : "transparent" } }
도구 모음 사용자 지정
ToolBar 는 하나의 시각적 항목으로 구성됩니다: background.
ToolBar { id: control background: Rectangle { implicitHeight: 40 color: "#eeeeee" Rectangle { width: parent.width height: 1 anchors.bottom: parent.bottom color: "transparent" border.color: "#21be2b" } } RowLayout { anchors.fill: parent ToolButton { text: qsTr("Undo") } ToolButton { text: qsTr("Redo") } } }
도구 버튼 사용자 지정
ToolButton 은 background 과 content item 두 개의 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ToolButton { id: control text: qsTr("ToolButton") width: 120 contentItem: Text { text: control.text font: control.font opacity: enabled ? 1.0 : 0.3 color: control.down ? "#17a81a" : "#21be2b" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } background: Rectangle { implicitWidth: 40 implicitHeight: 40 color: Qt.darker("#33333333", control.enabled && (control.checked || control.highlighted) ? 1.5 : 1.0) opacity: enabled ? 1 : 0.3 visible: control.down || (control.enabled && (control.checked || control.highlighted)) } }
도구 분리기 사용자 지정
ToolSeparator 는 background 과 content item 의 두 가지 시각적 항목으로 구성됩니다.
ToolBar { RowLayout { anchors.fill: parent ToolButton { text: qsTr("Action 1") } ToolButton { text: qsTr("Action 2") } ToolSeparator { padding: vertical ? 10 : 2 topPadding: vertical ? 2 : 10 bottomPadding: vertical ? 2 : 10 contentItem: Rectangle { implicitWidth: parent.vertical ? 1 : 24 implicitHeight: parent.vertical ? 24 : 1 color: "#c3c3c3" } } ToolButton { text: qsTr("Action 3") } ToolButton { text: qsTr("Action 4") } Item { Layout.fillWidth: true } } }
툴팁 커스터마이징
ToolTip 는 background 과 content item 의 두 가지 시각적 항목으로 구성됩니다.
import QtQuick import QtQuick.Controls.Basic ToolTip { id: control text: qsTr("A descriptive tool tip of what the button does") contentItem: Text { text: control.text font: control.font color: "#21be2b" } background: Rectangle { border.color: "#21be2b" } }
참고: attached ToolTip 을 사용자 지정하려면 자신만의 스타일로 제공해야 합니다. ToolTip
을 일회성으로 사용자 지정하려면 Custom Tool Tips 을 참조하세요.
텀블러 사용자 지정
텀블러는 세 가지 시각적 항목으로 구성됩니다: background, contentItem, delegate 입니다.
import QtQuick import QtQuick.Controls.Basic Tumbler { id: control model: 15 background: Item { Rectangle { opacity: control.enabled ? 0.2 : 0.1 border.color: "#000000" width: parent.width height: 1 anchors.top: parent.top } Rectangle { opacity: control.enabled ? 0.2 : 0.1 border.color: "#000000" width: parent.width height: 1 anchors.bottom: parent.bottom } } delegate: Text { text: qsTr("Item %1").arg(modelData + 1) font: control.font horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter opacity: 1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2) required property var modelData required property int index } Rectangle { anchors.horizontalCenter: control.horizontalCenter y: control.height * 0.4 width: 40 height: 1 color: "#21be2b" } Rectangle { anchors.horizontalCenter: control.horizontalCenter y: control.height * 0.6 width: 40 height: 1 color: "#21be2b" } }
고유한 콘텐츠 항목을 정의하려면 ListView 또는 PathView 을 루트 항목으로 사용합니다. 래핑 텀블러의 경우 PathView 을 사용합니다:
Tumbler { id: tumbler contentItem: PathView { id: pathView model: tumbler.model delegate: tumbler.delegate clip: true pathItemCount: tumbler.visibleItemCount + 1 preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 dragMargin: width / 2 path: Path { startX: pathView.width / 2 startY: -pathView.delegateHeight / 2 PathLine { x: pathView.width / 2 y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2 } } property real delegateHeight: tumbler.availableHeight / tumbler.visibleItemCount } }
포장하지 않는 텀블러의 경우 ListView 을 사용합니다:
Tumbler { id: tumbler contentItem: ListView { model: tumbler.model delegate: tumbler.delegate snapMode: ListView.SnapToItem highlightRangeMode: ListView.StrictlyEnforceRange preferredHighlightBegin: height / 2 - (height / tumbler.visibleItemCount / 2) preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2) clip: true } }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.