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

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

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

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

Q&A

解決済

1回答

2068閲覧

Python3.7、Pyqt5で親画面から子画面を表示、親画面に値を返したい。

WMS

総合スコア37

Python 3.x

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

0グッド

0クリップ

投稿2019/10/17 06:32

いつもこちらのサイトにはお世話になっております。

実装したいことですが、
Python3.7 Pyqt5で作成したlineEditが3つあります。
マウスで lineEdit をクリックした際、3つのボタンがある子画面が表示され、
ボタンを押すと親画面にてクリックした lineEdit に「〇番のボタンが押された。」をテキスト表示したいのですが表示できずに躓いています。

また、エディタは spyder を使用しているのですが、pyファイルを実行すると親画面、子画面は表示できるのですが、コンソールに

invalid result from MyMainWindow.eventFilter(), a 'bool' is expected not 'NoneType'

というエラーがズラッと表示されてしまいます。

毎度恐れ入りますが、ご教授頂けると幸いです。
よろしくお願い致します。

ファイル構成
sample1017.ui と sample1017.py を同じディレクトリに配置しています。

sample1017.ui

python

1<?xml version="1.0" encoding="UTF-8"?> 2<ui version="4.0"> 3 <class>MainMenu</class> 4 <widget class="QMainWindow" name="MainMenu"> 5 <property name="geometry"> 6 <rect> 7 <x>0</x> 8 <y>0</y> 9 <width>200</width> 10 <height>150</height> 11 </rect> 12 </property> 13 <property name="windowTitle"> 14 <string>Main</string> 15 </property> 16 <widget class="QWidget" name="centralwidget"> 17 <widget class="QLineEdit" name="lineEdit2"> 18 <property name="geometry"> 19 <rect> 20 <x>50</x> 21 <y>70</y> 22 <width>100</width> 23 <height>20</height> 24 </rect> 25 </property> 26 <property name="alignment"> 27 <set>Qt::AlignCenter</set> 28 </property> 29 </widget> 30 <widget class="QLineEdit" name="lineEdit3"> 31 <property name="geometry"> 32 <rect> 33 <x>50</x> 34 <y>100</y> 35 <width>100</width> 36 <height>20</height> 37 </rect> 38 </property> 39 <property name="alignment"> 40 <set>Qt::AlignCenter</set> 41 </property> 42 </widget> 43 <widget class="QLineEdit" name="lineEdit1"> 44 <property name="geometry"> 45 <rect> 46 <x>50</x> 47 <y>40</y> 48 <width>100</width> 49 <height>20</height> 50 </rect> 51 </property> 52 <property name="alignment"> 53 <set>Qt::AlignCenter</set> 54 </property> 55 </widget> 56 <widget class="QLabel" name="label"> 57 <property name="geometry"> 58 <rect> 59 <x>70</x> 60 <y>10</y> 61 <width>50</width> 62 <height>12</height> 63 </rect> 64 </property> 65 <property name="text"> 66 <string>メイン画面</string> 67 </property> 68 </widget> 69 </widget> 70 </widget> 71 <tabstops> 72 <tabstop>lineEdit1</tabstop> 73 <tabstop>lineEdit2</tabstop> 74 <tabstop>lineEdit3</tabstop> 75 </tabstops> 76 <resources/> 77 <connections/> 78 <slots> 79 <slot>slot1()</slot> 80 </slots> 81</ui> 82

sample1017.py

python

