前回に引き続き今回もPySide2+Qtquick(qml)のメモ
GUIだと結構定番の電卓っぽい奴の実装
Button押下でイベント発生させてTextInputからデータもらってTextInputに返すサンプルだと思ってくれればいい
Pythonコード
import sys import os from PySide2 import QtCore, QtWidgets, QtQml class Connect(QtCore.QObject): def __init__(self, parent=None): super(Connect, self).__init__(parent) @QtCore.Slot(int,int,result = float) def sum(self,arg1,arg2): return arg1 + arg2 @QtCore.Slot(int, int, result=float) def sub(self, arg1, arg2): return arg1 - arg2 @QtCore.Slot(int, int, result=float) def mul(self, arg1, arg2): return arg1 * arg2 @QtCore.Slot(int, int, result=float) def div(self, arg1, arg2): return arg1 / arg2 if __name__ == "__main__": os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material" app = QtWidgets.QApplication(sys.argv) myconnect = Connect() engine = QtQml.QQmlApplicationEngine() ctx = engine.rootContext() ctx.setContextProperty("Connect", myconnect) engine.load('mypyside2.qml') if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
qmlコード
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.0 Window { objectName: "a" visible: true width: 640 height: 480 title: qsTr("Hello World") TextInput { id: textInput1 x: 104 y: 108 width: 80 height: 37 text: qsTr("12") font.pixelSize: 20 } TextInput { id: textInput2 x: 179 y: 108 width: 80 height: 37 text: qsTr("2") font.pixelSize: 20 } TextInput { id: textInput3 x: 270 y: 108 width: 80 height: 37 text: qsTr("1") font.pixelSize: 20 } Row { id: row x: 104 y: 186 width: 427 height: 119 spacing: 9 Button { objectName:"button" id: button1 width: 100 height: 50 text: qsTr("add") font.pointSize: 14 onClicked:function(){ textInput3.text = Connect.sum(textInput1.text,textInput2.text) } } Button { id: button2 width: 100 height: 50 text: qsTr("sub") font.pointSize: 13 objectName: "button" onClicked:function(){ textInput3.text = Connect.sub(textInput1.text,textInput2.text) } } Button { id: button3 width: 100 height: 50 text: qsTr("mul") font.pointSize: 12 objectName: "button" onClicked:function(){ textInput3.text = Connect.mul(textInput1.text,textInput2.text) } } Button { id: button4 width: 100 height: 50 text: qsTr("div") font.pointSize: 12 objectName: "button" onClicked:function(){ textInput3.text = Connect.div(textInput1.text,textInput2.text) } } } }
解説的なやつ
python側
@QtCore.Slot(int,int,result = float) def sum(self,arg1,arg2): return arg1 + arg2
addの例で解説する。
@QtCore.Slot(int,int,result = float)で引数の型と返り値の型をqmlに対して公開する。
あとはdefで関数を実装するだけ前回との違いはSlotでreturnしているとこ。
ここで注意が必要なのが書かなくてもエラーは出ないがresult = floatは必須ということ
書かないと何も値が返ってこない
qml側
TextInput { id: textInput3 x: 270 y: 108 width: 80 height: 37 text: qsTr("1") font.pixelSize: 20 } Button { objectName:"button" id: button1 width: 100 height: 50 text: qsTr("add") font.pointSize: 14 onClicked:function(){ textInput3.text = Connect.sum(textInput1.text,textInput2.text) } }
こちらもaddの例で説明する。
まずqmlオブジェクトに対してはtextInput3.textのようにid.propertyでアクセスできる。(qmlではオブジェクト以下のパラメータ類のことをPropertyと呼ぶ
次にonclicked部分で押下時の動作を定義している。
textInput3.textにpython側のsumの返り値を代入するということをしているだけだ。
あくまでqmlオブジェクトへの代入はqml側でやるというとこがQtの方針
PythonやC++側からも子オブジェクトにアクセスできるがQt公式は推奨していない(参照関係がごちゃごちゃになるため
この関係を守るとUI設計者と内部実装側が完全分業可能なので合理的ではある。