Introduce
インストール
PyQtフレームワークを使用するには、まずpipパッケージマネージャを使用してPyQtをインストールする必要があります。
pipがインストールされている場合は、次のコマンドを実行して最新バージョンのPyQtをインストールしましょう。
$ pip install pyqt6
pip install pyqt6` が失敗した場合は、ここでインストールの変更を確認することができます。
PyQt入門
PyQtは、QtライブラリとPythonプログラミング言語の産物であるツールキットです。
PyQtはPythonで最もよく使われるGUIフレームワークの1つなので、よく書かれた大量のドキュメントと大きなコミュニティが存在します。
PyQtのコアクラスの1つは QWidget
クラスで、Widgetの実装です。
ウィジェットはGUIコンポーネントであり、ユーザーインターフェースの中核となる構成要素です。
ウィジェットは、ラベル、ボタン、メニュー、コンボボックス、スクローラー、ツールバー、ファイルダイアログ、などなどです。
ウィジェットはたくさんあり、使いこなすには時間がかかります。
ここでは、ほとんどすべてのPyQtアプリケーションに存在する、最も一般的に使用されるウィジェットを説明します。
アプリケーションのフレーム上でのこれらのウィジェットの相対的な順序は、レイアウトマネージャによって決定され、管理されます。
ここでは、利用可能なレイアウトマネージャと、それらがGUIコンポーネントの配置にどのような影響を与えるかについても見ていきます。
すべてのPyQtアプリケーションのエントリポイントは、アプリケーション自体を表すQApplication
クラスです。
このクラスは、すべての初期化処理と、描画する “キャンバス “を処理します。
注:アプリケーションのウィンドウやモーダルボックスの数に関係なく、常に1つの QApplication
インスタンスしか存在しません。
それでは、思い切ってPyQtアプリケーションを初期化し、空のキャンバスでウィンドウを初期化してみましょう。
import sys
from PyQt6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
root = QWidget()
root.setWindowTitle('A Simple PyQt6 App')
root.setGeometry(100, 100, 280, 80)
root.show()
sys.exit(app.exec())
このコードを実行すると、単純なアプリケーションが初期化されます。
この初期化を一行ずつ見ていきましょう。
まず、Pythonの組み込みモジュールである sys
をインポートし、Pythonの実行環境を操作するための関数を提供します。
この例では、ユーザーが “X “ボタンを押したときのアプリケーションの終了ステータスを処理するために、このモジュールを使用します。
import sys
次に、PyQt6.QtWidgets
モジュールから QApplication
(ベース) と QWidget
(GUIコンポーネント) をインポートします。
from PyQt6.QtWidgets import QApplication, QWidget
次に、この行はQTの要求事項です。
これはPyQTを初期化します。
sys.argvには、アプリケーションに渡されるすべてのコマンドライン引数のリストが含まれます。
あなたが作成するすべてのGUIアプリケーションは、QApplicationのインスタンスを正確に1つ持たなければなりません。
さて、QApplication
はPyQtアプリケーションの開発に関わるほとんどの要素の初期化を担当するので、最初にそれをインスタンス化したいと思います。
コマンドライン引数を渡すこともできるので、コンストラクタは sys.argv
引数を受け取ります。
app = QApplication(sys.argv)
さて、QApplication
自身は実際にはウィンドウを持ちません。
ウィンドウを持たずにアプリケーションを実行すると、私たちには見えない結果が得られます。
実際にウィンドウを導入するには、Window Widgetとしても知られるRoot Widgetを作成します。
いずれにしても、他のコンポーネントを追加していく最下部のWidgetを表します。
root = QWidget()
setWindowTitle()`を使って、カスタムウィンドウタイトルを設定しましょう。
root.setWindowTitle('A Simple PyQt6 App')
setGeometry()メソッドは 4 つの引数を受け取ります。
x_coordinate, y_coordinate
, width
& height
. x_coordinateと
y_coordinate` は Window を表示する際の原点を定義します。
root.setGeometry(100, 100, 280, 80)
さて、作成したGUIを画面に表示するために、root
の show()
メソッドを呼び出します。
root.show()
最後に、app.exec()
でアプリケーションを実行し、ユーザーがアプリケーションを閉じるまでアプリケーションのメインループを実行します。
sys.exit(app.exec())
レイアウトマネージャー
PyQtのレイアウトマネージャは、GUI上でPyQtウィジェットを配置する生産的な方法を提供します。
ウィジェットをうまく配置すればするほど、GUIアプリケーションはより洗練され、プロフェッショナルなものになります。
ボタンとボタンの間に不格好で大きなスペースがあり、スペースがあまり利用されていないのは、あまりユーザーフレンドリーではありません。
逆に、ボタンが近すぎると、誤クリックしやすくなります。
最も人気のあるPyQtレイアウトマネージャークラスは次のとおりです。
- QVBoxLayoutはウィジェットを縦に並べます。
- QHBoxLayoutはウィジェットを水平に配置します。
- QGridLayout はウィジェットをグリッドに配置します。
-
- QFormLayout はウィジェットを2列に並べます。
PyQtでGUIアプリケーションを作成する場合、同じアプリケーションでも、ウィンドウの種類に応じて4つの汎用レイアウトマネージャのうち2つ以上を使用することがよくあります。
前の例を活用して、QPushButton
のようないくつかのウィジェットを追加し、それらをレイアウトマネージャで管理することでアップグレードしてみましょう。
1. QVBoxLayout
ボックスレイアウトマネージャー(QVBoxまたはQHBoxの両方)は、親レイアウトまたはWidgetから取得したすべてのスペースを使用し、いくつかのボックスに分割されます。
マネージャによって管理される各Widgetは、1つのボックスを埋めることになります。
QVBoxLayout` では、Widget を縦に並べることができます。
レイアウトは、ウィジェットを上から下へと順番に追加していきます。
つまり、最初に追加したWidgetが一番上のWidgetになり、最後に追加したWidgetがレイアウトの一番下のWidgetになります。
それでは、QVBoxLayout
を使ってアプリケーションにいくつかのボタンを追加してみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the root Widget/Window
window = QWidget()
# Create the Vertical Box Layout Manager, setting `window` as parent by passing it in the constructor.
layout = QVBoxLayout(window)
# Create and add the QPushButton Widgets to the `layout`
layout.addWidget(QPushButton('One'))
layout.addWidget(QPushButton('Two'))
layout.addWidget(QPushButton('Three'))
layout.addWidget(QPushButton('Four'))
layout.addWidget(QPushButton('Five'))
# Show the parent Widget
window.show()
# Run the main Qt loop and allow safe exiting
sys.exit(app.exec())
このコードを実行すると、画面上に次のようなウィンドウが表示されます。
このウィンドウには5つのボタンがあり、上から下へ垂直に並んでいます。
ボタンをクリックしても何も起こらないのは、まだボタンに関するロジックを追加していないからです。
2. QHBoxLayout
QHBoxLayout` はボックスレイアウトで、Widget を水平に配置することができます。
レイアウトは左から右へとWidgetを追加していきます。
つまり、最初に追加されたウィジェットが一番左のウィジェットになり、最後に追加されたウィジェットがレイアウトの一番右のウィジェットになります。
縦長のボックスを横長に変更してみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QHBoxLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget of the Widgets added to the layout
window = QWidget()
# Create the Horizontal Box Layout Manager, setting `window` as parent by passing it in the constructor
layout = QHBoxLayout(window)
# Create and add the QPushButton Widgets to the `layout`
layout.addWidget(QPushButton('One'))
layout.addWidget(QPushButton('Two'))
layout.addWidget(QPushButton('Three'))
layout.addWidget(QPushButton('Four'))
layout.addWidget(QPushButton('Five'))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
このコードを実行すると、次のようなウィンドウが表示されます。
このウィンドウには、5つのボタンが水平に、左から右へと並んでいます。
3. QGridLayout
QGridLayout`は、Widgetを行と列のグリッドに配置したいときに使用します。
このグリッドでは、座標を使って各Widgetの相対位置を次のように定義します。
(row, column) のように定義します。
Note: row
と column
の両方とも整数である必要があります。
また、QGridLayout
は親のレイアウトやWidgetから取得したスペースをすべて使って、いくつかのボックスに分割します。
以前のレイアウトマネージャと同様に、それぞれのWidgetはそれ自身のボックスに入ります。
ボックスの数はウィジェットの数とその座標によって自動的に計算されます。
ここでは、水平ボックスレイアウトの代わりに QGridLayout
を使ってみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QGridLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget
window = QWidget()
# Create the buttons
button1 = QPushButton('One')
button2 = QPushButton('Two')
button3 = QPushButton('Three')
button4 = QPushButton('Four')
button5 = QPushButton('Five')
# Create the QGrid Layout Manager
layout = QGridLayout(window)
# Add button Widgets to the QGridLayout
# addWidget([object], [row number], )
layout.addWidget(button1,0,0)
layout.addWidget(button2,1,0)
layout.addWidget(button3,2,0)
layout.addWidget(button4,0,1)
layout.addWidget(button5,0,2)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
このコードを実行すると、画面上に次のようなウィンドウが表示されます。
このウィンドウには5つのボタンがあり、 addWidget()
メソッドで指定したように配置されています。
このメソッドは3つの引数を受け取ります。
- グリッドに配置するWidget。
-
- 配置する行
-
- 配置される列。
オプションの第4引数として alignment
があり、ボックス内の各Widgetのアライメントオプションを定義する。
デフォルトの値 (Qt.Alignment.AlignCenter
) は、各Widgetがボックスの中心から外側に向かうように配置されることを意味します。
Qt` モジュールについては、後のセクションで詳しく説明します。
最後に、columnSpan
と rowSpan
という引数があり、ウィジェットが複数の行や列をまたぐかどうかを定義します。
addWidget(Widget, fromRow, fromColumn, rowSpan, columnSpan, Qt.Alignment)
行と列のスパンと Qt.Alignment
を設定しましょう(PyQt6以前では Qt.AlignLeft
となります)。
# New import other than the ones already present
from PyQt6.QtCore import Qt
# addWidget([object], [row number], , [columnSpan], [rowSpan], Qt.Alignment)
layout.addWidget(button1, 0, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button2, 1, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button3, 2, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button4, 0, 1, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button5, 0, 2, 1, 1, Qt.Alignment.AlignLeft)
AlignLeft、
AlignTop、
AlignBottom、
AlignRight、
AlignCenter`を使用することができます。
ウィンドウのサイズを変更すると、各ボタンが中央ではなく、それぞれのボックスの左側に整列していることがわかります。
一方、 AlignCenter
を使用したり、デフォルトのままにしておくと、次のようになります。
4. QFormLayout
QFormLayout` は、デスクトップアプリケーションのフォームレイアウトを簡単に作成できるようにします。
QFormLayout は 2 つのカラムから構成されます。
1 つはラベル用、もう 1 つは入力用です。
一般的には、入力ウィジェットとして QLineEdit
や QSpinBox
、 QComboBox
、あるいは同様の入力ウィジェットが使用されます。
それでは、QFormLayout
を作成してみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
def addLabel(layout, text):
layout.addWidget(QLabel(text))
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a label Widget and add it to the layout
label = QLabel('Enter some text!')
layout.addWidget(label)
line_edit = QLineEdit()
layout.addWidget(line_edit)
# Create a QPushButton object with a caption on it
qbtn= QPushButton('Add Label')
# Add the QPushButton to the layout
layout.addWidget(qbtn)
# Close the application when the button is pressed
# Here I am using slots & signals, which I will demonstrate later in this tutorial
qbtn.clicked.connect(lambda:addLabel(layout, line_edit.text()))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
このコードを実行すると、次のようなウィンドウが表示されます。
このウィンドウには、2つのラベルと2つの QLineEdit
フィールドが addRow()
メソッドによって追加されています。
addRow()`は2つの引数を受け取ります。
- ラベルテキスト (文字列)
- 入力ウィジェット (QWidget)
このメソッドは自動的に新しい QLabel
オブジェクトを作成し、labelText をテキストとして追加します。
さらに、文字列の代わりに QLabel
引数を追加することで、自動変換をスキップすることもできます。
layout.addRow(QLabel('Nickname:'), QLineEdit())
layout.addRow(QLabel('Score:'), QLineEdit())
この結果も
ウィジェット
さて、PyQtが提供するレイアウトマネージャについてよく知ったところで、それらが何を管理しているのかに飛び込んでみましょう。
ウィジェットはQtの重要な概念であり、結果的にPyQtもそうなっています。
ウィジェットは、UIのグラフィカルなコンポーネントを反映します。
ユーザーインターフェースは、ウィンドウ内に配置された複数のウィジェットで構成されています。
各ウィジェットは、その外観と動作をモデル化するための一連の属性とメソッドを含んでいます。
PyQt6では、現在40以上のウィジェットが提供されており、独自のウィジェットを作成することも可能です。
PyQt5以降、基本クラスが異なるモジュールに再編成されました。
PyQt6では、いくつかの基本的な高レベルのモジュールが使用されています。
-
Qt
: 以下のモジュールはすべて、この1つのモジュールにまとめられています。 -
QtCore
: QtCore:
QtCore` モジュールには、他のモジュールで使用される、グラフィカルでないコアモジュールがすべて含まれています。シグナル、スロットなどは、このモジュールで実装されています。 -
QtWidgets
: このモジュールには、PyQt6 で利用できるほとんどのウィジェットが含まれています。 -
QtGui
:QtGui
はQtCore
モジュールを継承しており、GUI コンポーネントが含まれています。 -
QtSql
: このモジュールは、SQL データベースのデータベース統合機能を実装している。 -
QtMultimedia
: 低レベルのマルチメディア機能は、このモジュールに含まれています。 -
QtNetwork
: ネットワークプログラミングを実装するためのクラスです。QtNetwork`: ネットワークプログラミングを実装するためのクラス(ソケット、SSL 処理、ネットワークセッション、DNS、…)がこのモジュールに含まれます。
このセクションでは、QtWidgetsモジュールとそのウィジェットに焦点を当てます。
2. シグナルとスロット
PyQtのシグナルとスロットは、オブジェクト間の通信に使用されます。
この仕組みはQtフレームワークの中心的な機能です。
例えば、ユーザーがDeleteボタンをクリックした場合、ウィンドウの delete()
関数が呼び出されるようにしたいとします。
このために、2つのウィジェットは互いに通信する必要があります。
イベント
イベントとは、GUI上でユーザが実行するアクションのことです。
イベントが発生すると、対応するWidgetからシグナルが発信されます。
Qtで利用できるウィジェットには、多くの定義済みのシグナルがありますが、いつでも追加のカスタムシグナルを作ることができます。
スロットは、シグナルに応答して呼び出される関数です。
Qtで利用可能なWidgetには多くの定義済みのスロットがありますが、独自のスロットを作成することは非常に一般的なことです。
シグナルとスロットの最も便利な機能は以下の通りです。
- シグナルは他のシグナルに接続することができます。
- シグナルは1つまたは多くのスロットに接続することができます。
- 1つのスロットは1つまたは多くのシグナルに接続することができます。
シグナルをスロットに接続する一般的な構文は以下の通りです。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt6.QtCore import Qt
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a label beforehand
firstLabel = QLabel('Countrycode: BE')
secondLabel = QLabel('Brussels waffles are the best food ever.')
# Add labels to layout, creating an anonymous label while adding
layout.addWidget(firstLabel)
layout.addWidget(secondLabel, alignment = Qt.Alignment.AlignJustify)
layout.addWidget(QLabel('The Belgian flag consists of the colors black, yellow and red', wordWrap=True), alignment = Qt.Alignment.AlignLeft)
# using setText() we can change the caption of a label
firstLabel.setText('Belgium is a country located in Europe')
firstLabel.setAlignment(Qt.Alignment.AlignRight)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
このコードは slot_function
を Widget.signal
に接続し、シグナルが発信されるたびに slot_function()
関数が呼び出されるようにします。
予期しない振る舞いを避けるために、すべてのスロット関数に @pyqtSlot()
デコレータを付けることが重要です。
widget.signal.connect(slot_function)
では、シグナルとスロットの仕組みを利用したアプリケーションを作成してみましょう。
コンソールにメッセージを表示するボタンを設置します。
from PyQt6.QtCore import pyqtSlot
# Slot function - Note the @pyqtSlot() annotation!
@pyqtSlot()
def hello_world():
print('Button is clicked, Hello World!')
このコードを実行すると、画面上に次のようなウィンドウが表示されます。
このコードを実行し、ボタンをクリックすると、コンソールに次のテキストが出力されます。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton
from PyQt6.QtCore import pyqtSlot
@pyqtSlot()
def hello_world():
print('You shall not pass!')
# Create the Qt Application
app = QApplication(sys.argv)
# Create a QPushButton Object
button = QPushButton('Click me')
# Connect the button to the hello_world slot function
button.clicked.connect(hello_world)
# Show the button to the user
button.show()
# Run the main Qt loop
sys.exit(app.exec())
3. ボタン
さて、アプリケーションの他のGUIコンポーネントにラベルを付けることができるようになりました。
これから実装する最初のインタラクティブなコンポーネントである QButton
を見てみましょう。
ボタンは結果につながります。
私たちの場合は、特定の機能を呼び出すために使用します。
デフォルトのボタンとして、OK、Yes、No、Cancel、Apply、Close があらかじめ用意されているが、カスタムテキストを追加することもできる。
ボタンにイベントハンドラを付けて、ボタンが押されたときに関数やその他のコードを実行することができます。
ここでは、ユーザーが画面に QLabel
を追加できるようなボタンを作ってみましょう。
ユーザーが QLineEdit
にテキストを入力し、ボタンが押されたことを検出したら、 QLineEdit
からデータを収集し、そのテキストを使って新しい QLabel
のテキストを設定し、レイアウトに追加してみましょう。
ボタンはクリックイベントハンドラとして呼び出し可能な関数が渡されることを期待しているので、新しい関数 add_label()
を定義して、指定したレイアウトに任意の QLabel
を追加できるようにします。
You shall not pass!
では、GUIを書いて、ユーザーから提供されたテキストでこの関数を呼び出してみましょう。
def addLabel(layout, text):
layout.addWidget(QLabel(text))
このコードを実行すると、QLineEdit
フィールドにテキストを書き込むことができ、Add Labelを押すと、QLabel
としてレイアウトに追加されます。
4. 行の編集
これまで2回にわたって QLineEdit
ウィジェットについて簡単に見てきましたが、このウィジェットが提供する機能を少し見てみましょう。
前に見たように、ユーザーがテキスト行を入力することができます。
これらは、既存のデータを追加または編集するために、ユーザーデータを収集するための初歩的な方法です。
もちろん、コピー、ペースト、アンドゥ、リドゥなどの一般的な操作を行うことができます。
これらのメソッドで使用する一般的なメソッドをいくつか紹介します。
-
setAlignment()
は、アラインメント定数に従ってキャプションのアラインメントを再び調整します。 -
setMaxLength()
– ユーザーが超えられない最大文字数を設定します。 -
text()
–QLineEdit
内のテキストを取得します。 -
setText()
–QLineEdit
にテキストを設定します。 -
clear()
–QLineEdit
の内容を全て消去します。
前の例を書き直してみましょう。
今回は、すでに QLineEdit
に定義されたテキストがあり、新しいラベルを追加する代わりに、すでにある QLabel
を変更します。
有名な引用文のコーパスを持ち、要求に応じてランダムな引用文を表示する、初歩的な引用文アプリを作成します。
新しい名言を追加して「名言の追加」をクリックすると、名言のリストが拡張され、「名言の取得」で新しい名言を取得する際に名言のプールに含まれるようになります。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
def addLabel(layout, text):
layout.addWidget(QLabel(text))
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a Qlabel Widget and add it to the layout
label = QLabel('Enter some text!')
layout.addWidget(label)
# Create a QLineEdit to collect user data
line_edit = QLineEdit()
layout.addWidget(line_edit)
# Create a QPushButton object with a caption on it
qbtn= QPushButton('Add Label')
layout.addWidget(qbtn)
# When clicked, perform a callable function - `addLabel()`
qbtn.clicked.connect(lambda:addLabel(layout, line_edit.text()))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
この結果
5. Combo Boxes
Comboboxes allow users to pick from a list of options – similar to the <select
tag in HTML. These can be achieved through the QComboBox
Widget. The basic QComboBox
is a read-only Widget, meaning the user has to pick exclusively from the pre-defined list and can’t add their own options. However, they can also be editable – which allows the user to add a new option if none fit their needs.
Given below are the most commonly used methods of the QComboBox class:
-
addItem()
adds a string to the collection -
addItems()
will add each of the strings in the given list to the collection -
Clear()
is used to delete all items in the collection -
count()
is used to retrieve the number of items in the collection -
currentText()
is used to retrieve the text of the currently selected item -
itemText()
accepts anindex
argument and returns the text of that item -
currentIndex()
returns the index of the currently selected item
Let’s create a mini ordering app, where a user selects an item from a menu and enters a comment for the restaurant. Then, when a button is clicked – this order is shown to the user:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
from PyQt6.QtCore import pyqtSlot
import random
# Deifne helper functions as PyQt Slots
@pyqtSlot()
def randomQuote():
# Set label to random quote from the list
quoteLabel.setText(random.choice(quotes))
@pyqtSlot()
def addQuote():
# Add new quote to the list and clear the input field
quotes.append(newQuoteLineEdit.text())
newQuoteLineEdit.clear()
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
# Default quote list
quotes = ['Do or do not, there is no try.', 'The meaning of life is 42']
# Get a random quote for the user
quoteLabel = QLabel(random.choice(quotes))
# QLineEdit field to collect new quote information, and a button for it
newQuoteLineEdit = QLineEdit('Add new quote...')
addQuoteButton = QPushButton('Add New Quote')
# Button to get random quote
getQuoteButton = QPushButton('Get Random Quote')
# Add the previous Widgets to the layout
layout.addWidget(newQuoteLineEdit)
layout.addWidget(quoteLabel)
layout.addWidget(addQuoteButton)
layout.addWidget(getQuoteButton)
# On click - call the slots (functions)
getQuoteButton.clicked.connect(randomQuote)
addQuoteButton.clicked.connect(addQuote)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
では、注文を行い、それにリクエストを付けてみましょう。
6. ラジオボタンとチェックボックス
ラジオボタンとチェックボックスの用途はほとんど同じで、複数の選択肢から1つを選ぶことができます。
ただ、ラジオボタンはユーザーが一つの選択肢しか選べないように制限したいときに使い、チェックボックスはユーザーが複数の選択肢を選べるようにしたいときに使うという違いがあります。
例えば、新規顧客か旧顧客かを強制的に選択させ(同時に両方は選択できない)、登録したいサービスを複数選択できるようにすることができます。
これらは当然ながら QRadioButton
と QCheckBox
として実装されています。
チェックされているかどうかの確認、checked/uncheckedの設定、テキストの設定、ラベルのテキストを取得することができます。
-
setChecked()
はラジオボタンやチェックボックスをチェックします。 -
setText()
は、ボタンやチェックボックスに関連付けられたラベルを設定します。 -
text()
は、ボタン/チェックボックスのラベルを取得します。 -
isChecked()
は、ボタン/チェックボックスが選択されているかどうかをチェックする
それでは、架空の洗車場が提供するいくつかのサービスをユーザーが選択できるような、シンプルなアプリを作ってみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit, QComboBox
from PyQt6.QtCore import pyqtSlot
@pyqtSlot()
def placeOrder():
order_format = "Placed order for {} with comment '{}'"
layout.addWidget(QLabel(order_format.format(comboBox.currentText(), commentLineEdit.text())))
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
label1 = QLabel('Pick one of the following options:')
comboBox = QComboBox()
comboBox.addItems(['Pasta', 'Pizza', 'Lasagna'])
layout.addWidget(label1)
layout.addWidget(comboBox)
commentLineEdit = QLineEdit('Comment for the restaurant...')
placeOrderButton = QPushButton('Place order')
layout.addWidget(commentLineEdit)
layout.addWidget(placeOrderButton)
placeOrderButton.clicked.connect(placeOrder)
window.show()
sys.exit(app.exec())
これは、アンケートのようなアプリで、自分が古い顧客か新しい顧客かを選択させ、洗車場が提供するサービスの中から選択させるように促します。
7. テーブルウィジェットを使ってデータを表示する
QTableWidget` は、PyQt で Excel のような素晴らしいテーブルを作成し、そこにデータを表示できるようにする Widget で、多くの設定を必要としません。
その中にデータを表示することができます。
すべてのテーブルは、行と列を持つ、アイテムベースのテーブルです。
テーブルの情報を表示する方法は、QTableWidget
を使うことだけではないことに注意してください。
データモデルは QTableView
Widget を使って作成し、表示することができます。
しかし、QTableWidget
は本来 QTableView
を使って実際にテーブルを作成するので、最初からテーブルを使うという上位のアプローチをとることになります。
テーブルの列と行の性質を考えると、テーブルのデータを保持するために辞書を作成したり、リストのリストを作成したりすることも快適にできます。
テーブルを作成する際には、データを追加する前に列と行の数を設定し、ループを通してデータを投入することになるでしょう。
-
setRowCount()
は行数を設定します。 -
setColumnCount()
はカラムの数を設定します。 -
setHorizontalHeaderLabels()
は水平方向のヘッダーのラベルを設定します。
では、北欧の国とその首都を含む表を含む簡単なアプリケーションを作成してみましょう。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QRadioButton, QCheckBox
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
label_customer = QLabel('Pick one of the following options:')
# Create two radio buttons for the customer, assuming they might be a new customer
qradioButton = QRadioButton('Old Customer')
qradioButton2 = QRadioButton('New Customer')
qradioButton2.setChecked(True)
layout.addWidget(label_customer)
layout.addWidget(qradioButton)
layout.addWidget(qradioButton2)
label_service = QLabel("Pick the services you'd like:")
qCheckBox = QCheckBox('Car Wash')
qCheckBox2 = QCheckBox('Car Polish')
qCheckBox3 = QCheckBox('Vacuuming')
layout.addWidget(label_service)
layout.addWidget(qCheckBox)
layout.addWidget(qCheckBox2)
layout.addWidget(qCheckBox3)
window.show()
sys.exit(app.exec())
このコードを実行すると、画面上に次のようなウィンドウが表示されます。
8. ツリーウィジェットでデータを表示する
ツリーウィジェットは、ファイル階層や要素の特定のリストに関連するサブリストなど、ツリー状の構造を表示するのにとても便利です。
このタイプのウィジェットに対応するために、PyQtは QTreeWidget
を提供しています。
QTableWidgetが
QTableViewの上に構築されているのと同様に、
QTreeWidgetは
QTreeView` の上に構築されています。
ツリーはヘッダーとアイテムから構成される。
ヘッダはカラムの名前である。
各アイテムには、複数のアイテムを割り当てることができる。
例えば、アイテムはディレクトリで、そのディレクトリ内のファイルがアイテムになります。
また、アイテムはタスクで、そのタスクに割り当てられた人がアイテムになります。
ツリーウィジェットで使用する一般的なメソッドをいくつか紹介します。
-
setHeaderLabels()
は、ツリーウィジェットのカラム名を設定します。 -
clear()
は、ツリーからすべてのデータをクリアします。 -
editItem()
は、ツリー内の特定のアイテムを編集します。 -
addTopLevelItem()
: トップレベルのアイテムを追加する -
addTopLevelItems()
– トップレベルのアイテムのリストを追加する
各アイテムは、親コンポーネントに割り当てることができます。
トップレベルアイテムは QTreeWidget
自身に割り当てることができ、低レベルアイテムは既に存在するトップレベルアイテムに割り当てることができます。
しかし、あまりに多くのレベルがあると、ユーザーを混乱させることになります。
では、早速買い物リストを作ってみましょう。
食品
と家具
をトップレベルアイテム(買いたいもののカテゴリ)として、その子アイテムが実際のアイテムそのものになります。
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import (QApplication, QTableWidget, QTableWidgetItem)
from PyQt6.QtGui import QColor
# Declare our table values
nordic_countries = [('Norway', 'Oslo', 'Yes'),
('Iceland', 'Reykjavik', 'Yes'),
('Denmark', 'Copenhagen', 'Yes'),
('Belgium', 'Brussels','No')]
# Create the Qt Application
app = QApplication(sys.argv)
table = QTableWidget()
# Configure QTableWidget to have a number of rows equivalent to the amount of items from the nordic_countries struct
table.setRowCount(len(nordic_countries))
# Since every country in our 'nordic_countries' variable has the same amount of attributes
# we take the amount (3) of the first country and use this as the number of columns
table.setColumnCount(len(nordic_countries[0]))
# Set the Horizontal headers using setHorizontalHeaderLabels()
table.setHorizontalHeaderLabels(['Country', 'Capital', 'Scandinavian?'])
# Loop through every country in our 'nordic_countries' variable
for i, (country, capital, scandinavian_bool) in enumerate(nordic_countries):
# Make a QTableWidgetItem --> acts as an item in a table
item_country = QTableWidgetItem(country)
item_capital = QTableWidgetItem(capital)
item_scandinavian_bool = QTableWidgetItem(scandinavian_bool)
# Set the items: item, index, QTableWidgetItem
table.setItem(i, 0, item_country)
table.setItem(i, 1, item_capital)
table.setItem(i, 2, item_scandinavian_bool)
# Finally show the table
table.show()
# Launch the application
sys.exit(app.exec())
このコードを実行すると、画面上に次のようなウィンドウが表示されます。
結論
In this guide, we’ve jumped into PyQt – Python’s wrapper for the popular Qt library.
We’ve taken a look at some of the key concepts of the library, and jumped into working with it through Layout Managers, got familiar with Widgets and created several really simple demonstration applications that showcase how you can use them.