質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

Q&A

解決済

1回答

1388閲覧

PyQt5でのwidget間のデータのシンプルなやり取り

mattsu.

総合スコア13

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

0グッド

0クリップ

投稿2019/01/25 05:04

編集2019/01/25 05:46

前提・実現したいこと

python3とPyQt5でライブラリのようなものを作っています。

発生している問題

main関数内にwidgetAクラスとwidgetBクラスが存在するものとして,
widgetAクラスのテキストボックスに入力したテキストを
widgetBに渡したいと考えています.(widgetAクラスのOKボタンを押したタイミングで)
また,これらのクラスはmain関数内で定義して,
main関数でqtの知識がない人に使ってもらうように(connectなどを用いないで)
受け渡したいとかんがえています.受け渡すタイミングでテキストを修正できるようにもしたいです.

試したこと

widgetAのクラス

python

1class widgetA(QtWidgets.QWidget): 2 3 procStart = QtCore.pyqtSignal(str) 4 5 def __init__(self, parent=None): 6 super(widgetA, self).__init__(parent) 7 8 self.tex = "" 9 self.lineEdit = QtWidgets.QLineEdit(self) 10 self.lineEdit.setText("Hello!") 11 12 self.button = QtWidgets.QPushButton("Send Message to B", self) 13 self.button.clicked.connect(self.on_button_clicked1) 14 15 self.layout = QtWidgets.QHBoxLayout(self) 16 self.layout.addWidget(self.lineEdit) 17 self.layout.addWidget(self.button) 18 19 def on_button_clicked1(self): 20 self.procStart.emit(self.lineEdit.text())

python

1class widgetB(QtWidgets.QWidget): 2 3 4 def __init__(self, parent=None): 5 super(widgetB, self).__init__(parent) 6 7 self.lineEdit = QtWidgets.QLineEdit(self) 8 self.button = QtWidgets.QPushButton("Send Message to A", self) 9 self.layout = QtWidgets.QHBoxLayout(self) 10 self.layout.addWidget(self.lineEdit) 11 self.layout.addWidget(self.button) 12 13 def on_procStart(self, message): 14 self.lineEdit.setText("From A: " + message) 15 print(message)

python

1import sys 2from PyQt5 import QtCore, QtGui, QtWidgets 3 4if __name__ == "__main__": 5 import sys 6 7 app = QtWidgets.QApplication(sys.argv) 8 9 widgetA = widgetA() 10 widgetB = widgetB() 11 widgetA.show() 12 widgetB.show() 13 14 #ここで,qtを知らない人でも使えるようにしたい. 15  widgetA.procStart.connect(widgetB.on_procStart) 16 17 sys.exit(app.exec_())

完成型のイメージ

python

1import sys 2from PyQt5 import QtCore, QtGui, QtWidgets 3 4if __name__ == "__main__": 5 import sys 6 7 app = QtWidgets.QApplication(sys.argv) 8 9 widgetA = widgetA() 10 widgetB = widgetB() 11 widgetA.show() 12 widgetB.show() 13 14 #クラスの中身を詳しく知らなくても使えるようにしたい. 15  #イメージ 16  widgetB.セッター関数( widgetA.ゲッター関数 ) 17  widgetAのtextをwidgetBのtextに渡したい. 18 19 #テキスト編集のイメージ 20. text = widgetA.ゲッター関数 21 text = text+"hogehoge" 22  widgetB.セッター関数( text ) 23 24 sys.exit(app.exec_())

初めてのteratailでの質問で分かりにくいところがあるかもしれませんが,よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2019/01/25 05:11

こういうケースは普通シグナルスロットを使うので、以下が正着と思いますが、どのあたりがシンプルでないと感じるのでしょうか? ``` #ここをシンプルにしたい widgetA.procStart.connect(widgetB.on_procStart) ```
mattsu.

2019/01/25 05:25

tiitoi様,早速のご返答ありがとうございます. main関数でqtの知識がない人に使ってもらうようにしたいのですが, そのとき,widgetAのprocStartの部分や,connectがわかりにくいようで,この部分をうまく隠した使い方をできないか,検討しています. text = text+"hogehoge"の部分もどうしたら実現できるのか,ご教示いただけますと幸いです。
guest

回答1

0

ベストアンサー

setter()/getter() を用意してテキストボックスの中身を返すようにするだけでは、widget A のボタンをクリックしたタイミングで widget B の on_procStart() を呼び出すということはできません。
なので、widgetA が widgetB の参照を持っておいて、直接 widgetB の関数を呼び出す必要があります。
こうするぐらいなら、シグナルスロットを使ったほうがいいと思います。

main関数でqtの知識がない人に使ってもらうようにしたいのですが,

上記のような「あるオブジェクトのアクションが発生したら、別のオブジェクトでなにかアクションを起こす」というケースが GUI の開発ではよく出てきます。
matplotlib のように GUI 部分の実装 (バックエンドとして Qt も使われています) はライブラリ内に完全に隠蔽してライブラリ利用者側が直接触らないということであれば別ですが、
そうでなければ Qt を使用したライブラリを提供するのであれば、シグナルスロットという仕組みは隠蔽するのではなく、ライブラリ使用者側に理解して使ってもらうべきだと思います。

実際 Qt を使用したライブラリを見ると、APIリファレンスに signal 関数、slot 関数としてそれぞれ記載されており、隠蔽されている例は見たことがありません。


