web-dev-qa-db-ja.com

pyqt5-アプリケーションを閉じる/終了する

私はここにあるpyqt5チュートリアルで働いています Zetcode、PyQt5

私自身の演習として、アプリを閉じるために使用された方法に関係なく、同じダイアログメッセージボックスが表示されるように例を拡張しようとしています。

  • タイトルバーの[X]ボタンをクリックします(意図したとおりに機能します)
  • [閉じる]ボタンをクリックします(属性エラーが発生します)
  • 'escape'キーを押す(機能するが、方法/理由がわからない)

ダイアログメッセージボックスはcloseEventメソッドで実装され、最後に完全なスクリプトが提供されます。

私は2つの問題を抱えています:

1。 [閉じる]ボタンをクリックすると、終了するのではなく、メッセージボックスダイアログを含むcloseEventメソッドを呼び出します。

「閉じる」プッシュボタンのサンプルコードの行を置き換えました。

btn.clicked.connect(QCoreApplication.instance().quit)

代わりに、必要なダイアログをすでに実装しているcloseEventメソッドを呼び出そうとしています。

btn.clicked.connect(self.closeEvent)

ただし、スクリプトを実行して[閉じる]ボタンをクリックし、ダイアログで結果の[閉じる]オプションを選択すると、次のようになります。

Traceback (most recent call last):
File "5-terminator.py", line 41, in closeEvent
    event.accept()
AttributeError: 'bool' object has no attribute 'accept'
Aborted

誰かが私が間違っていることとここで何をする必要があるかをアドバイスできますか?

2。どういうわけかエスケープキーを押すと、メッセージボックスダイアログが表示され、正常に機能します。

わかりました、それが機能するのは素晴らしいことですが、CloseEventメソッドで定義されたメッセージボックス機能がkeyPressEventメソッド内で呼び出される方法と理由を知りたいです。

完全なスクリプトは次のとおりです。

import sys
from PyQt5.QtWidgets import (
    QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
from PyQt5.QtCore import QCoreApplication, Qt


class Window(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        btn = QPushButton("Close", self)
        btn.setToolTip("Close Application")
        # btn.clicked.connect(QCoreApplication.instance().quit)
        # instead of above button signal, try to call closeEvent method below
        btn.clicked.connect(self.closeEvent)

        btn.resize(btn.sizeHint())
        btn.move(410, 118)
        self.setGeometry(30, 450, 500, 150)
        self.setWindowTitle("Terminator")
        self.show()

    def closeEvent(self, event):
        """Generate 'question' dialog on clicking 'X' button in title bar.

        Reimplement the closeEvent() event handler to include a 'Question'
        dialog with options on how to proceed - Save, Close, Cancel buttons
        """
        reply = QMessageBox.question(
            self, "Message",
            "Are you sure you want to quit? Any unsaved work will be lost.",
            QMessageBox.Save | QMessageBox.Close | QMessageBox.Cancel,
            QMessageBox.Save)

        if reply == QMessageBox.Close:
            event.accept()
        else:
            event.ignore()

    def keyPressEvent(self, event):
        """Close application from escape key.

        results in QMessageBox dialog from closeEvent, good but how/why?
        """
        if event.key() == Qt.Key_Escape:
            self.close()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = Window()
    sys.exit(app.exec_())

誰かが私を啓発するために時間をかけることができることを願っています。

5
user3548783

2番目の質問は最初の質問に答えます。

再実装されたkeyPressEventメソッドは close() を呼び出し、ウィジェットにQCloseEventを送信します。続いて、ウィジェットの closeEvent が、そのイベントを引数として呼び出されます。

したがって、ボタンをウィジェットのclose()スロットに接続するだけで、すべてが期待どおりに機能します。

    btn.clicked.connect(self.close)
6
ekhumoro

Xボタンとは異なり、カスタムボタンは_close event_を渡すようには見えません。boolだけです。そのため、この演習はXボタンでは機能しますが、通常のボタンでは機能しません。いずれにせよ、最初の質問では、次のように(passacceptの)代わりにdestroy()ignoreを使用できます。

_import sys
from PyQt5.QtWidgets import (
    QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
from PyQt5.QtCore import QCoreApplication, Qt


class Window(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        btn = QPushButton("Close", self)
        btn.setToolTip("Close Application")
        # btn.clicked.connect(QCoreApplication.instance().quit)
        # instead of above button signal, try to call closeEvent method below
        btn.clicked.connect(self.closeEvent)

        btn.resize(btn.sizeHint())
        btn.move(410, 118)
        self.setGeometry(30, 450, 500, 150)
        self.setWindowTitle("Terminator")
        self.show()

    def closeEvent(self, event):
        """Generate 'question' dialog on clicking 'X' button in title bar.

        Reimplement the closeEvent() event handler to include a 'Question'
        dialog with options on how to proceed - Save, Close, Cancel buttons
        """
        reply = QMessageBox.question(
            self, "Message",
            "Are you sure you want to quit? Any unsaved work will be lost.",
            QMessageBox.Save | QMessageBox.Close | QMessageBox.Cancel,
            QMessageBox.Save)

        if reply == QMessageBox.Close:
            app.quit()
        else:
            pass

    def keyPressEvent(self, event):
        """Close application from escape key.

        results in QMessageBox dialog from closeEvent, good but how/why?
        """
        if event.key() == Qt.Key_Escape:
            self.close()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = Window()
    sys.exit(app.exec_())
_

2番目の質問では、Qtはウィジェットに応じてデフォルトの動作をします(ダイアログには別の動作がある場合があります。メッセージダイアログが開いているときにEscキーを押してみてください)。 Escの動作をオーバーライドする必要がある場合は、次のことを試してください。

_def keyPressEvent(self, event):
    if event.key() == QtCore.Qt.Key_Escape:
        print("esc")
_

最終的に ZetCode でわかるように。

0
armatita