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

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

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

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

Qt

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3262閲覧

PyQt4におけるシグナル/スロットについて。無限ループしてしまう。

mosquito

総合スコア19

Python 3.x

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

Qt

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2016/09/07 06:45

編集2016/09/07 18:26

毎度のことお世話になっております。
現在、python3.4言語でPyQt4を学んでいます。

本当ならPyQt4の書籍で学びたいのですが、
今現在、日本語によるものがないので、仕方なしに
Qt4の書籍を読み、PyQt4のドキュメントと照らし合わせながら学習を進めているという状況です。

ここで本題の質問なのですが、このコードを見てください。

python

1class Fusen(QWidget): 2 def __init__(self, mainwindow): 3 super().__init__() 4 self.createButton(mainwindow) 5 def createButton(self, mainwindow): 6 newFusenTB = QToolButton() 7 newFusenTB.setText('+') 8 newFusenTB.clicked.connect(lambda: mainwindow.createNewFusen()) # 問題のコード 9 ####Widgetの設定は省略#### 10 11class MainWindow(QMainWindow): 12 def __init__(self): 13 super().__init__() 14 self.createWindow() 15 def self.createWindow(self): 16 self.m_newFusenAct = QAction('&New Fusen', self) 17 self.m_newFusenAct.triggered.connect(lambda: self.createNewFusen()) 18 self.menubar = self.menuBar() 19 filemenu = self.menuBox.addMenu('&File') 20 filemenu.addAction(self.m_newFusenAct) 21 ###Windowの設定は省略### 22 def createNewFusen(self): 23 ptr = Fusen(self) #Fusenクラスのオブジェクト生成 24 ptr.show()

python

1MainWindow 2|-------------------------| 3|File| | # MenuBar 4|-------------------------| 5| | 6| | 7|-------------------------| 8 9Fusen 10|-------------------------| 11| [+] | # [+] は ToolButton 12|-------------------------| 13| | 14| | 15|-------------------------|

このプログラムを起動させると、まずMainWindowが表示されて、そのあとメニューバーのFile->NewFusenをクリックします。

そうすると、別のウィンドウであるFusenが表示される。
そして、Fusenの[+](ToolButton)をクリックしても、同じく新しいFusenが表示される。というプログラムになる予定です。


ですが、バグが発生しまして、
メニューのNewFusenのボタンをクリックして、Fusenクラスのオブジェクトが生成されるとき、
Fusenクラスのコンストラクタで、[+]ツールボタンが生成されると同時にconnectされているスロットが読まれて、また新たにFusenクラスのオブジェクトが生成される。(もしかしたら生成されるというのは勘違い?)

という、無限ループに陥ってしまうというわけです。


質問としては、
第一に無限ループを脱出する方法なのですが、
考えてみたのですが、どうも思い浮かびません。

解決策の予想ですが、どうもこの「シグナルとスロット」の関係にあるのではないかと思っているのですが、
どうなのでしょうか。

皆さんのお力を借りたく質問させてもらいましたが、
こちらの質問、説明に不備等がありましたら、
訂正いたしますので、ご意見をお聞かせください。

どうかよろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

クリック時にウィンドウを開くのであれば、QWidgetではなく、QDialogかQMainWindowを使いましょう。
Fusenクラス内から、スロット関数MainWindow::createNewFusen()を呼び出したい場合は以下のようなコードになりますが、素直にFusen::createNewFusen()を実装した方が良いと思います。

python

1# -*- coding: utf-8 -*- 2import sys 3from PyQt4 import QtCore, QtGui 4 5 6class Fusen(QtGui.QDialog): 7 def __init__(self, parent=None): 8 super(Fusen, self).__init__(parent) 9 self.setupUi(self) 10 self.button.clicked.connect(parent.createNewFusen) 11 self.action_newFusen.triggered.connect(parent.createNewFusen) 12 13 def setupUi(self, Fusen): 14 self.hboxlayout = QtGui.QHBoxLayout(Fusen) 15 self.button = QtGui.QPushButton("new Fusen") 16 self.hboxlayout.addWidget(self.button) 17 self.setLayout(self.hboxlayout) 18 19 self.menubar = QtGui.QMenuBar(Fusen) 20 self.action_newFusen = QtGui.QAction(Fusen) 21 self.action_newFusen.setText('new Fusen') 22 self.menubar.addAction(self.action_newFusen) 23 self.hboxlayout.setMenuBar(self.menubar) 24 25 26class MainWindow(QtGui.QMainWindow): 27 def __init__(self, parent=None): 28 super(MainWindow, self).__init__(parent) 29 self.setupUi(self) 30 self.button.clicked.connect(self.createNewFusen) 31 self.action_newFusen.triggered.connect(self.createNewFusen) 32 33 def setupUi(self, MainWindow): 34 self.centralwidget = QtGui.QWidget(MainWindow) 35 self.hboxlayout = QtGui.QHBoxLayout(self.centralwidget) 36 self.button = QtGui.QPushButton("new Fusen") 37 self.hboxlayout.addWidget(self.button) 38 MainWindow.setCentralWidget(self.centralwidget) 39 self.menubar = QtGui.QMenuBar(MainWindow) 40 self.action_newFusen = QtGui.QAction(MainWindow) 41 self.action_newFusen.setText('new Fusen') 42 self.menubar.addAction(self.action_newFusen) 43 MainWindow.setMenuBar(self.menubar) 44 45 def createNewFusen(self): 46 ptr = Fusen(self) 47 ptr.show() 48 49if __name__ == '__main__': 50 app = QtGui.QApplication(sys.argv) 51 main = MainWindow() 52 main.show() 53 app.exec_()

setupUi()はQt Designerを使うと書かずに済みますので、実際のコードは更に簡潔となります。

投稿2016/09/12 14:01

EloiseSeverin

総合スコア50

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

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

mosquito

2016/09/16 23:31

返信が遅れまして、申し訳ありません。 WidgetではなくDialogかMainWindowですね! そういうことなのですね。 それと、parentに指定していませんでした。見落としていました。 とてもわかりやすい解説をありがとうございます!
guest

0

Qt はわかりますが、Python も PyQt も全くわからないので勘で回答します。

python

1class Fusen(QWidget): 2 def __init__(self, mainwindow): 3 super().__init__() 4 def self.createButton(mainwindow)

self.createButton(mainwindow) の前の def は不要ではないでしょうか。

python

1 newFusenTB.clicked.connect(mainwindow.createNewFusen()) # 問題のコード

mainwindow.createNewFusen() ではなく、lambda: mainwindow.createNewFusen() ではないでしょうか。

投稿2016/09/07 11:29

yuki23

総合スコア1448

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

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

mosquito

2016/09/07 18:16

ご回答ありがとうございます。 そして、大変申し訳にくいのですが、 self.createButton(mainwindow)の 前の「def」は付け間違えです。 大変申し訳ありません。 と、同時に、 lambdaもつけ忘れでございます。 質問する側が、このようなことで、大変申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問