モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

目次目次を開く/閉じる

Qt for Python (PySide2) の基本的な使い方

モーダルを閉じる

ステッカーを選択してください

お支払い手続きへ
モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2018/06/20
最終更新最終更新
2023/11/17
記事区分記事区分
一般公開

目次

    インフラ構築と自動化が得意。TerraformとAnsibleでインフラを自動構築するお仕事が多め

    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()
    

    古い環境の場合は必要な共有ライブラリが存在せずにエラーになります。新しい 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()
    

    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
      }
    }
    

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

    #!/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()
    

    関数を実行する 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()
    

    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()
    

    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()
    

    シグナルとスロット

    コールバックの代替としてシグナルとスロットが利用できます。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
    

    バージョン情報の確認

    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
    

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

    Likeボタン(off)0
    詳細設定を開く/閉じる
    アカウント プロフィール画像

    インフラ構築と自動化が得意。TerraformとAnsibleでインフラを自動構築するお仕事が多め

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    >>さらに詳しくステッカーを贈る
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      ログインする

      関連記事

      • QML の基本的な使い方
        サムネイル画像-1779950179
        Qt Quick は、Qt フレームワークにおいて UI 作成のために利用されるライブラリです。Qt Quick で利用される言語 QML (Qt Modeling Language) について、基本的な使い方を記載します。 検証用のコード sample.py #!/usr/bin/python # -*- coding: utf-8 -*- from sys import exit
        OharaOhara9/7/2021に更新
        いいねアイコン画像0
      • Python コードスニペット (条件分岐)
        if-elif-else sample.py #!/usr/bin/python # -*- coding: utf-8 -*- # コメント内であっても、ASCII外の文字が含まれる場合はエンコーディング情報が必須 x = 1 # 一行スタイル if x==0: print 'a' # 参考: and,or,notが使用可能 (&&,||はエラー) elif x==1: p...
        coderinacoderina10/25/2015に更新
        いいねアイコン画像0
      • Python コードスニペット (リスト、タプル、ディクショナリ)
        リスト range 「0から10まで」といった範囲をリスト形式で生成します。 sample.py print range(10) # for(int i=0; i<10; ++i) ← C言語などのfor文と比較 print range(5,10) # for(int i=5; i<10; ++i) print range(5,10,2) # for(int i=5; i<10;...
        coderinacoderina9/28/2020に更新
        いいねアイコン画像0
      • ZeroMQ (zmq) の Python サンプルコード
        ZeroMQ を Python から利用する場合のサンプルコードを記載します。 Fixing the World To fix the world, we needed to do two things. One, to solve the general problem of "how to connect any code to any code, anywhere". Two, to wra...
        coderinacoderina9/7/2021に更新
        いいねアイコン画像0
      • Matplotlib/SciPy/pandas/NumPy サンプルコード
        サムネイル画像-9ca9c78897
        Python で数学的なことを試すときに利用される Matplotlib/SciPy/pandas/NumPy についてサンプルコードを記載します。 Matplotlib SciPy pandas [NumPy](https://www.numpy
        パンダパンダ12/26/2024に更新
        いいねアイコン画像0