1import sys 2from PyQt5.QtWidgets import * 3from PyQt5.QtCore import * 4from PyQt5 import QtCore, QtGui, QtWidgets, uic 5 6class MyMainWindow(QtWidgets.QMainWindow): 7 8 def __init__(self, parent=None): 9 super(MyMainWindow, self).__init__(parent) 10 uic.loadUi('sample1017.ui', self) 11 12 # イベントをフィルタ (監視) するウィジェットを設定する。 13 self.lineEdit1.installEventFilter(self) 14 self.lineEdit2.installEventFilter(self) 15 self.lineEdit3.installEventFilter(self) 16 17 self.SecondWindow = Second() 18 19 def eventFilter(self, obj, event): 20 if event.type() == QEvent.FocusIn: 21 print(obj.objectName()) 22 self.SecondWindow.show() 23 24 def on_procStart(self, param): 25#クリックされた lineEdit に子画面から受け取った値をセットしたいです。 26 self.lineEdit1.setText(param) 27 28class Second(QtWidgets.QWidget): 29 30 procStart = QtCore.pyqtSignal(str) 31 32 def __init__(self, parent=None): 33 super(Second, self).__init__(parent) 34 self.w = QtWidgets.QDialog(parent) 35 self.parent = MyMainWindow 36 37 self.title = 'Second Window' 38 self.left = 800 39 self.top = 300 40 self.width = 180 41 self.height = 300 42 self.setWindowTitle(self.title) 43 self.setGeometry(self.left, self.top, self.width, self.height) 44 self.centralwidget = QtWidgets.QWidget(self) 45 self.centralwidget.setObjectName("centralwidget") 46 self.pushButton_1 = QtWidgets.QPushButton(self.centralwidget) 47 self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) 48 self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) 49 self.pushButton_1.setObjectName("pushButton_1") 50 self.pushButton_2.setObjectName("pushButton_2") 51 self.pushButton_3.setObjectName("pushButton_3") 52 self.pushButton_1.setGeometry(QtCore.QRect(30, 30, 111, 41)) 53 self.pushButton_2.setGeometry(QtCore.QRect(30, 80, 111, 41)) 54 self.pushButton_3.setGeometry(QtCore.QRect(30, 130, 111, 41)) 55 self.pushButton_1.setText("1") 56 self.pushButton_2.setText("2") 57 self.pushButton_3.setText("3") 58 self.pushButton_1.clicked.connect(self.on_button_clicked1) 59 self.pushButton_2.clicked.connect(self.on_button_clicked2) 60 self.pushButton_3.clicked.connect(self.on_button_clicked3) 61 62#一つの関数にできそうな気がするのですがやりかたがわかりません。 63 def on_button_clicked1(self): 64 text = "1番のボタンが押された。" 65 self.procStart.emit(text) 66 def on_button_clicked2(self): 67 text = "2番のボタンが押された。" 68 self.procStart.emit(text) 69 def on_button_clicked3(self): 70 text = "3番のボタンが押された。" 71 self.procStart.emit(text) 72 73 74if __name__ == '__main__': 75 app = QtWidgets.QApplication(sys.argv) 76 win = MyMainWindow() 77 sec = Second() 78 win.show() 79 sec.procStart.connect(win.on_procStart) 80 81 sys.exit(app.exec_())

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

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

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

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

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

guest

回答1

0

ベストアンサー

ボタンクリックでテキストを表示する方法

ボタンを押すと親画面にてクリックした lineEdit に「〇番のボタンが押された。」をテキスト表示したいのですが表示できずに躓いています。

シグナルスロットをお使いください。
ボタンが押されたときに呼び出す関数はすでに設定できているようなので、あとは self.parent() で親クラスのオブジェクトを取得して、lineEdit1, lineEdit2, lineEdit3 に setText で直接設定してください。

エラーが出る問題について

invalid result from MyMainWindow.eventFilter(), a 'bool' is expected not 'NoneType'

訳: MyMainWindow.eventFilter() から無効な返り値を受け取りました。(bool を返すべきところを None が返されました。)

親クラスの関数をオーバーライドした場合、その関数の引数や返り値は親クラスの関数と同じにする必要があります。
(C++ であれば、コンパイラ時にエラーで教えてくれますが、Python だと実行時にエラーとなります。)

リファレンス QObject::eventFilter を確認すると、

bool QObject::eventFilter(QObject *watched, QEvent *event)

なので、bool を返す必要があるとわかります。
今回、なにも return していない (Python でなにも返さない場合は None を返したことになります) ため、エラーとなっています。

対処方法としては、イベントを処理したあと、親クラスの eventFilter にイベントを投げるようにすればよいです。

python

1 def eventFilter(self, obj, event): 2 # イベントを処理 3 4 return super().eventFilter(obj, event)

コード

サブのウィンドウのボタン配置等も Qt Designer で作成した *.ui ファイルで行うように変更しました。

  • main.py
  • mainwindow.ui
  • secondwindow.ui

main.py

python

