CSSやJavaScriptのような宣言型プログラミング言語であるQt QMLで、どのようにユーザーインターフェイスのプロトタイプを作成、変更できるのか、ゼロインスト―ルでテストしましょう!
Qt QMLは、クロスプラットフォームに対応するC ++およびPythonによるQt アプリケーションを、高い生産性と簡単なUI開発が実現できるように設計されています。
このインタラクティブなWebAssemblyベースの「Qtオンラインコーディングアプリ」では、オンラインエディターで実行できる典型的なスクリプト構文と複数のコーディング例をご紹介しています。
これらのサンプルでは、わずか数行のQt QMLコードで、フレキシブルなユーザーエクスペリエンスを容易に作成し、デザインを簡単にコーディングできることをご覧いただけます。右のプルダウンメニューからワンクリックでサンプルを実行できます。
あらゆる形のアイコンベースのメニューも簡単に作成することが可能です。パスプロパティを変更してアイコンをぼかしたり拡大縮小したり、パスコントロールポイントを変更してパスの形状を変更することができます。
QMLでは、いろいろな種類のアニメーションを提供します。これにより、わずか数行のコードでフレキシブルなアニメーションを作成できます。
Qt Quick Controlsは、ユーザーインターフェイスの重要な構成要素です。 UIのニーズに合わせてコントロールを作成およびカスタマイズするのがいかに簡単かご覧いただけます。
UIコントロールは、基本的なQMLタイプから作成することができます。この例では、非常に基本的なQMLタイプから作成されたダイヤルゲージを示しています。
QMLには、既製の2Dおよび3Dチャートタイプにも、豊富なコントロールがあります。静的または動的なデータ用に3Dバーまたはサーフェスでデータをレンダリングするための便利な方法をご利用いただけます。
次のCandy cracsherを作るのはあなたかも…?単純なゲームを作成する場合でも、数行のQMLコードで実現することができます。
これらのサンプルでは、わずか数行のQt QMLコードで、フレキシブルなユーザーエクスペリエンスを容易に作成し、デザインを簡単にコーディングできることをご覧いただけます。右のプルダウンメニューからワンクリックでサンプルを実行できます。
import QtQuick 2.3
Rectangle {
width: 200
height: 100
color: "#090F2A"
Text {
anchors.centerIn: parent
text: "Hello, World!"
color: "#fff"
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQuick.Window 2.2
Window {
id: rootWindow
title: qsTr("Smart home")
width: 640; height: 400
visible: true
color: "white"
// The background consists of two active buttons to switch the ViewSection
// between a grid and path view.
Image {
id: background
width: 640
height: 400
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/qt-demo-screen-white.png"
// Button Qt Quick Control could be used instead of Image. There is another Qt Quick Control example.
Image {
id: gridButtonImage
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/interface.png"
width: 20 // We want to have a fixed size for the image
height: width
anchors { top: background.top; left: background.left; topMargin: 12; leftMargin: 50 }
TapHandler {
onTapped: pathView.visible = false;
}
}
Image {
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/balls.png"
width: gridButtonImage.width
height: width
anchors { top: background.top; left: background.left; topMargin: 12; leftMargin: 85 }
TapHandler {
onTapped: pathView.visible = true;
}
}
}
// ListModel provides images, shared between the grid and path views.
ListModel {
id: imageModel
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/door.png"
}
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/home.png"
}
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/power.png"
}
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/signs.png"
}
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/tool.png"
}
ListElement {
file: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/smartHome/weapons.png"
}
}
// Delegate is used by the views to render the model items
Component {
id: pathViewDelegate
Image {
opacity: PathView.opacity
scale: PathView.scale
z: PathView.z
source: file
width: 64
height: 64
fillMode: Image.PreserveAspectFit
}
}
Component {
id: gridViewDelegate
Image {
source: file
width: 64
height: 64
fillMode: Image.PreserveAspectFit
TapHandler {
onLongPressed: scale = (scale === 1.5) ? 1.0 : 1.5;
}
Behavior on scale {
NumberAnimation { }
}
}
}
Component {
id: hightlightRectangle
Rectangle {
radius: 4
color: "transparent"
border { width: 2; color: "lightgreen" }
width: 64 + 4
height: width
visible: PathView.onPath
}
}
GridView {
id: gridView
visible: !pathView.visible
anchors.centerIn: parent
width: parent.width * 0.5
height: parent.height * 0.5
model: imageModel
delegate: gridViewDelegate
}
PathView {
id: pathView
anchors.centerIn: parent
width: parent.width * 0.8
height: parent.height * 0.8
model: imageModel
delegate: pathViewDelegate
visible: true
highlight: hightlightRectangle
path: Path {
startX: 208; startY: 265
PathAttribute { name: "opacity"; value: 1.0 }
PathAttribute { name: "scale"; value: 1.0 }
PathAttribute { name: "z"; value: 0 }
PathCubic { x: 37; y: 142; control1X: 139; control1Y: 250
control2X: 53; control2Y: 237 }
PathAttribute { name: "opacity"; value: 0.5 }
PathAttribute { name: "scale"; value: 0.5 }
PathAttribute { name: "z"; value: -1 }
PathCubic { x: 94; y: 59; control1X: 41.1; control1Y: 117.1
control2X: 60.9; control2Y: 77.9 }
PathAttribute { name: "opacity"; value: 0.25 }
PathAttribute { name: "scale"; value: 0.25 }
PathAttribute { name: "z"; value: -2 }
PathCubic { x: 364; y: 56; control1X: 161.9; control1Y: 32.6
control2X: 274.1; control2Y: 25.4 }
PathAttribute { name: "opacity"; value: 0.5 }
PathAttribute { name: "scale"; value: 0.5 }
PathAttribute { name: "z"; value: -1 }
PathCubic { x: 208; y: 265; control1X: 478.4; control1Y: 152.3
control2X: 409.6; control2Y: 277.7 }
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQuick.Window 2.2
Window {
title: qsTr("SmoothAnimations")
id: window
width: 640
height: 480
visible: true
// Background
Image {
x: 0
y: 0
width: parent.width
height: parent.height
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/animations/rocketpath.png"
}
AnimatedSprite {
id: animatedSprite
width: parent.width * 0.1
height: parent.height * 0.1
anchors { top: parent.top; topMargin: 20; right: parent.right; rightMargin: 20 }
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/animations/snowflake.png"
frameCount: 51 // Frame width automatically calculated
frameDuration: 10
running: false
TapHandler {
onTapped: animatedSprite.running = !animatedSprite.running;
}
}
Item {
id: rocket
width: 128; height: 96
Image {
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/animations/rocket.png"
anchors.centerIn: parent
rotation: 90
}
TapHandler {
onTapped: pathAnimation.running = !pathAnimation.running
}
}
PathAnimation {
id: pathAnimation
duration: 2000
easing.type: Easing.InOutQuad
loops: 1
target: rocket
orientation: PathAnimation.RightFirst
anchorPoint: Qt.point(rocket.width/2, rocket.height/2)
path: Path {
startX: rocket.width/2; startY: rocket.height/2
PathCubic {
x: window.width - rocket.width/2
y: window.height - rocket.height/2
control1X: x; control1Y: rocket.height/2
control2X: rocket.width/2; control2Y: y
}
PathCubic {
x: window.width - rocket.width/2
y: window.height - rocket.height/2
control1X: x; control1Y: rocket.height/2
control2X: rocket.width/2; control2Y: y
}
}
}
Image {
id: img
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/animations/face-smile.png"
anchors.horizontalCenter: parent.horizontalCenter
TapHandler {
onTapped: bounceAnimation.running = !bounceAnimation.running
}
SequentialAnimation on y {
id: bounceAnimation
running: false
loops: 1
YAnimator {
easing.amplitude: 1.6
to: window.height-img.height; easing.type: Easing.InOutElastic; duration: 2000
}
PauseAnimation { duration: 1000 }
YAnimator {
to: 0; easing.type: Easing.OutQuad; duration: 1000
}
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14
import QtQuick.Controls.Material 2.14
import QtQuick.Controls.Universal 2.14
ApplicationWindow {
id: window
width: 360
height: 520
visible: true
title: "Qt Quick Controls Gallery"
Shortcut {
sequences: ["Esc", "Back"]
enabled: stackView.depth > 1
onActivated: navigateBackAction.trigger()
}
Action {
id: navigateBackAction
icon.source: stackView.depth > 1 ? "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/back.png" : "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/drawer.png"
onTriggered: {
if (stackView.depth > 1) {
stackView.pop()
listView.currentIndex = -1
} else {
drawer.open()
}
}
}
Shortcut {
sequence: "Menu"
onActivated: optionsMenuAction.trigger()
}
Action {
id: optionsMenuAction
icon.source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/menu.png"
onTriggered: optionsMenu.open()
}
header: ToolBar {
Material.foreground: "white"
RowLayout {
spacing: 20
anchors.fill: parent
ToolButton {
action: navigateBackAction
}
Label {
id: titleLabel
text: listView.currentItem ? listView.currentItem.text : "Gallery"
font.pixelSize: 20
elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
}
ToolButton {
action: optionsMenuAction
Menu {
id: optionsMenu
x: parent.width - width
transformOrigin: Menu.TopRight
Action {
text: "About"
onTriggered: aboutDialog.open()
}
}
}
}
}
Drawer {
id: drawer
width: Math.min(window.width, window.height) / 3 * 2
height: window.height
interactive: stackView.depth === 1
ListView {
id: listView
focus: true
currentIndex: -1
anchors.fill: parent
delegate: ItemDelegate {
width: parent.width
text: model.title
highlighted: ListView.isCurrentItem
onClicked: {
listView.currentIndex = index
var pageId;
switch (model.source) {
case "busyIndicator":
pageId = busyIndicator;
break;
case "buttonPage":
pageId = buttonPage;
break;
case "checkboxPage":
pageId = checkboxPage;
break;
case "comboboxPage":
pageId = comboboxPage;
break;
case "delayButtonPage":
pageId = delayButtonPage;
break;
case "dialPage":
pageId = dialPage;
break;
case "dialogPage":
pageId = dialogPage;
break;
case "delegatePage":
pageId = delegatePage;
break;
case "framePage":
pageId = framePage;
break;
case "groupBoxPage":
pageId = groupBoxPage;
break;
case "pageIndicatorPage":
pageId = pageIndicatorPage;
break;
case "progressBarPage":
pageId = progressBarPage;
break;
case "radioButtonPage":
pageId = radioButtonPage;
break;
case "rangeSliderPage":
pageId = rangeSliderPage;
break;
case "scrollBarPage":
pageId = scrollBarPage;
break;
case "scrollIndicatorPage":
pageId = scrollIndicatorPage;
break;
case "sliderPage":
pageId = sliderPage;
break;
case "spinBoxPage":
pageId = spinBoxPage;
break;
case "stackViewPage":
pageId = stackViewPage;
break;
case "swipeViewPage":
pageId = swipeViewPage;
break;
case "switchPage":
pageId = switchPage;
break;
case "tabBarPage":
pageId = tabBarPage;
break;
case "toolTipPage":
pageId = toolTipPage;
break;
default:
pageId = tumblerPage;
break;
}
stackView.push(pageId)
drawer.close()
}
}
model: ListModel {
ListElement { title: "BusyIndicator"; source: "busyIndicator" }
ListElement { title: "Button"; source: "buttonPage" }
ListElement { title: "CheckBox"; source: "checkboxPage" }
ListElement { title: "ComboBox"; source: "comboboxPage" }
ListElement { title: "DelayButton"; source: "delayButtonPage" }
ListElement { title: "Dial"; source: "dialPage" }
ListElement { title: "Dialog"; source: "dialogPage" }
ListElement { title: "Delegates"; source: "delegatePage" }
ListElement { title: "Frame"; source: "framePage" }
ListElement { title: "GroupBox"; source: "groupBoxPage" }
ListElement { title: "PageIndicator"; source: "pageIndicatorPage" }
ListElement { title: "ProgressBar"; source: "progressBarPage" }
ListElement { title: "RadioButton"; source: "radioButtonPage" }
ListElement { title: "RangeSlider"; source: "rangeSliderPage" }
ListElement { title: "ScrollBar"; source: "scrollBarPage" }
ListElement { title: "ScrollIndicator"; source: "scrollIndicatorPage" }
ListElement { title: "Slider"; source: "sliderPage" }
ListElement { title: "SpinBox"; source: "spinBoxPage" }
ListElement { title: "StackView"; source: "stackViewPage" }
ListElement { title: "SwipeView"; source: "swipeViewPage" }
ListElement { title: "Switch"; source: "switchPage" }
ListElement { title: "TabBar"; source: "tabBarPage" }
ListElement { title: "ToolTip"; source: "toolTipPage" }
ListElement { title: "Tumbler"; source: "tumblerPage" }
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
StackView {
id: stackView
anchors.fill: parent
initialItem: Pane {
id: pane
Image {
id: logo
width: pane.availableWidth / 2
height: pane.availableHeight / 2
anchors.centerIn: parent
anchors.verticalCenterOffset: -50
fillMode: Image.PreserveAspectFit
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/qt-logo.png"
}
Label {
text: "Qt Quick Controls 2 provides a set of controls that can be used to build complete interfaces in Qt Quick."
anchors.margins: 20
anchors.top: logo.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: arrow.top
horizontalAlignment: Label.AlignHCenter
verticalAlignment: Label.AlignVCenter
wrapMode: Label.Wrap
}
Image {
id: arrow
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/arrow.png"
anchors.left: parent.left
anchors.bottom: parent.bottom
}
}
}
Dialog {
id: aboutDialog
modal: true
focus: true
title: "About"
x: (window.width - width) / 2
y: window.height / 6
width: Math.min(window.width, window.height) / 3 * 2
contentHeight: aboutColumn.height
Column {
id: aboutColumn
spacing: 20
Label {
width: aboutDialog.availableWidth
text: "The Qt Quick Controls 2 module delivers the next generation user interface controls based on Qt Quick."
wrapMode: Label.Wrap
font.pixelSize: 12
}
Label {
width: aboutDialog.availableWidth
text: "In comparison to the desktop-oriented Qt Quick Controls 1, Qt Quick Controls 2 "
+ "are an order of magnitude simpler, lighter and faster, and are primarily targeted "
+ "towards embedded and mobile platforms."
wrapMode: Label.Wrap
font.pixelSize: 12
}
}
}
Component {
id: busyIndicator
Page {
// Almost every page shares the following Flickable item.
// It should have been implemented as a shared component, but due to
// WebAssembly application limitations of editing multiple files,
// it has been been copied to each page.
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "BusyIndicator is used to indicate activity while content is being loaded,"
+ " or when the UI is blocked waiting for a resource to become available."
}
BusyIndicator {
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: buttonPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Button presents a push-button that can be pushed or clicked by the user. "
+ "Buttons are normally used to perform an action, or to answer a question."
}
ColumnLayout {
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
Button {
text: "First"
Layout.fillWidth: true
}
Button {
id: button
text: "Second"
highlighted: true
Layout.fillWidth: true
}
Button {
text: "Third"
enabled: false
Layout.fillWidth: true
}
}
}
}
}
Component {
id: checkboxPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "CheckBox presents an option button that can be toggled on or off. "
+ "Check boxes are typically used to select one or more options from a set of options."
}
Column {
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
CheckBox {
text: "First"
checked: true
}
CheckBox {
text: "Second"
}
CheckBox {
text: "Third"
checked: true
enabled: false
}
}
}
}
}
Component {
id: comboboxPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "ComboBox is a combined button and popup list. It presents "
+ "a list of options to the user that occupies minimal screen space."
}
ComboBox {
model: ["First", "Second", "Third"]
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "ComboBox can be made \l editable. An editable combo box auto-"
+ "completes its text based on what is available in the model."
}
ComboBox {
editable: true
model: ListModel {
id: model
ListElement { text: "Banana" }
ListElement { text: "Apple" }
ListElement { text: "Coconut" }
}
onAccepted: {
if (find(editText) === -1)
model.append({text: editText})
}
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: delayButtonPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "DelayButton is a checkable button that incorporates a delay before the "
+ "button is activated. This delay prevents accidental presses."
}
DelayButton {
text: "DelayButton"
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: dialPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "The Dial is similar to a traditional dial knob that is found on devices such as "
+ "stereos or industrial equipment. It allows the user to specify a value within a range."
}
Dial {
value: 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: dialogPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Dialog is a popup that is mostly used for short-term tasks "
+ "and brief communications with the user."
}
Button {
text: "Message"
anchors.horizontalCenter: parent.horizontalCenter
// width: buttonWidth
onClicked: messageDialog.open()
Dialog {
id: messageDialog
x: (parent.width - width) / 2
y: (parent.height - height) / 2
title: "Message"
Label {
text: "Lorem ipsum dolor sit amet..."
}
}
}
Button {
id: button
text: "Confirmation"
anchors.horizontalCenter: parent.horizontalCenter
// width: buttonWidth
onClicked: confirmationDialog.open()
Dialog {
id: confirmationDialog
x: (parent.width - width) / 2
y: (parent.height - height) / 2
parent: Overlay.overlay
modal: true
title: "Confirmation"
standardButtons: Dialog.Yes | Dialog.No
Column {
spacing: 20
anchors.fill: parent
Label {
text: "The document has been modified.\nDo you want to save your changes?"
}
CheckBox {
text: "Do not ask again"
anchors.right: parent.right
}
}
}
}
Button {
text: "Content"
anchors.horizontalCenter: parent.horizontalCenter
// width: buttonWidth
onClicked: contentDialog.open()
Dialog {
id: contentDialog
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: Math.min(dialogPage.width, dialogPage.height) / 3 * 2
contentHeight: logo.height * 2
parent: Overlay.overlay
modal: true
title: "Content"
standardButtons: Dialog.Close
Flickable {
id: flickable
clip: true
anchors.fill: parent
contentHeight: column.height
Column {
id: column
spacing: 20
width: parent.width
Image {
id: logo
width: parent.width / 2
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/qt-logo.png"
}
Label {
width: parent.width
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc finibus "
+ "in est quis laoreet. Interdum et malesuada fames ac ante ipsum primis "
+ "in faucibus. Curabitur eget justo sollicitudin enim faucibus bibendum. "
+ "Suspendisse potenti. Vestibulum cursus consequat mauris id sollicitudin. "
+ "Duis facilisis hendrerit consectetur. Curabitur sapien tortor, efficitur "
+ "id auctor nec, efficitur et nisl. Ut venenatis eros in nunc placerat, "
+ "eu aliquam enim suscipit."
wrapMode: Label.Wrap
}
}
ScrollIndicator.vertical: ScrollIndicator {
parent: contentDialog.contentItem
anchors.top: flickable.top
anchors.bottom: flickable.bottom
anchors.right: parent.right
anchors.rightMargin: -contentDialog.rightPadding + 1
}
}
}
}
Button {
text: "Input"
anchors.horizontalCenter: parent.horizontalCenter
// width: buttonWidth
onClicked: inputDialog.open()
Dialog {
id: inputDialog
x: (parent.width - width) / 2
y: (parent.height - height) / 2
parent: Overlay.overlay
focus: true
modal: true
title: "Input"
standardButtons: Dialog.Ok | Dialog.Cancel
ColumnLayout {
spacing: 20
anchors.fill: parent
Label {
elide: Label.ElideRight
text: "Please enter the credentials:"
Layout.fillWidth: true
}
TextField {
focus: true
placeholderText: "Username"
Layout.fillWidth: true
}
TextField {
placeholderText: "Password"
echoMode: TextField.PasswordEchoOnEdit
Layout.fillWidth: true
}
}
}
}
}
}
}
Component {
id: delegatePage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
property var delegateComponentMap: {
"ItemDelegate": itemDelegateComponent,
"SwipeDelegate": swipeDelegateComponent,
"CheckDelegate": checkDelegateComponent,
"RadioDelegate": radioDelegateComponent,
"SwitchDelegate": switchDelegateComponent
}
Component {
id: itemDelegateComponent
ItemDelegate {
text: labelText
width: parent.width
}
}
Component {
id: swipeDelegateComponent
SwipeDelegate {
id: swipeDelegate
text: labelText
width: parent.width
Component {
id: removeComponent
Rectangle {
color: SwipeDelegate.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
SwipeDelegate.onClicked: view.model.remove(ourIndex)
Label {
font.pixelSize: swipeDelegate.font.pixelSize
text: "Remove"
color: "white"
anchors.centerIn: parent
}
}
}
swipe.left: removeComponent
swipe.right: removeComponent
}
}
Component {
id: checkDelegateComponent
CheckDelegate {
text: labelText
width: parent.width
}
}
ButtonGroup {
id: radioButtonGroup
}
Component {
id: radioDelegateComponent
RadioDelegate {
text: labelText
ButtonGroup.group: radioButtonGroup
}
}
Component {
id: switchDelegateComponent
SwitchDelegate {
text: labelText
}
}
ColumnLayout {
id: column
spacing: 40
anchors.fill: parent
anchors.topMargin: 20
Label {
Layout.fillWidth: true
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Delegate controls are used as delegates in views such as ListView."
}
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: ListModel {
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
}
section.property: "type"
section.delegate: Pane {
width: listView.width
height: sectionLabel.implicitHeight + 20
Label {
id: sectionLabel
text: section
anchors.centerIn: parent
}
}
delegate: Loader {
id: delegateLoader
property string labelText: text
property ListView view: listView
property int ourIndex: index
width: listView.width
sourceComponent: delegateComponentMap[text]
// Can't find a way to do this in the SwipeDelegate component itself,
// so do it here instead.
ListView.onRemove: SequentialAnimation {
PropertyAction {
target: delegateLoader
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
target: item
property: "height"
to: 0
easing.type: Easing.InOutQuad
}
PropertyAction {
target: delegateLoader
property: "ListView.delayRemove"
value: false
}
}
}
}
}
}
}
Component {
id: framePage
Page {
id: _framePage
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
readonly property int itemWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 3, _framePage.availableWidth / 3 * 2))
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Frame is used to layout a logical group of controls together, within a visual frame."
}
Frame {
anchors.horizontalCenter: parent.horizontalCenter
Column {
spacing: 20
width: _framePage.itemWidth
RadioButton {
text: "First"
checked: true
width: parent.width
}
RadioButton {
id: button
text: "Second"
width: parent.width
}
RadioButton {
text: "Third"
width: parent.width
}
}
}
}
}
}
Component {
id: groupBoxPage
Page {
id: _groupBBoxPage
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
readonly property int itemWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 3, _groupBBoxPage.availableWidth / 3 * 2))
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "A GroupBox provides a frame, a title on top of it, and a logical group of controls within that frame."
}
GroupBox {
title: "Title"
anchors.horizontalCenter: parent.horizontalCenter
Column {
spacing: 20
width: _groupBBoxPage.itemWidth
RadioButton {
text: "First"
checked: true
width: parent.width
}
RadioButton {
id: button
text: "Second"
width: parent.width
}
RadioButton {
text: "Third"
width: parent.width
}
}
}
}
}
}
Component {
id: pageIndicatorPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "PageIndicator is used to indicate the currently active page in a container of pages."
}
PageIndicator {
count: 5
currentIndex: 2
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: progressBarPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "ProgressBar indicates the progress of an operation. It can be set in an "
+ "indeterminate mode to indicate that the length of the operation is unknown."
}
ProgressBar {
id: bar
value: 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
ProgressBar {
indeterminate: true
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: radioButtonPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "RadioButton presents an option button that can be toggled on or off. "
+ "Radio buttons are typically used to select one option from a set of options."
}
Column {
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
RadioButton {
text: "First"
}
RadioButton {
text: "Second"
checked: true
}
RadioButton {
text: "Third"
enabled: false
}
}
}
}
}
Component {
id: rangeSliderPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "RangeSlider is used to select a range specified by two values, by sliding each handle along a track."
}
RangeSlider {
id: slider
first.value: 0.25
second.value: 0.75
anchors.horizontalCenter: parent.horizontalCenter
}
RangeSlider {
orientation: Qt.Vertical
first.value: 0.25
second.value: 0.75
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: scrollBarPage
Flickable {
id: flickable
contentHeight: pane.height
Pane {
id: pane
width: flickable.width
height: flickable.height * 1.25
Column {
id: column
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "ScrollBar is an interactive bar that can be used to scroll to a specific position. "
+ "A scroll bar can be either vertical or horizontal, and can be attached to any Flickable, "
+ "such as ListView and GridView."
}
Image {
rotation: 90
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/arrows.png"
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
ScrollBar.vertical: ScrollBar { }
}
}
Component {
id: scrollIndicatorPage
Flickable {
id: flickable
contentHeight: pane.height
Pane {
id: pane
width: flickable.width
height: flickable.height * 1.25
Column {
id: column
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "ScrollIndicator is a non-interactive indicator that indicates the current scroll position. "
+ "A scroll indicator can be either vertical or horizontal, and can be attached to any Flickable, "
+ "such as ListView and GridView."
}
Image {
rotation: 90
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/arrows.png"
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
Component {
id: sliderPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Slider is used to select a value by sliding a handle along a track."
}
Slider {
id: slider
value: 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
Slider {
orientation: Qt.Vertical
value: 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: spinBoxPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "SpinBox allows the user to choose an integer value by clicking the up or down indicator buttons, "
+ "by pressing up or down on the keyboard, or by entering a text value in the input field."
}
SpinBox {
id: box
value: 50
anchors.horizontalCenter: parent.horizontalCenter
editable: true
}
}
}
}
Component {
id: stackViewPage
StackView {
id: stackView
initialItem: page
Component {
id: page
Pane {
id: pane
width: parent ? parent.width : 0 // TODO: fix null parent on destruction
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "StackView provides a stack-based navigation model which can be used with a set of interlinked pages. "
+ "Items are pushed onto the stack as the user navigates deeper into the material, and popped off again "
+ "when he chooses to go back."
}
Button {
id: button
text: "Push"
anchors.horizontalCenter: parent.horizontalCenter
width: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 2, pane.availableWidth / 3))
onClicked: stackView.push(page)
}
Button {
text: "Pop"
enabled: stackView.depth > 1
width: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 2, pane.availableWidth / 3))
anchors.horizontalCenter: parent.horizontalCenter
onClicked: stackView.pop()
}
}
}
}
}
}
Component {
id: swipeViewPage
Pane {
id: pane
SwipeView {
id: view
currentIndex: 1
anchors.fill: parent
Repeater {
model: 3
Pane {
width: view.width
height: view.height
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "SwipeView provides a navigation model that simplifies horizontal paged scrolling. "
+ "The page indicator on the bottom shows which is the presently active page."
}
Image {
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/arrows.png"
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
PageIndicator {
count: view.count
currentIndex: view.currentIndex
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Component {
id: switchPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Switch is an option button that can be dragged or toggled on or off. "
+ "Switches are typically used to select between two states."
}
Column {
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
Switch {
text: "First"
}
Switch {
text: "Second"
checked: true
}
Switch {
text: "Third"
enabled: false
}
}
}
}
}
Component {
id: tabBarPage
Page {
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
Repeater {
model: 3
Pane {
width: swipeView.width
height: swipeView.height
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "TabBar is a bar with icons or text which allows the user "
+ "to switch between different subtasks, views, or modes."
}
Image {
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/QQC/arrows.png"
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: "First"
}
TabButton {
text: "Second"
}
TabButton {
text: "Third"
}
}
}
}
Component {
id: toolTipPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "A tool tip is a short piece of text that informs the user of a control's function."
}
Button {
text: "Tip"
anchors.horizontalCenter: parent.horizontalCenter
ToolTip.timeout: 5000
ToolTip.visible: pressed
ToolTip.text: "This is a tool tip."
}
}
}
}
Component {
id: tumblerPage
Page {
Flickable {
anchors.fill: parent
contentHeight: pane.implicitHeight
flickableDirection: Flickable.AutoFlickIfNeeded
Pane {
id: pane1
width: parent.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Column {
spacing: 40
width: parent.width
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Tumbler is used to select a value by spinning a wheel."
}
Tumbler {
model: 10
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQuick.Window 2.2
Rectangle {
color: "#545454"
width: 640; height: 480
Item {
id: root
property real value : slider.x * 100 / (container.width - 32)
anchors.centerIn: parent
width: 210; height: 210
Image {
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/customControls/background.png"
}
Image {
x: 96
y: 35
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/customControls/needle_shadow.png"
transform: Rotation {
origin.x: 9; origin.y: 67
angle: needleRotation.angle
}
}
Image {
id: needle
x: 98; y: 33
antialiasing: true
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/customControls/needle.png"
transform: Rotation {
id: needleRotation
origin.x: 5; origin.y: 65
// needle angle
angle: Math.min(Math.max(-130, root.value*2.6 - 130), 133)
Behavior on angle {
SpringAnimation {
spring: 1.4
damping: .15
}
}
}
}
Image { x: 21; y: 18; source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/customControls/overlay.png" }
}
Rectangle {
id: container
property int oldWidth: 0
anchors { bottom: parent.bottom; left: parent.left
right: parent.right; leftMargin: 20; rightMargin: 20
bottomMargin: 10
}
height: 16
radius: 8
opacity: 0.7
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.0; color: "gray" }
GradientStop { position: 1.0; color: "white" }
}
onWidthChanged: {
if (oldWidth === 0) {
oldWidth = width;
return
}
var desiredPercent = slider.x * 100 / (oldWidth - 32)
slider.x = desiredPercent * (width - 32) / 100
oldWidth = width
}
Rectangle {
id: slider
x: 1; y: 1; width: 30; height: 14
radius: 6
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.0; color: "#424242" }
GradientStop { position: 1.0; color: "black" }
}
MouseArea {
anchors.fill: parent
anchors.margins: -16 // Increase mouse area a lot outside the slider
drag.target: parent; drag.axis: Drag.XAxis
drag.minimumX: 2; drag.maximumX: container.width - 32
}
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.14
import QtQuick.Layouts 1.3
import QtDataVisualization 1.0
import QtQuick.Controls 2.14
import QtQuick.Controls.Styles 1.4
Rectangle {
id: mainView
width: 640
height: 480
ListModel {
id: data
ListElement{ row: "0"; col: "0"; longitude: "20.0"; latitude: "10.0"; pop_density: "4.75"; }
ListElement{ row: "1"; col: "0"; longitude: "21.1"; latitude: "10.3"; pop_density: "3.00"; }
ListElement{ row: "2"; col: "0"; longitude: "22.5"; latitude: "10.7"; pop_density: "1.24"; }
ListElement{ row: "3"; col: "0"; longitude: "24.0"; latitude: "10.5"; pop_density: "2.53"; }
ListElement{ row: "0"; col: "1"; longitude: "20.2"; latitude: "11.2"; pop_density: "3.55"; }
ListElement{ row: "1"; col: "1"; longitude: "21.3"; latitude: "11.5"; pop_density: "3.03"; }
ListElement{ row: "2"; col: "1"; longitude: "22.6"; latitude: "11.7"; pop_density: "3.46"; }
ListElement{ row: "3"; col: "1"; longitude: "23.4"; latitude: "11.5"; pop_density: "4.12"; }
ListElement{ row: "0"; col: "2"; longitude: "20.2"; latitude: "12.3"; pop_density: "3.37"; }
ListElement{ row: "1"; col: "2"; longitude: "21.1"; latitude: "12.4"; pop_density: "2.98"; }
ListElement{ row: "2"; col: "2"; longitude: "22.5"; latitude: "12.1"; pop_density: "3.33"; }
ListElement{ row: "3"; col: "2"; longitude: "23.3"; latitude: "12.7"; pop_density: "3.23"; }
ListElement{ row: "0"; col: "3"; longitude: "20.7"; latitude: "13.3"; pop_density: "5.34"; }
ListElement{ row: "1"; col: "3"; longitude: "21.5"; latitude: "13.2"; pop_density: "4.54"; }
ListElement{ row: "2"; col: "3"; longitude: "22.4"; latitude: "13.6"; pop_density: "4.65"; }
ListElement{ row: "3"; col: "3"; longitude: "23.2"; latitude: "13.4"; pop_density: "6.67"; }
ListElement{ row: "0"; col: "4"; longitude: "20.6"; latitude: "15.0"; pop_density: "6.01"; }
ListElement{ row: "1"; col: "4"; longitude: "21.3"; latitude: "14.6"; pop_density: "5.83"; }
ListElement{ row: "2"; col: "4"; longitude: "22.5"; latitude: "14.8"; pop_density: "7.32"; }
ListElement{ row: "3"; col: "4"; longitude: "23.7"; latitude: "14.3"; pop_density: "6.90"; }
}
GridLayout {
id: gridLayout
columns: 2
Layout.fillHeight: true
Layout.fillWidth: true
anchors.top: mainView.top
anchors.bottom: mainView.bottom
anchors.left: mainView.left
anchors.right: mainView.right
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
border.color: surfaceGraph.theme.gridLineColor
border.width: 2
Surface3D {
id: surfaceGraph
anchors.fill: parent
anchors.margins: parent.border.width
theme: Theme3D {
type: Theme3D.ThemePrimaryColors
font.pointSize: 60
}
scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
Surface3DSeries {
itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel"
ItemModelSurfaceDataProxy {
itemModel: data
// The surface data points are not neatly lined up in rows and columns,
// so we define explicit row and column roles.
rowRole: "row"
columnRole: "col"
xPosRole: "latitude"
zPosRole: "longitude"
yPosRole: "pop_density"
}
}
}
}
// We'll use one grid cell for buttons
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
GridLayout {
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
columns: 2
Button {
Layout.minimumWidth: parent.width / 2
Layout.fillHeight: true
Layout.fillWidth: true
text: "Clear Selections"
onClicked: clearSelections() // call a helper function to keep button itself simpler
}
Button {
Layout.minimumWidth: parent.width / 2
Layout.fillHeight: true
Layout.fillWidth: true
text: "Quit - NA"
}
Button {
Layout.fillHeight: true
Layout.fillWidth: true
text: "Reset Cameras"
onClicked: resetCameras() // call a helper function to keep button itself simpler
}
Button {
Layout.fillHeight: true
Layout.fillWidth: true
text: "Toggle Mesh \n Styles"
onClicked: toggleMeshStyle() // call a helper function to keep button itself simpler
}
}
}
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
border.color: scatterGraph.theme.gridLineColor
border.width: 2
Scatter3D {
id: scatterGraph
anchors.fill: parent
anchors.margins: parent.border.width
theme: Theme3D {
type: Theme3D.ThemeDigia
font.pointSize: 60
}
scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
Scatter3DSeries {
itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel"
ItemModelScatterDataProxy {
itemModel: data
// Mapping model roles to scatter series item coordinates.
xPosRole: "latitude"
zPosRole: "longitude"
yPosRole: "pop_density"
}
}
}
}
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
border.color: barGraph.theme.gridLineColor
border.width: 2
Bars3D {
id: barGraph
anchors.fill: parent
anchors.margins: parent.border.width
theme: Theme3D {
type: Theme3D.ThemeQt
font.pointSize: 60
}
selectionMode: AbstractGraph3D.SelectionItemAndRow | AbstractGraph3D.SelectionSlice
scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
Bar3DSeries {
itemLabelFormat: "@seriesName: @valueLabel"
name: "Population density"
ItemModelBarDataProxy {
itemModel: data
// Mapping model roles to bar series rows, columns, and values.
rowRole: "row"
columnRole: "col"
valueRole: "pop_density"
}
}
}
}
}
function clearSelections() {
barGraph.clearSelection()
scatterGraph.clearSelection()
surfaceGraph.clearSelection()
}
function resetCameras() {
surfaceGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
barGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
surfaceGraph.scene.activeCamera.zoomLevel = 100.0
scatterGraph.scene.activeCamera.zoomLevel = 100.0
barGraph.scene.activeCamera.zoomLevel = 100.0
}
function toggleMeshStyle() {
if (barGraph.seriesList[0].meshSmooth === true) {
barGraph.seriesList[0].meshSmooth = false
if (surfaceGraph.seriesList[0].flatShadingSupported)
surfaceGraph.seriesList[0].flatShadingEnabled = true
scatterGraph.seriesList[0].meshSmooth = false
} else {
barGraph.seriesList[0].meshSmooth = true
surfaceGraph.seriesList[0].flatShadingEnabled = false
scatterGraph.seriesList[0].meshSmooth = true
}
}
}
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Particles 2.12
Rectangle {
id: screen
property int maxColumn: 10
property int maxRow: 15
property int maxIndex: maxColumn * maxRow
property var board: new Array(maxIndex);
// NOTE! The JavaScript is in this file to be accessible for the demo users
// Normally the JavaScript functions should be in a separate .js file
//Index function used instead of a 2D array
function index(column, row) {
return column + (row * maxColumn);
}
function startNewGame() {
//Delete blocks from previous game
for (var i = 0; i < maxIndex; i++) {
if (board[i] != null)
board[i].destroy();
}
//Calculate board size
maxColumn = Math.floor(gameCanvas.width / gameCanvas.blockSize);
maxRow = Math.floor(gameCanvas.height / gameCanvas.blockSize);
maxIndex = maxRow * maxColumn;
//Initialize Board
board = new Array(maxIndex);
gameCanvas.score = 0;
for (var column = 0; column < maxColumn; column++) {
for (var row = 0; row < maxRow; row++) {
board[index(column, row)] = null;
createBlock(column, row);
}
}
}
function createBlock(column, row) {
var dynamicObject = boomBlockComponent.createObject(gameCanvas);
if (dynamicObject == null) {
console.log("error creating block");
console.log(boomBlockComponent.errorString());
return false;
}
dynamicObject.type = Math.floor(Math.random() * 3);
dynamicObject.x = column * gameCanvas.blockSize;
dynamicObject.y = row * gameCanvas.blockSize;
dynamicObject.width = gameCanvas.blockSize;
dynamicObject.height = gameCanvas.blockSize;
dynamicObject.spawned = true;
board[index(column, row)] = dynamicObject;
return true;
}
property int fillFound; //Set after a floodFill call to the number of blocks found
property var floodBoard; //Set to 1 if the floodFill reaches off that node
function handleClick(xPos, yPos) {
var column = Math.floor(xPos / gameCanvas.blockSize);
var row = Math.floor(yPos / gameCanvas.blockSize);
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return;
if (board[index(column, row)] == null)
return;
//If it's a valid block, remove it and all connected (does nothing if it's not connected)
floodFill(column, row, -1);
if (fillFound <= 0)
return;
gameCanvas.score += (fillFound - 1) * (fillFound - 1);
shuffleDown();
victoryCheck();
}
function floodFill(column, row, type) {
if (board[index(column, row)] == null)
return;
var first = false;
if (type == -1) {
first = true;
type = board[index(column, row)].type;
//Flood fill initialization
fillFound = 0;
floodBoard = new Array(maxIndex);
}
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return;
if (floodBoard[index(column, row)] == 1 || (!first && type != board[index(column, row)].type))
return;
floodBoard[index(column, row)] = 1;
floodFill(column + 1, row, type);
floodFill(column - 1, row, type);
floodFill(column, row + 1, type);
floodFill(column, row - 1, type);
if (first == true && fillFound == 0)
return; //Can't remove single blocks
board[index(column, row)].dying = true;
board[index(column, row)] = null;
fillFound += 1;
}
function shuffleDown() {
//Fall down
for (var column = 0; column < maxColumn; column++) {
var fallDist = 0;
for (var row = maxRow - 1; row >= 0; row--) {
if (board[index(column, row)] == null) {
fallDist += 1;
} else {
if (fallDist > 0) {
var obj = board[index(column, row)];
obj.y = (row + fallDist) * gameCanvas.blockSize;
board[index(column, row + fallDist)] = obj;
board[index(column, row)] = null;
}
}
}
}
//Fall to the left
fallDist = 0;
for (column = 0; column < maxColumn; column++) {
if (board[index(column, maxRow - 1)] == null) {
fallDist += 1;
} else {
if (fallDist > 0) {
for (row = 0; row < maxRow; row++) {
obj = board[index(column, row)];
if (obj == null)
continue;
obj.x = (column - fallDist) * gameCanvas.blockSize;
board[index(column - fallDist, row)] = obj;
board[index(column, row)] = null;
}
}
}
}
}
function victoryCheck() {
//Award bonus points if no blocks left
var deservesBonus = true;
for (var column = maxColumn - 1; column >= 0; column--)
if (board[index(column, maxRow - 1)] != null)
deservesBonus = false;
if (deservesBonus) {
gameCanvas.score += 500;
gameFinishedDialog.won = true;
}
//Check whether game has finished
if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) {
gameFinishedDialog.open();
}
}
//only floods up and right, to see if it can find adjacent same-typed blocks
function floodMoveCheck(column, row, type) {
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return false;
if (board[index(column, row)] == null)
return false;
var myType = board[index(column, row)].type;
if (type == myType)
return true;
return floodMoveCheck(column + 1, row, myType) || floodMoveCheck(column, row - 1, board[index(column, row)].type);
}
width: 640; height: 480
Item {
width: parent.width
anchors { top: parent.top; bottom: toolBar.top }
Image {
id: background
anchors.fill: parent
source: "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/background.jpg"
fillMode: Image.PreserveAspectCrop
}
Item {
id: gameCanvas
property int score: 0
property int blockSize: 40
anchors.centerIn: parent
width: parent.width - (parent.width % blockSize);
height: parent.height - (parent.height % blockSize);
MouseArea {
anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y);
}
}
}
Dialog {
id: gameFinishedDialog
property bool won: false
anchors.centerIn: parent
title: won ? "You won the game!" : "Game over!"
}
Rectangle {
id: toolBar
width: parent.width; height: newGameButton.height
anchors.bottom: screen.bottom
Button {
id: newGameButton
anchors { left: parent.left; verticalCenter: parent.verticalCenter }
text: "New Game"
onClicked: startNewGame()
}
Label {
id: score
anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter }
text: "Score: " + gameCanvas.score
color: "black"
}
}
Component {
id: boomBlockComponent
Item {
id: block
property int type: 0
property bool dying: false
property bool spawned: false
Behavior on x {
enabled: spawned;
SpringAnimation{ spring: 2; damping: 0.2 }
}
Behavior on y {
SpringAnimation{ spring: 2; damping: 0.2 }
}
Image {
id: img
anchors.fill: parent
source: {
if (type == 0)
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/redStone.png";
else if (type == 1)
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/blueStone.png";
else
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/greenStone.png";
}
opacity: 0
Behavior on opacity {
NumberAnimation { properties:"opacity"; duration: 200 }
}
}
ParticleSystem {
id: sys
anchors.centerIn: parent
ImageParticle {
source: {
if (type == 0)
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/redStar.png";
else if (type == 1)
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/blueStar.png";
else
return "https://cdn2.hubspot.net/hubfs/149513/QML/playground/examples/images/sameGame/greenStar.png";
}
rotationVelocityVariation: 360
}
Emitter {
id: particles
anchors.centerIn: parent
emitRate: 0
lifeSpan: 700
velocity: AngleDirection {angleVariation: 360; magnitude: 80; magnitudeVariation: 40}
size: 16
}
}
states: [
State {
name: "AliveState"
when: spawned == true && dying == false
PropertyChanges { target: img; opacity: 1 }
},
State {
name: "DeathState"
when: dying == true
StateChangeScript { script: particles.burst(50); }
PropertyChanges { target: img; opacity: 0 }
StateChangeScript { script: block.destroy(1000); }
}
]
}
}
}
ご紹介した例はいかがでしたか?次はぜひ本格的にQtをお試しください!
Qtフレームワーク、MPUでのデスクトップ開発用およびMCUでの組み込み開発用のツール、およびその他のエンタープライズアドオンを評価ライセンス(無料)でお試しいただくことが可能です。 UIデザイナーの方は、評価パッケージにも含まれているQt DesignStudioをぜひお試しください。