QDialog不同的位置使用不同的组合键

问题描述

我有这个片段来模拟调用自定义 QDialog 的窗口的关闭

import sys
from PyQt5.QtWidgets import QApplication,QWidget,QDialog,QPushButton,QVBoxLayout,QHBoxLayout,QLabel
from PyQt5.QtCore import Qt

class ExitDialog(QDialog):
    """Todo"""
    def __init__(self):
        super().__init__()

        self.buttonSi = QPushButton("Yes")
        self.buttonSi.clicked.connect(self.si_clicked)

        self.buttonNo = QPushButton("No")
        self.buttonNo.clicked.connect(self.no_clicked)

        self.buttonNonUscire = QPushButton("Do not exit")
        self.buttonNonUscire.clicked.connect(self.non_uscire_clicked)

        self.text = QLabel("Do you want to save changes before exit?")
        self.text.setAlignment(Qt.AlignCenter)

        hBox1 = QHBoxLayout()
        hBox1.addWidget(self.text)

        hBox2 = QHBoxLayout()
        hBox2.addWidget(self.buttonSi)
        hBox2.addWidget(self.buttonNo)
        hBox2.addWidget(self.buttonNonUscire)

        self.layout = QVBoxLayout()
        self.layout.addLayout(hBox1)
        self.layout.addLayout(hBox2)

        self.setLayout(self.layout)

        self.value_choosed = None

    def keyPressEvent(self,event):
        if event.key == Qt.Key_Escape:
            event.ignore()

    def get_choosed_value(self):
        return self.value_choosed

    def si_clicked(self):
        self.value_choosed = 0
        self.close()

    def no_clicked(self):
        self.value_choosed = 1
        self.close()

    def non_uscire_clicked(self):
        self.value_choosed = 2
        self.close()


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(400,300,400,200)
        vBox = QVBoxLayout()
        btn = QPushButton("Exit")
        btn.clicked.connect(self.btn_clicked)
        vBox.addWidget(btn)
        self.setLayout(vBox)

    def btn_clicked(self):
        self.close()

    def closeEvent(self,event):
        dialog = ExitDialog()
        dialog.exec_()
        choice = dialog.get_choosed_value()
        if choice == 0:
            event.accept()
        elif choice == 1:
            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':
    a = QApplication(["Todo"])
    w = Window()
    w.show()
    sys.exit(a.exec_())

我注意到当我使用主窗口的“x”按钮或组合键 ALT+F4 来激活 ExitDialog 时,它的位置在使用 btn 的不同屏幕坐标上退出
我使用的是 Ubuntu 18.04.5,窗口管理器:GNOME Shell。

这怎么可能?

解决方法

好吧,我实际上是通过在 __init__ 的末尾添加一个 QTimer 来解决的。

import sys
from PyQt5.QtWidgets import QApplication,QWidget,QDialog,QPushButton,QVBoxLayout,QHBoxLayout,QLabel,QDesktopWidget
from PyQt5.QtCore import Qt,QTimer


class ExitDialog(QDialog):
    """TODO"""
    def __init__(self):
        super().__init__()

        self.buttonSi = QPushButton("Yes")
        self.buttonSi.clicked.connect(self.si_clicked)

        self.buttonNo = QPushButton("No")
        self.buttonNo.clicked.connect(self.no_clicked)

        self.buttonNonUscire = QPushButton("Do not exit")
        self.buttonNonUscire.clicked.connect(self.non_uscire_clicked)

        self.text = QLabel("Do you want to save changes before exit?")
        self.text.setAlignment(Qt.AlignCenter)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.text)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(self.buttonSi)
        hbox2.addWidget(self.buttonNo)
        hbox2.addWidget(self.buttonNonUscire)

        self.layout = QVBoxLayout()
        self.layout.addLayout(hbox1)
        self.layout.addLayout(hbox2)

        self.setLayout(self.layout)

        self.value_choosed = None

        self.timer = QTimer()
        self.timer.timeout.connect(self.setPos)
        self.timer.start(1)

    def setPos(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) // 2,(screen.height() - size.height()) // 2)
        self.timer.stop()

    def keyPressEvent(self,event):
        if event.key == Qt.Key_Escape:
            event.ignore()

    def get_choosed_value(self):
        return self.value_choosed

    def si_clicked(self):
        self.value_choosed = 0
        self.close()

    def no_clicked(self):
        self.value_choosed = 1
        self.close()

    def non_uscire_clicked(self):
        self.value_choosed = 2
        self.close()


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(400,300,400,200)
        vbox = QVBoxLayout()
        btn = QPushButton("Exit")
        btn.clicked.connect(self.btn_clicked)
        vbox.addWidget(btn)
        self.setLayout(vbox)

    def btn_clicked(self):
        self.close()

    def closeEvent(self,event):
        dialog = ExitDialog()
        dialog.exec_()
        choice = dialog.get_choosed_value()
        if choice == 0:
            event.accept()
        elif choice == 1:
            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':
    a = QApplication(["TODO"])
    w = Window()
    w.show()
    sys.exit(a.exec_())

不知道有没有办法直接和系统的窗口管理器交互。