1import sys 2from PyQt5.QtWidgets import * 3from PyQt5.QtCore import * 4from PyQt5 import uic 5 6 7class MyMainWindow(QMainWindow): 8 def __init__(self, parent=None): 9 super().__init__(parent) 10 uic.loadUi("mainwindow.ui", self) 11 12 # イベントをフィルタ (監視) するウィジェットを設定する。 13 self.lineEdit1.installEventFilter(self) 14 self.lineEdit2.installEventFilter(self) 15 self.lineEdit3.installEventFilter(self) 16 17 # 表示するまで、windows のジオメトリが確定しないため、ここで表示する。 18 self.show() 19 20 # メインウィンドウの右隣に Second を表示 21 self.SecondWindow = Second(self) 22 self.SecondWindow.move(self.x() + self.width(), self.y()) 23 24 def eventFilter(self, obj, event): 25 if event.type() == QEvent.FocusIn: 26 print(obj.objectName()) 27 # フォーカスされた lineedit を記録しておく。 28 self.SecondWindow.set_lineedit(obj) 29 self.SecondWindow.show() 30 31 return super().eventFilter(obj, event) 32 33 34class Second(QDialog): 35 def __init__(self, parent=None): 36 super().__init__(parent) 37 uic.loadUi("secondwindow.ui", self) 38 self.lineEdit = None 39 40 # pushButton1 の clicked シグナルを on_button1_clicked スロットに接続 41 self.pushButton1.clicked.connect(self.on_button1_clicked) 42 # pushButton2 の clicked シグナルを on_button2_clicked スロットに接続 43 self.pushButton2.clicked.connect(self.on_button2_clicked) 44 # pushButton3 の clicked シグナルを on_button3_clicked スロットに接続 45 self.pushButton3.clicked.connect(self.on_button3_clicked) 46 47 def on_button1_clicked(self): 48 self.lineEdit.setText("1番のボタンが押された。") 49 50 def on_button2_clicked(self): 51 self.lineEdit.setText("2番のボタンが押された。") 52 53 def on_button3_clicked(self): 54 self.lineEdit.setText("3番のボタンが押された。") 55 56 def set_lineedit(self, lineEdit): 57 self.lineEdit = lineEdit 58 59 60if __name__ == "__main__": 61 app = QApplication(sys.argv) 62 win = MyMainWindow() 63 sys.exit(app.exec_())

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainMenu</class> <widget class="QMainWindow" name="MainMenu"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>248</width> <height>150</height> </rect> </property> <property name="windowTitle"> <string>Main</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QLabel" name="label"> <property name="geometry"> <rect> <x>29</x> <y>9</y> <width>191</width> <height>21</height> </rect> </property> <property name="text"> <string>メイン画面</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> <widget class="QLineEdit" name="lineEdit1"> <property name="geometry"> <rect> <x>30</x> <y>44</y> <width>191</width> <height>21</height> </rect> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> <widget class="QLineEdit" name="lineEdit2"> <property name="geometry"> <rect> <x>30</x> <y>72</y> <width>191</width> <height>21</height> </rect> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> <widget class="QLineEdit" name="lineEdit3"> <property name="geometry"> <rect> <x>30</x> <y>100</y> <width>191</width> <height>21</height> </rect> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> </widget> </widget> <tabstops> <tabstop>lineEdit1</tabstop> <tabstop>lineEdit2</tabstop> <tabstop>lineEdit3</tabstop> </tabstops> <resources/> <connections/> <slots> <slot>slot1()</slot> </slots> </ui>

secondwindow.ui

<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Dialog</class> <widget class="QDialog" name="Dialog"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>100</width> <height>113</height> </rect> </property> <property name="windowTitle"> <string>Dialog</string> </property> <widget class="QPushButton" name="pushButton3"> <property name="geometry"> <rect> <x>10</x> <y>80</y> <width>80</width> <height>20</height> </rect> </property> <property name="text"> <string>3</string> </property> </widget> <widget class="QPushButton" name="pushButton2"> <property name="geometry"> <rect> <x>10</x> <y>50</y> <width>80</width> <height>20</height> </rect> </property> <property name="text"> <string>2</string> </property> </widget> <widget class="QPushButton" name="pushButton1"> <property name="geometry"> <rect> <x>10</x> <y>20</y> <width>80</width> <height>20</height> </rect> </property> <property name="text"> <string>1</string> </property> </widget> </widget> <resources/> <connections/> </ui>

投稿2019/10/17 07:22

編集2019/10/17 11:35
tiitoi

総合スコア21956

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

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

WMS

2019/10/17 10:45

tiitoi様 毎度ご教授頂き誠にありがとうございます。 頂いたソースで勉強させていただいているのですが、一点質問があります。 例えば、 mainwindow の lineEdit2 をクリック secondwindow のボタン3をクリック mainwindow の lineEdit2 に「3番のボタンが押された。」と表示するにはどのようにしたらよいでしょうか。 何回も恐縮ですが、よろしくお願いいたします。
tiitoi

2019/10/17 11:34

以下のようにしてはどうでしょうか。回答の main.py だけ変更しました。(.ui の2つは変更してません) 作成した SecondWindow 側からはどの lineedit にフォーカスされて呼び出されたかはわからないので、SecondWindow に記録するようにします。 具体的には、set_lineedit() という関数を作ってフォーカスしたときにその lineedit を渡して記録しておきます。 ボタンがクリックされた際はその lineedit に対して、setText() でテキストを設定するようにします。
WMS

2019/10/17 13:44

tiitoi様 lineEditごとオブジェクトとして保存してしまうのですね。 大胆ですが背景色や文字色等、プロパティを変更するのにとても有利な方法になりそうですね。 この方法でプログラムを作成してみます。 どうもありがとうございました。
tiitoi

2019/10/17 14:39 編集

一応補足ですが、Python ではオブジェクトを代入しても、そのオブジェクト自体がコピーされるわけではなく、参照がコピーされるだけなので、オブジェクトを保存することの処理コストは心配しなくても大丈夫です。(オブジェクトの参照を保存しているだけです) https://docs.python.org/ja/3/library/copy.html
WMS

2019/10/18 07:01

tiitoi様 オブジェクトとして保存、というのにちょっと抵抗があったのですが補足頂き安心しました。 色々とできそうでプログラムするのが楽しみです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問