Qt for Python (PySide2) の基本的な使い方
[履歴] [最終更新] (2018/07/17 01:36:15)
1
作品
409
技術情報
最近の投稿
ここは
趣味の電子工作を楽しむ人のためのハードウェア情報共有サイト

技術情報や作品の投稿機能、リアルタイム遠隔操作 API をご利用いただけます。
新着作品

概要

QT を Python から利用するためのライブラリには PyQt や PySide 等が存在します。PySide は元々 QT4 向けのライブラリでしたが、QT5 に対応するために新たに PySide2 が開発されました。PySide2 は Qt for Python ともよばれています。

Q: PySide? Qt for Python? what is the name?
A: The name of the project is Qt for Python and the name of the module is PySide2.
Q: Why PySide2 and not just PySide?
A: Since PySide was developed for Qt4, when the port was made to support Qt5, the name was changed to PySide2 to infer that is was a newer version.
https://wiki.qt.io/Qt_for_Python

PySide2 について基本的な使い方を記載します。今回は VirtualBox と Vagrant で Debian9/stretch をインストールして利用することにします。

以下のコマンドで同期しつつ、X11 で動作確認します。

vagrant rsync
vagrant rsync-auto

インストール

必要なバージョンの python や qt5 等をインストールする必要があります。

python

pyenv を利用すると簡単です。今回は 2.7.15 を利用することにします。

pyenv global 2.7.15

PySide2 自体は pip でインストールできます

pip install --index-url=http://download.qt.io/snapshots/ci/pyside/5.9/latest/ pyside2 --trusted-host download.qt.io

qt5 および依存ライブラリ

OpenGL 等が依存先としてまとめてインストールされます。環境によっては pyside2/wiki/Dependencies を参照して、不足しているパッケージを適宜追加でインストールします。

sudo apt-get install qt5-default
sudo apt-get install qttools5-dev-tools

動作検証

DISPLAY が利用できない場合は仮想ディスプレイを作成して利用します。

sample.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtWidgets import QApplication, QLabel

def Main():
    app = QApplication(argv)
    label = QLabel("Hello World")
    label.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

古い環境の場合は必要な共有ライブラリが存在せずにエラーになります。新しい OS を利用するか、必要に応じてソースコードからビルドします。例えば以下のような libc のバージョンエラーが発生します。

$ python sample.py
Traceback (most recent call last):
  File "sample.py", line 2, in <module>
    from PySide2.QtWidgets import QApplication, QLabel
ImportError: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /home/username/.pyenv/versions/2.7.15/lib/python2.7/site-packages/PySide2/QtWidgets.so)

以下のようにソースコードからビルドして対応できます。

mkdir glibc_install
cd glibc_install/
wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.1.tar.gz
tar zxvf glibc-2.14.1.tar.gz
cd glibc-2.14.1/
mkdir build
cd build/
../configure --prefix=/opt/glibc-2.14
make -j4
sudo make install
export LD_LIBRARY_PATH=/opt/glibc-2.14/lib

その他の検証用のコード

HTML の利用

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtWidgets import QApplication, QLabel

def Main():
    app = QApplication(argv)
    label = QLabel("<font color=red size=40>Hello World!</font>")
    label.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

QML の利用

#!/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.0

Rectangle {
  width: 200
  height: 200
  color: "green"
  Text {
    text: "Hello World"
    anchors.centerIn: parent
  }
}

Uploaded Image

メッセージボックスの利用

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtWidgets import QApplication, QMessageBox

def Main():
    app = QApplication(argv)
    msg_box = QMessageBox()
    msg_box.setText("Hello World!")
    msg_box.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

関数を実行する push ボタンの利用

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtWidgets import QApplication, QPushButton

def f():
    print("clicked!")

def Main():
    app = QApplication(argv)

    # push 時に関数を実行
    button = QPushButton("Click me")
    button.clicked.connect(f)

    buttonExit = QPushButton("Exit")
    buttonExit.clicked.connect(app.exit)

    button.show()
    buttonExit.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

QWidget を継承したクラスを作成

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from random import choice
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayout, QApplication

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()

        self.nums = ["1", "2", "3"]

        # ラベルの作成
        self.text = QLabel("0")
        self.text.setAlignment(Qt.AlignCenter)

        # push ボタンの作成
        self.button = QPushButton("Click me!")
        self.button.clicked.connect(self.f)

        # ラベルとボタンを格納する箱となるレイアウトの作成
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

    def f(self):
        self.text.setText(choice(self.nums))

def Main():
    app = QApplication(argv)
    widget = MyWidget()
    widget.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

QDialog を継承したクラスを作成

QDialogQWidget を継承しています。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtWidgets import QLineEdit, QPushButton, QApplication, QVBoxLayout, QDialog

class MyForm(QDialog):
    def __init__(self):
        super(MyForm, self).__init__()
        self.setWindowTitle("My Form")

        # 入力フォーム、ボタン
        self.edit = QLineEdit("xxxx")
        self.button = QPushButton("yyyy")
        self.button.clicked.connect(self.f)

        # レイアウト
        layout = QVBoxLayout()
        layout.addWidget(self.edit)
        layout.addWidget(self.button)
        self.setLayout(layout)

    def f(self):
        print ("Hello %s" % self.edit.text())

def Main():
    app = QApplication(argv)
    form = MyForm()
    form.show()
    exit(app.exec_())

if __name__ == '__main__':
    Main()

Uploaded Image

シグナルとスロット

コールバックの代替としてシグナルとスロットが利用できます。QPushButton も内部的にはシグナルとスロットを利用しています。

sample.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from PySide2.QtCore import QObject, Signal, Slot
from time import sleep

class MyQObject(QObject): # QObject を継承すること
    clicked = Signal()
    changed = Signal(int)

    def __init__(self):
        super(MyQObject, self).__init__()
        self.clicked.connect(self.onClicked)
        self.changed.connect(self.onChanged)

    @Slot()
    def onClicked(self):
        print("clicked")

    @Slot(int)
    def onChanged(self, num):
        print("changed: %d" % num)

    def f(self):
        self.clicked.emit()
        self.changed.emit(123)

def Main():
    obj = MyQObject()

    while True:
        obj.f()
        sleep(1.0)

if __name__ == '__main__':
    Main()

実行例

$ python sample.py
clicked
changed: 123
clicked
changed: 123
...

プロパティ

Property() を利用すると、Qt オブジェクトと Python オブジェクトのプロパティをバインディングできます。

sample.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import exit, argv
from PySide2.QtCore import Property
from PySide2.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication

class MyWidget(QWidget):

    def __init__(self):
        super(MyWidget, self).__init__()
        self.label = QLabel("xxxx")
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.label)
        self.setLayout(self.layout)

    def GetLabelText(self):
        return self.label.text()

    def SetLabelText(self, text):
        self.label.setText(text)

    labelText = Property(str, GetLabelText, SetLabelText)

def Main():
    app = QApplication(argv)
    widget = MyWidget()
    widget.show()

    print(widget.labelText)
    widget.labelText = "yyyy"

    exit(app.exec_())

if __name__ == '__main__':
    Main()

QLabel の初期値が widget.labelText で取得できています。逆に widget.labelText に値を設定すると QLabel に反映されます。

$ python sample.py
xxxx

Uploaded Image

バージョン情報の確認

ipython 等で以下のコマンドを実行して PySide および Qt のバージョンを確認できます。

PySide バージョン

import PySide2.QtCore
print(PySide2.__version__)
→ e.g. 2.0.0

PySide をコンパイルした Qt バージョン

print(PySide2.QtCore.__version__)
→ e.g. 5.11.0

実行時に利用されている Qt バージョン

print(PySide2.QtCore.qVersion())
→ e.g. 5.11.0

都度参照するためのドキュメント

関連ページ
    概要 Qt Quick は、こちらのページで記載した Qt フレームワークにおいて UI 作成のために利用されるライブラリです。Qt Quick で利用される言語 QML (Qt Modeling Language) について、基本的な使い方を記載します。 検証用のコード sample.py #!/usr/bin/python # -*- coding: utf-8 -*- from s
    概要 リモートホストの X Window System (X11) を転送して利用する方法を、SSH および Virtual Network Computing (VNC) の二つの方法について記載します。 SSH サーバとホストの両方で X11 転送を有効にすることで利用できます。アプリケーション毎に転送できます。
    概要 ロボットアプリケーションの開発環境の一つ OpenRAVE (Open Robotics Automation Virtual Environment) の環境を構築するための手順を記載します。ここでは特に Debian9 を利用します。 インストール 依存パッケージ ビルドツール関連 sudo apt install git build-essential cmake