yu00’s blog

プログラミングに関する備忘録です

ウィジェットの自動伸縮の設定

PyQt5入門 PythonでGUI作成 - yu00’s blog


レイアウトでウィジェットを配置するとき,
ウィジェットは自動的に伸縮します.
ここでは自動伸縮の設定について説明します.

自動伸縮するかどうか

自動伸縮をするしないを設定するには,
QWidget.setSizePolicy()を使います.

QWidget.setSizePolicy(horizontalPolicy, verticalPolicy) -> none

QWidget.setSizePolicy(QSizePolicy) -> none

自動伸縮を設定します
horizontalPolicy, verticalPolicy:QSizePolicy.Policy型, 横方向,縦方向の自動伸縮

QSizePolicy.QSizePolicy(horizontalPolicy, verticalPolicy, type = DefaultType) -> QSizePolicy

horizontalPolicy, verticalPolicy:QSizePolicy.Policy型, 横方向,縦方向の自動伸縮


縦方向,横方向それぞれの自動伸縮は次のどれかを指定します.

QSizePolicy.Policy

QSizePolicy.Fixed
ウィジェットのサイズがQWidget.sizeHint()に固定されます.

QSizePolicy.Minimum
ウィジェットのサイズはsizeHint()以下になりません.
拡大はされます.

QSizePolicy.Maximum
ウィジェットのサイズはsizeHint()以上になりません.
縮小はされます.

QSizePolicy.Preferred
基本sizeHint()のサイズになりますが,拡大も縮小もします.

QSizePolicy.Expanding
基本sizeHint()のサイズになりますが,拡大も縮小します.
また,拡大のときは特別な領域も使用して
できるだけ大きくなるようにします.

QSizePolicy.MinimumExpanding
sizeHint()以下になりません.
拡大のときはできるだけ大きくなるようにします.

QSizePolicy.Ignored
ウィジェットのサイズをできるだけ大きくなるようにします.

サンプルコード

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout,\
    QSizePolicy

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = QWidget()

    button1 = QPushButton('1')
    button2 = QPushButton('2')
    
    # 自動伸縮を設定
    button1.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
    button2.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
    
    layout = QHBoxLayout()
    layout.addWidget(button1)
    layout.addWidget(button2)
    window.setLayout(layout)
    
    window.show()
    sys.exit(app.exec_())

実行例

f:id:yu00:20150906212500p:plain
ボタン2は縦,横とも拡大します.

ウィジェットのサイズ比

2つウィジェット並べてサイズ比を1対2にしたいなど,各ウィジェットのサイズの比率
を変更するにはストレッチを設定します.
ストレッチはQSizePolicyで変更できます.
ただしウィジェットの最小サイズより小さくはならないので注意してください.

QSizePolicy.setHorizontalStretch(stretchFactor) -> none

横方向のストレッチを変更します.
stretchFactor:int型,サイズ比

QSizePolicy.setVerticalStretch(stretchFactor) -> none

縦方向のストレッチを変更します.

サンプルコード

ボタンを2対3の比率で横に配置するプログラムを書いてみます.

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout,\
    QSizePolicy

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = QWidget()

    button1 = QPushButton('1')
    button2 = QPushButton('2')

    # ボタンのサイズポリシーを取得
    sizePolicy1 = button1.sizePolicy()
    sizePolicy2 = button2.sizePolicy()
    # ストレッチを2対3にセット
    sizePolicy1.setHorizontalStretch(2)
    sizePolicy2.setHorizontalStretch(3)
    # サイズポリシーをセット
    button1.setSizePolicy(sizePolicy1)
    button2.setSizePolicy(sizePolicy2)
    
    layout = QHBoxLayout()
    layout.addWidget(button1)
    layout.addWidget(button2)
    window.setLayout(layout)
        
    window.show()
    sys.exit(app.exec_())

実行例

f:id:yu00:20150906222534p:plain

QWidgetクラス

PyQt5入門 PythonでGUI作成 - yu00’s blog

PyQt5ではウェジェットでウィンドウを作成し,
その中にボタンやラベルなどの部品を配置していきます.
ここではウェジェットの基本的な使い方を説明します.

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