シグナルスロットを使わない場合は以下のようになる。

python

1import sys 2from PyQt5 import QtCore, QtGui, QtWidgets 3 4 5class widgetA(QtWidgets.QWidget): 6 procStart = QtCore.pyqtSignal(str) 7 8 def __init__(self, widgetB, parent=None): 9 super(widgetA, self).__init__(parent) 10 self.widgetB = widgetB 11 12 self.tex = "" 13 self.lineEdit = QtWidgets.QLineEdit(self) 14 self.lineEdit.setText("Hello!") 15 16 self.button = QtWidgets.QPushButton("Send Message to B", self) 17 self.button.clicked.connect(self.on_button_clicked1) 18 19 self.layout = QtWidgets.QHBoxLayout(self) 20 self.layout.addWidget(self.lineEdit) 21 self.layout.addWidget(self.button) 22 23 def on_button_clicked1(self): 24 self.widgetB.on_procStart(self.lineEdit.text()) 25 26 27class widgetB(QtWidgets.QWidget): 28 def __init__(self, parent=None): 29 super(widgetB, self).__init__(parent) 30 31 self.lineEdit = QtWidgets.QLineEdit(self) 32 self.button = QtWidgets.QPushButton("Send Message to A", self) 33 self.layout = QtWidgets.QHBoxLayout(self) 34 self.layout.addWidget(self.lineEdit) 35 self.layout.addWidget(self.button) 36 37 def on_procStart(self, message): 38 self.lineEdit.setText("From A: " + message) 39 print(message) 40 41 42if __name__ == "__main__": 43 import sys 44 app = QtWidgets.QApplication(sys.argv) 45 46 widgetB = widgetB() 47 widgetA = widgetA(widgetB) 48 widgetA.show() 49 widgetB.show() 50 51 sys.exit(app.exec_()) 52

追記

python

1import sys 2from PyQt5 import QtCore, QtGui, QtWidgets 3 4 5class widgetA(QtWidgets.QWidget): 6 7 procStart = QtCore.pyqtSignal(str) 8 9 def __init__(self, modify, parent=None): 10 super(widgetA, self).__init__(parent) 11 12 self.modify = modify 13 self.tex = "" 14 self.lineEdit = QtWidgets.QLineEdit(self) 15 self.lineEdit.setText("Hello!") 16 17 self.button = QtWidgets.QPushButton("Send Message to B", self) 18 self.button.clicked.connect(self.on_button_clicked1) 19 20 self.layout = QtWidgets.QHBoxLayout(self) 21 self.layout.addWidget(self.lineEdit) 22 self.layout.addWidget(self.button) 23 24 def on_button_clicked1(self): 25 text = self.modify(self.lineEdit.text()) 26 self.procStart.emit(text) 27 28 29class widgetB(QtWidgets.QWidget): 30 def __init__(self, parent=None): 31 super(widgetB, self).__init__(parent) 32 33 self.lineEdit = QtWidgets.QLineEdit(self) 34 self.button = QtWidgets.QPushButton("Send Message to A", self) 35 self.layout = QtWidgets.QHBoxLayout(self) 36 self.layout.addWidget(self.lineEdit) 37 self.layout.addWidget(self.button) 38 39 def on_procStart(self, message): 40 self.lineEdit.setText("From A: " + message) 41 print(message) 42 43 44if __name__ == "__main__": 45 import sys 46 app = QtWidgets.QApplication(sys.argv) 47 48 def modify(message): 49 return message + 'hogehoge' 50 51 widgetA = widgetA(modify) 52 widgetB = widgetB() 53 widgetA.show() 54 widgetB.show() 55 widgetA.procStart.connect(widgetB.on_procStart) 56 57 sys.exit(app.exec_())

投稿2019/01/25 05:47

編集2019/01/25 06:35
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mattsu.

2019/01/25 06:09

tiitoi様,参照を用いた場合も添付していただき,ありがとうございます。 やはり,signal/slotの方が疎に結合できて強力であることが,わかります. もし,可能であれば,signal/slotで受け渡すタイミングで,main関数から任意の文字列を結合する方法も教えて頂けますと幸いです.
tiitoi

2019/01/25 06:13

シグナルが emit されたら、connect してある slot 関数が呼ばれるので、その間に処理を挟むということはできないです。 質問の例だと main 関数で変更したい意図というのはよくわからないのですが、signal を創出する前の on_button_clicked1() または受け取った後の on_procStart() で変更するのではなにか問題があるのでしょうか?
mattsu.

2019/01/25 06:23

文字の結合方法が,様々なパターンが考えられており,クラスに関数としてすべて定義するよりは,main関数で文字列として編集するほうが汎用性が高いと思い,質問させていただきました. matplotlibやkerasのように汎用性が高く,使いやすいものを目指しています.
mattsu.

2019/01/25 06:24

ただ,上の指摘にあるように「あるオブジェクトのアクションが発生したら、別のオブジェクトでなにかアクションを起こす」の部分の影響でかなり難しいのだと実感してきました.
tiitoi

2019/01/25 06:36 編集

もし実現するなら、例えば追記したようにコールバック関数を使うとかですかね?
mattsu.

2019/01/25 07:17

やはり,関数を渡す等,クラス内部で処理する必要がありそうですね. ほかの方の回答がなければ,ベストアンサーとさせていただきます。 お付き合いいただきありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問