问题描述
我有这个片段来模拟调用自定义 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_())
不知道有没有办法直接和系统的窗口管理器交互。