PyQt4およびQML

さらに最近では、フレームワークQtのソフトウェアの開発者は、我々はその非常に簡単、マークアップ言語でGUIの外観、代替標準を応援 - QML。

メインプログラムとQMLのバンドルは、Qt宣言モジュールです。 バージョン4.7以降-PyQt4はこのモジュールをサポートしています。

QMLはメインGUIよりもはるかにシンプルで柔軟性があり、さらに、JavaScriptで関数を記述できるため、プログラミング言語でもあります。 Pythonはかなりシンプルで柔軟なインタープリター言語です。





始めましょう



まずQMLフォーム。 プログラムの起動時にエラーが発生しても作業が停止しないため、完全に準備ができていると同時に効率的です。 その後、我々は、コードの一部をカバーします。



import Qt 4.7 Rectangle { //  signal wantquit property int qwX: 0; property int qwY: 0 property int owX: 0; property int owY: 0 property bool first: true /*      */ function updateMessage(text) { messageText.text = text } anchors.fill: parent; color: "black" //  Text { id: messageText; anchors.centerIn: parent; color: "white" } //    MouseArea { anchors.fill: parent onClicked: { //     python messageText.text = someone.some_id first = true } onPositionChanged: { owX = first? mouseX : owX owY = first? mouseY : owY first = false qwX+=mouseX-owX qwY+=mouseY-owY //  main.form_move(qwX, qwY) } onDoubleClicked: { //  wantquit() } } }
      
      







この場合、フォームは「form.qml」という名前でpythonファイルと同じディレクトリに保存されます。

次に、PyQtを使用してこのフォームを印刷します。 この目的のために、モジュールは、要素QtDeclarative QDeclarativeViewを持っています。 それは別のウィンドウ、それぞれ子として集積化のいずれかであり得る、したがって特性とQWidgetの機能を継承し、この方法は、接続有します。



 from PyQt4 import QtCore, QtGui, Qt, QtDeclarative import sys app = QtGui.QApplication(sys.argv) #  QML  view = QtDeclarative.QDeclarativeView() view.setSource(QtCore.QUrl('form.qml')) view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) view.setGeometry(100, 100, 400, 240) view.show() sys.exit(app.exec_())
      
      



、QtDeclarative from PyQt4 import QtCore, QtGui, Qt, QtDeclarative import sys app = QtGui.QApplication(sys.argv) # QML view = QtDeclarative.QDeclarativeView() view.setSource(QtCore.QUrl('form.qml')) view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) view.setGeometry(100, 100, 400, 240) view.show() sys.exit(app.exec_())







その結果、削除されたqmlviewerが作成されます。

さらに、いくつかのメソッドの利便性と操作性のために、QDeclarativeViewを継承するクラスを作成し、フォームの外観をわずかに変更し、トップダウンプログラミングに適したクラスが初期化されるときに呼び出される追加の「スタブ」関数を作成します。

起動時に、黒い長方形だけが表示されます。 (ウィンドウフレームがないため、タスクバーからのみ閉じることができます)。



 from PyQt4 import QtCore, QtGui, Qt, QtDeclarative class I_will_be_form(QtDeclarative.QDeclarativeView): def __init__(self, parent=None): QtDeclarative.QDeclarativeView.__init__(self, parent) #   self.setWindowFlags(Qt.Qt.FramelessWindowHint) self.setSource(QtCore.QUrl.fromLocalFile('form.qml')) self.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) self.setGeometry(100, 100, 400, 240) self.signal_func_Qml() self.signalThis() self.slot() self.prop() def signal_func_Qml(self): print "Qml's signal" def signalThis(self): print "Signal of PyQt" def slot(self): print "Property" def prop(self): print "Slot " import sys app = QtGui.QApplication(sys.argv) Iwbf = I_will_be_form() Iwbf.show() sys.exit(app.exec_())
      
      



、QtDeclarative from PyQt4 import QtCore, QtGui, Qt, QtDeclarative class I_will_be_form(QtDeclarative.QDeclarativeView): def __init__(self, parent=None): QtDeclarative.QDeclarativeView.__init__(self, parent) # self.setWindowFlags(Qt.Qt.FramelessWindowHint) self.setSource(QtCore.QUrl.fromLocalFile('form.qml')) self.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) self.setGeometry(100, 100, 400, 240) self.signal_func_Qml() self.signalThis() self.slot() self.prop() def signal_func_Qml(self): print "Qml's signal" def signalThis(self): print "Signal of PyQt" def slot(self): print "Property" def prop(self): print "Slot " import sys app = QtGui.QApplication(sys.argv) Iwbf = I_will_be_form() Iwbf.show() sys.exit(app.exec_())



from PyQt4 import QtCore, QtGui, Qt, QtDeclarative class I_will_be_form(QtDeclarative.QDeclarativeView): def __init__(self, parent=None): QtDeclarative.QDeclarativeView.__init__(self, parent) # self.setWindowFlags(Qt.Qt.FramelessWindowHint) self.setSource(QtCore.QUrl.fromLocalFile('form.qml')) self.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) self.setGeometry(100, 100, 400, 240) self.signal_func_Qml() self.signalThis() self.slot() self.prop() def signal_func_Qml(self): print "Qml's signal" def signalThis(self): print "Signal of PyQt" def slot(self): print "Property" def prop(self): print "Slot " import sys app = QtGui.QApplication(sys.argv) Iwbf = I_will_be_form() Iwbf.show() sys.exit(app.exec_())







QMLへのアクセス



signal_func_Qml関数に入力することから始めましょう。 QDeclarativeView QMLは、彼がrootObject()メソッドによってアップロードされたファイル構造へのアクセスを持っています。 このメソッドはルートオブジェクトを返します。 したがって、このファイルの機能と信号を操作できます。 QML要素にプロパティを直接割り当てることはできません。 (できたとしても、関数でこれを行う方が賢明でしょう)。

そのため、QMLファイルには、ルートウィジェットのスペースをダブルクリックして送信されるwantquitシグナルが既にあります。 また、渡されたテキストをテキストウィジェットに書き込むupdateMessage関数。



 def signal_func_Qml(self): print "Qml's signal" root = self.rootObject() #(1) root.wantquit.connect(app.quit) #(2) root.updateMessage(QtCore.QString('From root')) #(3)
      
      







これは、関数が満たされる方法です。 行番号(1)で、ローカルルート変数にルートオブジェクトを取得し、行(2)でアプリケーション終了関数をwantquitシグナルにアタッチし、行(3)でupdateMessage関数を実行します。 通常のstr型はQMLファイルを受け入れないため、QMLファイルに渡される文字列値は必ずQString型に変換する必要がありますが、数値形式にはこのような問題はありません。

同様に、Pythonファイルクラスによって送信された信号を処理できます。 これを行うには、初期化された信号であるクラスI_will_be_formに書き込みます(クラスを初期化する前に、同じレベルで):



 inited = QtCore.pyqtSignal(str) def __init__(self, parent=None): ......
      
      







また、信号を入力してくださいこの関数:



 def signalThis(self): print "Signal of PyQt" root = self.rootObject() #(1) self.inited.connect(root.updateMessage) #(2) self.inited.emit(QtCore.QString("I'm ready!")) #(3)
      
      







ライン(1)私たちは再びルートオブジェクトを取得します(前の関数のように、彼はローカル変数でした)。 ライン(2)私たちは信号inited機能updateMessage QML-ファイルをバインドします。 したがって、シグナルを送信するテキストは、パラメーターとして関数に渡されます。 行(3)で、「I'm ready!」というテキストを含む信号を送信します。 (ここでも、再び、それは安全でプレーすることは必ずしもありませんが、QStringの中で投げることを忘れて、それでも良いアイデアはありません)。



PyQtへのアクセス



PyQtからQMLへのアクセスに加えて、反対の可能性もあります。 スロット関数を設定することから始めましょう。



 def slot(self): print "Property" self.engine().rootContext().setContextObject(self) #(1) self.engine().rootContext().setContextProperty('main', self) #(2)
      
      



setContextObject(自己)#( def slot(self): print "Property" self.engine().rootContext().setContextObject(self) #(1) self.engine().rootContext().setContextProperty('main', self) #(2)







両方の行で、QMLからPyQtオブジェクトへのアクセスを開きます。 最初の場合のみ、自己オブジェクト(ここではI_will_be_form)の関数はQMLルートウィジェットの関数になり、I_will_be_formクラスの関数へのアクセスはその名前で実行されます。 2番目のケースでは、クラスI_will_be_formが識別子mainを持つルートオブジェクトのウィジェットになり、関数へのアクセスがそれぞれmain。<関数名>になり、名前の競合がなくなり、コードの理解が簡単になります。 ただし、すべての機能にアクセスできるわけではありません。

当初、QMLは強く型付けされた言語であるC ++に適合しており、そのクラスにはprivate、public、protectedなどの概念があります。 Pythonには、類型化もこれらの概念もありません。 PyQt開発者はこの問題を修正する必要がありました。 そのため、特定の関数をすべて同じクラスI_will_be_formで説明します。



 @QtCore.pyqtSlot(int, int) #(1) def form_move(self, x, y): self.move(x, y)
      
      







この関数は、送信されたxおよびy座標に従ってQDeclarativeViewウィンドウを移動します。 今ライン(1)に注意を払う、それはあなたがQMLのこの機能にアクセスすることを可能にする私達の機能のスロットになりますが、この場合には値を返すことはできません。

その結果、onPositionChangedブロック内のQMLコードフラグメントは意味を持ち始め、値をform_move関数に渡してウィンドウを移動し、起動時に長方形上でマウスボタンを押したまま移動できるようにします。

次に、prop関数を入力します。



 def prop(self): print "Slot" self.engine().rootContext().setContextProperty('someone', so)
      
      







また、I_will_be_formの前に別のSomeoneクラスを追加で記述し、すぐにグローバル変数で初期化します。



 class Someone(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) self.my_id = QtCore.QString("I'm first") @QtCore.pyqtProperty(QtCore.QString) #(1) def some_id(self): return self.my_id so = Someone()
      
      







まず、prop関数自体を検討します。前の関数と同様に、オブジェクトへのアクセスが開かれますが、今回はSomeoneクラスです。 必ずQObjectのプロパティを継承することに注意してください。そうしないと、QMLはこのクラスを受け入れません。 それでは、以前考えられていたform_moveとは異なり、値を返すsome_id関数に移りましょう。 数値(1)の行は、この値のタイプを説明すると同時に、QMLからこの関数へのオープンアクセスを示します。 繰り返しますが、値の型はstrではなくQStringです。

これで、QMLファイルのonClickedブロックが機能し、四角形をクリックするとテキストが変わります。



おわりに



私の意見では、主にPyQtからQMLへのアクセスを使用する必要があります。これは、2番目の場合のようにQMLコードを混乱させないためです。 はい、この方法ははるかに単純で、必要なコードが少ないため、プログラムの可読性が向上します。

Pythonコード

QMLコード



UPD:インデントがなくてすみません。 私は、コードがそれらを認識しないと注意を払っていないことを知っているが、まだ修正されていません。



All Articles