簡體   English   中英

self.close() 會關閉程序,即使 closeEvent() 里面有 self.ignore()

[英]self.close() will close the program even though closeEvent() has self.ignore() inside

當我在應用程序上單擊“X”並從 MessageBox 中按“否”時,程序將不會關閉 但是當我隱藏程序並從系統托盤的菜單中單擊“退出”並從消息框中單擊“否”時,該程序仍將成功關閉....

我的代碼是這樣的:

    exitAction = menu.addAction("Quit")
    exitAction.triggered.connect(self.close)

那么我的 closeEvent() 代碼是:

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Quit', 'Are You Sure to Quit?', QMessageBox.No | QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

編輯:我意識到每當菜單彈出 QMessageBox 時,無論我選擇哪個選項,整個程序仍將關閉,我認為可能是這個問題?:

os._exit(app2.exec_())

我在消息框之前添加了self.show()並且它可以工作,有沒有辦法讓它在沒有 self.show() 的情況下工作? 因為我允許用戶在程序隱藏時從系統托盤退出程序

   def closeEvent(self, event):
        self.show() << I added this and it works
        reply = QMessageBox.question(self, 'Quit', 'Are You Sure to Quit?', QMessageBox.No | QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

可重現的代碼:

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUi()

    def initUi(self):
        self.resize(350, 150)
        self.setWindowTitle("Test")
        pb_min = QPushButton("Minimise the Program", self)
        pb_min.clicked.connect(self.pbMin)

        h_box = QHBoxLayout()
        h_box.addStretch()

        h_box.addWidget(pb_min)
        h_box.addStretch()

        self.setLayout(h_box)

    def pbMin(self):
        menu = QMenu()
        showAction = menu.addAction('Show')
        showAction.triggered.connect(self.showGUI)
        exitAction = menu.addAction("Quit")
        exitAction.triggered.connect(self.close)
        self.hide()
        self.mSysTrayIcon = QSystemTrayIcon(self)
        icon = QIcon("test.png")
        self.mSysTrayIcon.setIcon(icon)
        self.mSysTrayIcon.setContextMenu(menu)
        self.mSysTrayIcon.setToolTip("Show Test")
        self.mSysTrayIcon.activated.connect(self.onActivated)
        self.mSysTrayIcon.show()

    def showGUI(self):
        self.show()
        self.mSysTrayIcon.hide()

    def onActivated(self, reason):
        if reason == self.mSysTrayIcon.Trigger:
            self.show()
            self.mSysTrayIcon.hide()


    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Quit', 'Are You Sure to Quit?', QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    os._exit(app.exec_())

您提供的代碼存在一些問題。

首先,您不應該每次最小化窗口時都創建一個新的系統托盤圖標; 雖然它可能一定的意義,但它可能是一個問題,因為在某些平台(特別是 Windows)中,當您創建一個新圖標時,該圖標可能不會總是被“刪除”(如“隱藏”),除非您明確刪除它(通常使用deleteLater() )。

然后,當您說“程序仍將成功關閉”時,它可能不會。 這通常取決於平台(不同的操作系統和操作系統版本),但這不是重點。

此外,由於您需要一種統一的方式來確保用戶真的想退出,您應該提供相應的方法來做到這一點,從而對其返回值做出反應,因為closeEvent和觸發的操作連接以不同的方式響應。

我已經修改了您的代碼,統一了一個“closeRequest”方法,可以更好地對用戶交互做出反應。


一些注意事項。

  1. 每當您使用“非標准”QWidget(例如 QSystemTrayIcon)時,您都需要更好地控制程序實際退出的方式/時間,並且在設置QApplication.setQuitOnLastWindowClosed(bool)需要特別小心。

  2. 使用os._exit一樣的sys.exit :“ os._exit()應通常只在子進程叉()之后使用”,這是並發事件循環,如使用的(很少)的情況下PyQt 事件循環以及 PyGame 事件循環(請參閱官方文檔)。

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUi()

    def initUi(self):
        self.resize(350, 150)
        self.setWindowTitle("Test")
        pb_min = QPushButton("Minimise the Program", self)
        pb_min.clicked.connect(self.pbMin)

        h_box = QHBoxLayout()
        h_box.addStretch()

        h_box.addWidget(pb_min)
        h_box.addStretch()

        self.setLayout(h_box)

        menu = QMenu()
        showAction = menu.addAction('Show')
        showAction.triggered.connect(self.showGUI)
        exitAction = menu.addAction("Quit")
        exitAction.triggered.connect(self.quitRequest)
        self.mSysTrayIcon = QSystemTrayIcon(self)
        icon = QIcon("test.png")
        self.mSysTrayIcon.setIcon(icon)
        self.mSysTrayIcon.setContextMenu(menu)
        self.mSysTrayIcon.setToolTip("Show Test")
        self.mSysTrayIcon.activated.connect(self.onActivated)

    def pbMin(self):
        self.hide()
        self.mSysTrayIcon.show()

    def showGUI(self):
        self.show()
        self.mSysTrayIcon.hide()

    def onActivated(self, reason):
        if reason == self.mSysTrayIcon.Trigger:
            self.show()
            self.mSysTrayIcon.hide()

    def quitRequest(self):
        if self.closeRequest():
            QApplication.quit()

    def closeRequest(self):
        reply = QMessageBox.question(self, 'Quit', 'Are You Sure to Quit?', QMessageBox.Yes | QMessageBox.No)
        return reply == QMessageBox.Yes

    def closeEvent(self, event):
        if self.closeRequest():
            event.accept()
            QApplication.quit()
        else:
            event.ignore()

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

找到我自己的解決方案,每當隱藏主程序時,系統托盤顯示的messagebox一旦關閉,整個程序也會關閉,因此添加app.setQuitOnLastWindowClosed(False)以避免關閉MessageBox導致整個程序關掉。
最后,在 closeEvent() 中添加quit() ()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM