Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@karakuri-t910

PySide2をゼロから学んでいく~#2 ボタン~

はじめに

PythonでGUI開発をするためのライブラリ「PySide2」の基本的な使い方を、いくつかの段階に分けて説明していきます。

当ページではPySide2のボタンについて説明しています。

環境

以下の通りになります。

  • Windows 10
  • Python 3.8以降

公式リファレンス

QPushButton

ベースプログラム

以下のウィンドウを表示するだけのプログラムをベースにして実装していきます。

# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能(今はウィンドウだけ)
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()


# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

PySide2でボタン

ボタンを表示する

単純にボタンを表示してみます。

サンプルプログラム

# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能(今はウィンドウだけ)
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        # ボタンを表示
        self.button1 = QtWidgets.QPushButton("Button 1", self)


# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

実行結果

000.png

プログラム解説

ボタンを表示するのに以下のメソッドを使用しています。

書式:
    QtWidgets.QPushButton("<文字列>", window_object)
引数:
    "文字列": ボタンに表示する内容
    window_object: ボタンを表示させるウィンドウ(基本的に self を指定)

ウィンドウオブジェクトは、ボタンを表示させたいウィンドウを指定します。

PySide2で複数のウィンドウを開いた際に、ある一つのウィンドウに対してボタンをつけたい場合に指定します。そのような場合はほとんど出くわすことはないので、サンプルプログラムのように基本的に自身のウィンドウを意味するselfを指定します。

特定のウィンドウオブジェクトに表示させてみる

気になる方は以下のタブを展開してみてください。
正直知らなくても問題ないです。

複数のウィンドウのある1つにボタンを表示させる

●サンプルプログラム
# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能
class MainWindow(QtWidgets.QWidget):
    def __init__(self, title="None Title"):
        super().__init__()
        self.setGeometry(100, 100, 300, 200)
        self.setWindowTitle(title)


# アプリの実行と終了
app = QtWidgets.QApplication()

# ウィンドウオブジェクトの生成
window1 = MainWindow("Window 1")
window2 = MainWindow("Window 2")
window3 = MainWindow("Window 3")
window4 = MainWindow("Window 4")
window5 = MainWindow("Window 5")

# Window 3 にボタンを配置
button = QtWidgets.QPushButton("Window 3 だけにボタンを表示しました。", window3)

# ウィンドウを表示
window1.show()
window2.show()
window3.show()
window4.show()
window5.show()

app.exec_()

●実行結果
001.png

●プログラム解説
MainWindowクラスはインスタンス生成時にウィンドウタイトルを設定するだけにしてます。

MainWindowクラス内でボタンを表示しない理由は、クラス内で他のウィンドウオブジェクトを取得するのが難しくなり、全体的なコードが長くなってしまうからです(単に私が知らないだけです)。

そこでメイン処理で5つのウィンドウオブジェクトを生成し、Window 3 だけ個別にボタンを表示するようにしています。

ボタンに機能をつける

ボタンをクリックしたら関数を呼び出すようにします。

サンプルプログラム

Button 1をクリックしたら以下のアスキーアートを表示するプログラムです。

バン(∩`・ω・)バンバン
_/_ミつ/ ̄ ̄ ̄/
\/___/”

# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        button1 = QtWidgets.QPushButton("Button 1", self)
        button1.clicked.connect(self.pushed_button1)

    def pushed_button1(self):
        print("バン(∩`・ω・)バンバン \n  _/_ミつ/ ̄ ̄ ̄/\n       \/___/”")


# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

実行結果

000.gif

プログラム解説

サンプルプログラムのミソの部分です。

button = QtWidgets.QPushButton("Button", self)
button.clicked.connect(呼び出したい関数名)

QtWidgets.QPushButton("表示内容", window_object)でプッシュボタンを定義し、戻り値として定義したボタン情報を渡します。

この戻り値にはシグナルと呼ばれるメソッドを持ち、簡単に言うと「このボタンにどういう操作をしたら、どんな処理をするの?」ということを指定できます。

サンプルプログラムではclickedというシグナルと、そのシグナルが送られたら何の関数を呼び出すのかというconnectを指定しています。

シグナルについては、当ページの「こぼれ話」でちょこっと取り扱います。

メニューボタン

一つのボタンに幾つかの選択肢を与えてみます。
入門レベルを超えた(中級も超えてる?)内容なので「そんなものもあるんだぁ」程度でOKです。

サンプルプログラム

  • 注記 PySide2公式リファレンスやStack Overflowなどでメニューボタンの実装方法を調べましたが一切出てきませんでした。以下に載せているサンプルプログラムは、私が試行錯誤で実現した方法になります。そのため正規のボタンメニューの実装方法なのか否かは分からないため真に受けないようご注意を。
# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        # メニューインスタンス生成(この変数menuListに項目と機能を追加していく)
        menuList = QtWidgets.QMenu(self)

        # 喜びのメニューとその機能を追加
        action = QtWidgets.QAction("喜", menuList)  # 喜のメニューを作成
        action.setObjectName("Emotions")            # 識別子(無くても良い)
        action.triggered.connect(self.print_happy)  # ボタンを押したら呼び出す関数
        menuList.addAction(action)                  # 喜の機能をメニューに追加

        # 怒りのメニューとその機能を追加
        action = QtWidgets.QAction("怒", menuList)
        action.setObjectName("Emotions")
        action.triggered.connect(self.print_angry)
        menuList.addAction(action)

        # 哀しみのメニューとその機能を追加
        action = QtWidgets.QAction("哀", menuList)
        action.setObjectName("Emotions")
        action.triggered.connect(self.print_sad)
        menuList.addAction(action)

        # 楽しみのメニューとその機能を追加
        action = QtWidgets.QAction("楽", menuList)
        action.setObjectName("Emotions")
        action.triggered.connect(self.print_pleasant)
        menuList.addAction(action)

        # メニューボタンを定義
        menu_button = QtWidgets.QPushButton("喜怒哀楽を表現", self)
        menu_button.setMenu(menuList)  # ボタンに上記に定義した全メニューを登録

    # 喜び
    def print_happy(self):
        print("ヾ(*´∀`*)ノ")

    # 怒り
    def print_angry(self):
        print("(#^ω^)ピキピキ")

    # 哀しみ
    def print_sad(self):
        print("(´・ω・`)ショボーン")

    # 楽しみ
    def print_pleasant(self):
        print("(≧∇≦)")



# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

実行結果

001.gif

プログラム解説

一つずつ説明していきます。

①メニューの種類を格納できる変数の宣言

# メニューインスタンス生成(この変数menuListに項目と機能を追加していく)
menuList = QtWidgets.QMenu(self)

QtWidgets.QMenu()クラスは「どんなメニューを作り、各々はどんな機能なのか」を保存できる変数を戻り値として渡します。あくまで保存だけです。ボタンにメニューの種類と機能を追加するにはQtWidgets.QPushButton.setMenu(メニュー情報)を使用しますが、これは③で説明します。

書式:
    class QtWidgets.QMenu(window_object)
引数:
    window_object: メニューの追加対象となるウィンドウ

メニューバーというのもありますが、こちらはQtWidgets.QMenuBarというクラスがあります。
当ページでは割愛します。

②各メニューとその機能を追加

# 喜びのメニューとその機能を追加
action = QtWidgets.QAction("喜", menuList)  # 喜のメニューを作成
action.setObjectName("Emotions")            # 識別子(無くても良い)
action.triggered.connect(self.print_happy)  # ボタンを押したら呼び出す関数
menuList.addAction(action)                  # 喜の機能をメニューに追加

メニューと機能の追加処理は基本的に上記の通りなので、メニュー登録用関数・メソッドを実装すると一層スッキリとしてそれでいて見やすいコードになります。

メニューボタンなので各項目と各々に機能を持たせる必要があります。そこで機能を与えるためにQtWidgets.QAction("メニュー名", メニューインスタンス)を用いています。QActioクラスは第一引数に機能名、第二引数に登録対象の変数を渡します。

setObjectName("識別子")は「複数のメニューがあり、これは何のグループなのか?」を分けるためのグループ名みたいなものです。幾つかのメニューに各々の名前を付けるってことです。setObjectName("識別子")は記述しなくても問題ないですが、いくつもメニューがある場合は区別のために実装した方が後々管理しやすいかと。

triggered.connect(関数名)は「何の機能を実行するのか」を登録するメソッドです。triggeredは何かしらの操作(クリックとかキー入力とか)があったら実行するというシグナルです。

addAction()で上記3つの処理をメニューインスタンスに保存しています。

③メニューボタンの生成とメニューの登録

# メニューボタンを定義
menu_button = QtWidgets.QPushButton("喜怒哀楽を表現", self)
menu_button.setMenu(menuList)  # ボタンに上記に定義した全メニューを登録

「①メニューの種類を格納できる変数の宣言」ではQtWidgets.QMenu()クラスで「メニューとその機能の保存だけ」と説明しました。その保存したメニューの内容をボタンに登録するメソッドがQtWidgets.QPushButton.setMenu()メソッドになります。

書式:
    class QtWidgets.QMenu(window_object)
引数:
    window_object: メニューの追加対象となるウィンドウ

ボタンを使ったサンプルプログラム

私が1分程度で考えたボタンを使ったプログラムをいくつかご披露。

PySide2のアプリを閉じるボタン

ウィンドウの閉じるボタンとは別に、PySide2のボタンで閉じるを実装しました。

# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能(今はウィンドウだけ)
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(300, 300, 300, 200)

        quitButton = QtWidgets.QPushButton("アプリを終了する", self)
        quitButton.clicked.connect(self.application_quit)

    def application_quit(self):
        # Qtが用意しているcloseスロットを実行
        self.close()


# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

よく使うアプリを起動するボタン

以下のアプリを起動するボタンを作ってみました。

  • Chrome
  • サクラエディタ
  • Kindle
import subprocess
# PySide2のモジュールを読み込む
from PySide2 import QtWidgets


# ウィンドウの見た目と各機能(今はウィンドウだけ)
class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(300, 300, 300, 200)

        # メニューインスタンス生成
        menuList = QtWidgets.QMenu(self)

        # Chromeを起動するメニューとその機能を登録
        action = QtWidgets.QAction("Chromeを起動", menuList)
        action.setObjectName("run_applications")
        action.triggered.connect(self.run_chrome)
        menuList.addAction(action)

        # サクラエディタを起動するメニューとその機能を登録
        action = QtWidgets.QAction("サクラエディタを起動", menuList)
        action.setObjectName("run_applications")
        action.triggered.connect(self.run_sakura_editor)
        menuList.addAction(action)

        # Kindleを起動するメニューとその機能を登録
        action = QtWidgets.QAction("Kindleを起動", menuList)
        action.setObjectName("run_applications")
        action.triggered.connect(self.run_kindle)
        menuList.addAction(action)

        # 全部を起動するメニューとその機能を登録
        action = QtWidgets.QAction("全部を起動", menuList)
        action.setObjectName("run_applications")
        action.triggered.connect(self.run_all_applications)
        menuList.addAction(action)

        run_application_button = QtWidgets.QPushButton("何のアプリを起動する?", self)
        run_application_button.setMenu(menuList)

    def run_chrome(self):
        # エスケープシーケンスを無効にする「R」を忘れないで!!
        self.chromePath = R"C:\Program Files\Google\Chrome\Application\chrome.exe"
        subprocess.Popen(self.chromePath)

    def run_sakura_editor(self):
        # エスケープシーケンスを無効にする「R」を忘れないで!!
        self.sakuraeditorPath = R"C:\Program Files (x86)\sakura\sakura.exe"
        subprocess.Popen(self.sakuraeditorPath)

    def run_kindle(self):
        # エスケープシーケンスを無効にする「R」を忘れないで!!
        self.kindlePath = R"C:\Users\からくり\AppData\Local\Amazon\Kindle\application\Kindle.exe"
        subprocess.Popen(self.kindlePath)

    def run_all_applications(self):
        subprocess.Popen(self.chromePath)
        subprocess.Popen(self.sakuraeditorPath)
        subprocess.Popen(self.kindlePath)



# アプリの実行と終了
app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec_()

こぼれ話

シグナルとスロット

このページでは簡単に説明するだけです。
この話はちゃんと別の記事で説明しようと思います。

シグナル

何か操作されたら、他のオブジェクトに知らせる関数・メソッドのことをシグナルといいます。当ページでは「ボタンをクリックしたら関数を呼び出す」処理を実装しましたが、この「クリックしたら」がシグナルになります。

シグナルには以下のようなものがあります。

ボタンのシグナル名 機能
clicked クリックしたら(押して離したら)シグナルを送る
pressed 押した瞬間にシグナルを送る
released 離した瞬間にシグナルを送る
他多数 他に何があるのか分からないだけです...

スロット

シグナルを受け取ったら実行する関数・メソッドのことです。当ページでは「ボタンをクリックしたら関数を呼び出す」処理を実装しましたが、この「関数を呼び出す」がスロットになります。

Qtではもともと用意されているスロットもありますが、当ページはスロットを自作しております。pushed_button1メソッドやprint_happyメソッドを自作してます。これらがスロットです。

Qtで用意されているスロットには以下があります。

ウィジェットのシグナル名 機能
close アプリを終了する
hide ウィジェットを非表示にする?
hideについてはあまり理解していませんのでご注意を。
他多数 他に何があるのか分からないだけです...

シグナルとスロットはどうやって結びつけてるの?

connect(関数・メソッド名)で結びつけています。

サンプルプログラムを見返せば分かると思いますが「Button 1をクリックしたらpushed_button1メソッドを呼び出す」処理を以下のように実装しました。

button1.clicked.connect(self.pushed_button1)

clicked(シグナル内容)→ connect(シグナル送信)という流れでシグナルを送ります。その後pushed_button1メソッド(スロット)を実行しています。

複数のボタンを使いたいとき

当ページでは、2つ以上ボタンがある場合の説明は割愛させて頂きます。

QtWidgets.QFormLayoutというモジュールの使い方を学ぶ必要があります。
ボタンやチェックボックスなど、ウィジェットのレイアウトを決める方法として、当シリーズの別ページ記載します。

ここではあくまでもボタンの表示と機能の与え方のみをお伝えした次第であります。

メニューについて

メニューボタンの使い方は正直理解しにくかったと思います。

正直私自身、PySide2でメニュー系の処理を理解しきれていないので、勉強して言語化できるようになったらメニューに焦点を当てた解説ページを投稿します。

詳しい説明については私が言語化できるくらい理解してから。。。

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
karakuri-t910
介護職をやっております。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?