Qt Quick は、こちらのページで記載した Qt フレームワークにおいて UI 作成のために利用されるライブラリです。Qt Quick で利用される言語 QML (Qt Modeling Language) について、基本的な使い方を記載します。
sample.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from sys import exit, argv
from PySide2.QtWidgets import QApplication
from PySide2.QtQuick import QQuickView
from PySide2.QtCore import QUrl
def Main():
app = QApplication(argv)
view = QQuickView()
url = QUrl('view.qml')
view.setSource(url)
view.show()
exit(app.exec_())
if __name__ == '__main__':
Main()
view.qml
import QtQuick 2.7
...
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
Text {
text: Math.random()
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
function randomNumber() {
return Math.random() * 360;
}
function getNumber() {
return rectangle.randomNumber();
}
Text {
text: rectangle.getNumber()
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
myscript.js
function randomNumber() {
return Math.random() * 360;
}
function getNumber() {
return randomNumber();
}
view.qml
import QtQuick 2.7
import 'myscript.js' as Logic
Rectangle {
id: rectangle
width: 600
height: 600
Text {
text: Logic.getNumber()
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
function myfunc() {
console.log('xxxx')
// console.exception('xxxx')
// console.trace()
return parseInt(mytext.text) + 1
}
MouseArea {
anchors.fill: parent
onClicked: mytext.text = rectangle.myfunc()
}
Text {
id: mytext
text: '0'
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
出力例
console.log()
qml: xxxx
console.exception()
qml: xxxx
myfunc (file:///vagrant/work/view.qml:9)
onClicked (file:///vagrant/work/view.qml:15)
console.trace()
myfunc (file:///vagrant/work/view.qml:9)
onClicked (file:///vagrant/work/view.qml:15)
console.assert()
を利用できます。スタックトレースも出力されます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
function myfunc() {
console.assert(1 == 1, 'pass')
console.assert(1 == 0, 'fail')
return parseInt(mytext.text) + 1
}
MouseArea {
anchors.fill: parent
onClicked: mytext.text = rectangle.myfunc()
}
Text {
id: mytext
text: '0'
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
出力例
fail
myfunc (file:///vagrant/work/view.qml:10)
onClicked (file:///vagrant/work/view.qml:16)
console.time()
から console.timeEnd()
までの時間を計測できます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
function myfunc() {
console.time('mykey1')
// do something here...
console.timeEnd('mykey1')
return parseInt(mytext.text) + 1
}
MouseArea {
anchors.fill: parent
onClicked: mytext.text = rectangle.myfunc()
}
Text {
id: mytext
text: '0'
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
出力例
mykey1: 0ms
ある箇所が何回実行されたかを console.count()
で確認できます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 600
height: 600
function myfunc() {
console.count('xxxx')
return parseInt(mytext.text) + 1
}
MouseArea {
anchors.fill: parent
onClicked: mytext.text = rectangle.myfunc()
}
Text {
id: mytext
text: '0'
y: 30
anchors.horizontalCenter: rectangle.horizontalCenter
}
}
出力例
xxxx: 1
xxxx: 2
xxxx: 3
環境変数 QML_IMPORT_TRACE=1
で実行すると、以下のような情報を確認できます。
$ QML_IMPORT_TRACE=1 python sample.py
QQmlImportDatabase::addImportPath: "/home/vagrant/.pyenv/versions/2.7.15/lib/python2.7/site-packages/PySide2/Qt/qml"
QQmlImportDatabase::addImportPath: "qrc:/qt-project.org/imports"
QQmlImportDatabase::addImportPath: "/home/vagrant/.pyenv/versions/2.7.15/bin"
QQmlImports(file:///vagrant/work/view.qml)::addLibraryImport: "QtQuick" 2.7 as ""
QQmlImports(file:///vagrant/work/view.qml)::importExtension: loaded "/home/vagrant/.pyenv/versions/2.7.15/lib/python2.7/site-packages/PySide2/Qt/qml/QtQuick.2/qmldir"
QQmlImportDatabase::registerPluginTypes: "QtQuick" from "/home/vagrant/.pyenv/versions/2.7.15/lib/python2.7/site-packages/PySide2/Qt/qml/QtQuick.2"
QQmlImports(file:///vagrant/work/view.qml)::resolveType: "Text" => "QQuickText" TYPE
QQmlImports(file:///vagrant/work/view.qml)::resolveType: "Rectangle" => "QQuickRectangle" TYPE
QQmlImports(file:///vagrant/work/view.qml)::resolveType: "MouseArea" => "QQuickMouseArea" TYPE
親の位置をもとにして x
と y
で相対的な座標を指定できます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 300
height: 300
Rectangle {
x: 100
y: 100
width: 100
height: 100
color: 'blue'
Rectangle {
x: 20
y: 20
width: 100
height: 100
color: 'red'
}
}
}
他の要素の位置を元にして anchors
で位置を指定できます。以下では parent
をもとにしていますが、その他に同階層の任意の要素に対して id
を指定することで位置関係を指定できます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 300
height: 300
Rectangle {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
width: 100
height: 100
color: 'red'
}
}
State
の AnchorChanges
を利用することで指定した要素の anchors
を動的に変更できます。その際 Transition
の AnchorAnimation
も併用することで遷移時のアニメーションについて指定できます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 300
height: 300
Rectangle {
id: mytarget
width: 100
height: 100
color: 'red'
}
MouseArea {
anchors.fill: parent
onClicked: rectangle.state = 'mystate'
}
states: State {
name: 'mystate'
AnchorChanges {
target: mytarget
anchors.top: rectangle.top
anchors.bottom: rectangle.bottom
}
PropertyChanges {
target: mytarget
anchors.topMargin: 10
anchors.bottomMargin: 10
}
}
transitions: Transition {
// smoothly transit in 5 secs
AnchorAnimation { duration: 5000 }
}
}
遷移前
遷移後
Row、Column、Grid 等を利用すると、子要素を整列させることができます。
import QtQuick 2.7
Rectangle {
id: rectangle
width: 300
height: 300
Row {
spacing: 20
Rectangle { width: 80; height: 100; color: 'red' }
Rectangle { width: 80; height: 100; color: 'red' }
Rectangle { width: 80; height: 100; color: 'red' }
}
}