まずはわかりやすいように,QWidgetを継承した自分用のクラスを作ります.
QWidgetに関する設定はこの継承したクラス内で行います.

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget

# QWidgetを継承したクラスを作る
class MyWidget(QWidget):
    def __init__(self):
        super().__init__()
        
        self.init_ui() # 初期設定
        
        self.show()
        
    def init_ui(self):
        """初期設定を行う"""
        pass # 後々この部分に初期設定を書く
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = MyWidget() # 自分のウィジェットを使う
    
    sys.exit(app.exec_())
    

ウィンドウの表示位置とサイズの変更

QWidget.setGeometry(x, y, w, h) -> none

ウィンドウの表示位置とサイズを変更します
x,y:int, ウィンドウx,y座標
w,h:int, ウィンドウ幅,高さ

ウィンドウタイトルの設定

QWidget.setWindowTitle(title) -> none

ウィンドウタイトルを設定します

サンプルコード
    def init_ui(self):
        self.setWindowTitle('My Title')
実行例

f:id:yu00:20150904180252p:plain

アイコンの設定

QWidget.setWindowIcon(icon) -> none

アイコンを設定します

サンプルコード
    def init_ui(self):
        self.setWindowIcon(QIcon('my-icon.png'))
実行例

f:id:yu00:20150904181917p:plain

ドキュメントの読み方

PyQt5入門 PythonでGUI作成 - yu00’s blog

PyQt5の多くのクラスや関数はQtをラップしただけなので,
PyQt5を使ったプログラムを書く場合Qt本家のドキュメントを
参照することになると思います.
ここではQt本家のドキュメントの読み方を説明します.
ただ,リンク先の場所やドキュメントの形式が変わってしまう可能性はありますが...

次がよく見るページです.

リファレンストップページです.

ウィジェットとは何なのか,レイアウトなどの
ウィジェットに関する基本的な説明が書いてあります.

基本的なウィジェットのクラス,レイアウトクラスなど,
各クラスがカテゴリーごとに分類されて説明されています.

各クラスが説明されているページでは,基本的な関数やスロットとその説明などが
書かれています.

イベント処理

PyQt5入門 PythonでGUI作成 - yu00’s blog

イベント処理の方法

PyQt5でキーボードやマウスなどのイベントを扱う処理の説明です.
ウィジェットでキーボードやマウスの入力などのイベント起こると,それぞれに対応する関数が呼ばれます.
例えばキーボード入力が起こるとQWidget.keyPressEvent()という
関数が呼ばれます.

イベントが起こったとき何か処理をしたい場合には,
ウィジェットを継承し対応する関数を再実装(オーバーライド)することで実現します.

イベント処理の例

例としてエスケープキーが押されたらウィンドウを閉じるプログラムを書いてみます.

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt

# QWidgetを継承
class MyWidget(QWidget):
    # キーボードイベントをオーバーライド
    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape: # キーがエスケープなら
            self.close() # 閉じる
            
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = MyWidget() # 継承したウィジェットを使う
    window.show()
    
    sys.exit(app.exec_())

シグナルとスロット

PyQt5入門 PythonでGUI作成 - yu00’s blog

シグナルとスロットとは

シグナルとスロットの例として,
ボタンを押したときに何か処理をするプログラムを考えます.
そのときの流れは次のようになります.

  1. ボタンを押す
  2. ボタンが押されたというイベントが発行される
  3. そのイベントに紐づけされた処理が実行される

この流れの2がシグナル,3がスロットになります.

このように,シグナルは何かが起こったときに発行されるイベント,
スロットはシグナルが起こったとき実行される処理です.

シグナルとスロットの特徴

シグナルとスロットには次のような特徴があります.

ウィジェットにはシグナルが設定されている

ウィジェットにはもともといくつかのシグナルが設定されています.
例えばボタンウィジェットにはボタンが押されたときに発行される
シグナルが設定されています.

シグナルとスロットは自分で作ることもできる

シグナル,スロットはもともとあるものを利用することもできますが,
自分で作ることもできます.

シグナルとスロットの例

シグナルとスロットの例としてボタンが押されたときに
アプリを終了するプログラムを書いてみます.

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

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton) 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    button = QPushButton('button', window)
    
    # スロットを設定
    button.clicked.connect(app.quit)
    
    window.show()
    sys.exit(app.exec_())

ボタンが押されたときQPushButton.clicked()というシグナル関数が呼ばれます.
QApplication.quit()はアプリを終了する関数です.
上のプログラムのようにconnect関数を実行するすることで,
clickedシグナルのスロットにquitが設定されます.
そして,ボタンが押されたときclicked()が呼ばれ,quit()が呼ばれることで
アプリが終了します.

レイアウトを使った配置

PyQt5入門 PythonでGUI作成 - yu00’s blog

レイアウトとは

レイアウトはウィジェットを簡単に配置する仕組みです.
ウィジェットを横に並べたり,マス目に並べたりできます.
ウィジェットの位置は自動的に計算されるので,
自分でピクセルの位置を設定する必要はありません.

レイアウトの例

例として,ウィジェットを横に並べるQHBoxLayoutを使って
ボタンを3つ横に並べてみます.

サンプルコード

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = QWidget()
    #  ボタンを作成
    button1 = QPushButton('1')
    button2 = QPushButton('2')
    button3 = QPushButton('3')
    
    # レイアウト作成
    layout = QHBoxLayout()
    # レイアウトにボタンを追加
    layout.addWidget(button1)
    layout.addWidget(button2)
    layout.addWidget(button3)
    
    # レイアウトをセット
    window.setLayout(layout)
    
    window.show()
    sys.exit(app.exec_())

実行例

f:id:yu00:20150902173318p:plain

このようにレイアウトを作成した後addWidgetを使いウィジェットを配置し,
setLayoutを使ってレイアウトをウィジェットにセットします.

レイアウトの組み合わせ

レイアウトを複数組み合わせることによって複雑なレイアウトを作ることができます.

例として,横に配置するQHBoxLayoutと縦に配置するQVBoxLayoutを
組み合わせてみます.

サンプルコード

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

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, 
                             QHBoxLayout, QVBoxLayout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = QWidget()

    button1 = QPushButton('1')
    button2 = QPushButton('2')
    button3 = QPushButton('3')
    
    # ボタン配置
    hbox = QHBoxLayout()
    hbox.addWidget(button1)
    vbox = QVBoxLayout()
    vbox.addWidget(button2)
    vbox.addWidget(button3)
    hbox.addLayout(vbox)
    
    window.setLayout(hbox)
    
    window.show()
    sys.exit(app.exec_())

実行例

f:id:yu00:20150902175819p:plain:h119

このようにaddLayoutを使うことでレイアウトに
別のレイアウトを追加できます.

ウィジェット

PyQt5入門 PythonでGUI作成 - yu00’s blog

ウィジェットとは

ウィンドウ,ボタン,ラベルなどのユーザーインターフェースを構成する部品を
ウィジェットと呼びます.
PyQt5ではQWidgetクラスがウィジェットを表しています.

ウィジェットの機能・特徴

ウィジェットには次のような機能・特徴があります.

ウィジェットの中に別のウィジェットを埋め込める

QWidgetクラスにはウェジェットの中に別のウェジェットを埋め込む機能があります.
PyQt5のプログラムではまずベースとなるウィンドウのウィジェットを作り,
その中にボタンやラベルなどのウィジェットを埋め込んでいくことで
GUIを作ります.

ウィジェットを埋め込むことで親子関係ができる

外側のウィジェットが親,埋め込んだ内側のウィジェットが子になります.

親がないウィジェットはウィンドウになる

親がない,つまりいちばん外側のウィジェットがウィンドウになります.

ウィジェットの例

例としてウィンドウにボタン用のクラスであるQPushButtonを埋め込んでみます.

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

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    window = QWidget()
    button = QPushButton('button', window) # ボタンを埋め込み
    window.show()

    sys.exit(app.exec_())

QPushButton()の第一引数が表示するテキスト,
第二引数が親のウィジェットです.
実行すると次のようになります.
f:id:yu00:20150901211049p:plain