我有一个名为Main的QMainWIndow,它调用了名为popup_on_waiver的QDialog。 QDialog有一个组合框可以选择小时数。用户选择小时数并单击“确定”后,我想关闭弹出窗口,隐藏QMainwindow,并在组合框中选择小时数后启动QMainwindow。该程序将一直运行,直到用户选择小时数和单击确定为止。它关闭弹出窗口并隐藏主窗口。(要求应用程序必须永远在隐藏状态下运行,因此必须隐藏主窗口)。当它调用launch_after_interval时,其失败,并显示错误“进程已完成,退出代码为1073741845”。请告知正确的步骤。 我将在下面未提供的某些其他条件下启动主窗口,因此我编写了一个单独的块,用于在用户选择的豁免时间之后再次启动主窗口。另外,我尝试获取弹出窗口的结果,接受还是拒绝,但没有返回任何内容。
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import QUrl, Qt, QTimer, QSize, QRect
import sys
class popup_on_waiver(QDialog):
#pop up window
def __init__(self, parent=None):
super(QDialog,self).__init__(parent)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setMinimumSize(QSize(660, 340))
self.setWindowTitle("Waiver")
self.cb = QComboBox() #combobox
self.cb.setGeometry(QRect(40, 40, 100, 30))
self.cb.addItems(["1", "2", "3", "4"])
self.cb.currentIndexChanged[str].connect(self.returnInterval)
self.cb.setObjectName("combobox")
self.cb.move(80, 80)
self.buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
self.buttons.accepted.connect(self.hide_main)
self.buttons.rejected.connect(self.reject) #buttons
vbox = QVBoxLayout(self) #layout
vbox.addWidget(self.cb)
vbox.addWidget(self.buttons)
self.setLayout(vbox)
def hide_main(self, hours):
self.accept
self.parent().hide()
launch_after_interval(self.interval) #calling timer function
def returnInterval(self, hours): #combobox value that is number of hours
self.interval = int(hours) * 3600 * 1000
#QMainwindow
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.initUI()
def initUI(self):
self.centralwidget = QWidget(self)
self.Waiver = QPushButton('Waiver')
self.Waiver.clicked.connect(lambda: self.popup())
hbox = QHBoxLayout()
hbox.addWidget(self.Waiver)
self.centralwidget.setLayout(hbox)
self.setGeometry(50, 50, 1200, 600)
self.setWindowTitle("Timesheet")
self.setWindowIcon(QIcon(""))
self.setStyleSheet("background-color:")
self.setCentralWidget(self.centralwidget)
self.show()
def popup(self):
self.p = popup_on_waiver()
self.p.exec_()
def launch_after_interval(interval):
timer = QTimer()
timer.setSingleShot(True)
timer.setInterval(interval)
timer.timeout().connect(lambda: Main())
timer.start()
答案 0 :(得分:0)
您的代码存在各种问题:
self.parent().hide()
时该对话框将不起作用,因为parent()
返回了None
,而显然{{1} 1}}属性; hide
信号连接到accepted
,这需要一个参数,但是accepted
信号没有任何内容; hide_main
中accepted
的括号,因此不会被调用; hide_main
仅在组合索引更改时设置,但如果用户不更改(保留默认值),则不会设置任何self.interval
; self.interval
标志,仅 ,它将重置其他所有窗口标志;结果将是您将没有新窗口,但有一个“嵌入”在父级中的小部件;正确设置标志,您应该使用WindowStaysOnTopHint
; self.setWindowFlags(self.flags() | Qt.WindowStaysOnTopHint)
中应该没有括号; timer.timeout().connect
对象在timer
范围之外没有引用,也没有设置父对象,因此一旦函数返回,它将被删除并且永远不会被触发; 修改后的代码(修改以粗体显示):
launch_after_interval
其他相对小问题:
class popup_on_waiver(QDialog):
def __init__(self, parent=None):
super(QDialog,self).__init__(parent)
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.setMinimumSize(QSize(660, 340))
self.setWindowTitle("Waiver")
self.cb = QComboBox() #combobox
self.cb.setGeometry(QRect(40, 40, 100, 30))
self.cb.addItems(["1", "2", "3", "4"])
self.cb.currentIndexChanged[str].connect(self.returnInterval)
self.cb.setObjectName("combobox")
self.cb.move(80, 80)
self.buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
self.buttons.accepted.connect(self.hide_main)
self.buttons.rejected.connect(self.reject)
vbox = QVBoxLayout(self)
vbox.addWidget(self.cb)
vbox.addWidget(self.buttons)
self.setLayout(vbox)
# set the default interval
self.interval = 3600000
# no arguments here!
def hide_main(self):
self.accept() # <-- the parentheses!
self.parent().hide()
launch_after_interval(self.interval)
def returnInterval(self, hours):
self.interval = int(hours) * 3600 * 1000
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.initUI()
def initUI(self):
self.centralwidget = QWidget(self)
self.Waiver = QPushButton('Waiver')
# if the function does not have arguments, lambda is usually not required
self.Waiver.clicked.connect(self.popup)
hbox = QHBoxLayout()
hbox.addWidget(self.Waiver)
self.centralwidget.setLayout(hbox)
self.setGeometry(50, 50, 1200, 600)
self.setWindowTitle("Timesheet")
self.setWindowIcon(QIcon(""))
self.setStyleSheet("background-color:")
self.setCentralWidget(self.centralwidget)
self.show()
def popup(self):
# the parent is required to make the dialog modal *and* allow it
# to call parent().hide()!
self.p = popup_on_waiver(self)
self.p.exec_()
def launch_after_interval(interval):
# set a parent QObject for the timer, so that it's not removed
# when the function returns
timer = QTimer(QApplication.instance())
timer.setSingleShot(True)
timer.setInterval(interval)
timer.timeout.connect(lambda: Main())
timer.start()
,它与QMainWindow的centralwidget
太相似了),因为它们会造成混乱并导致难以发现错误和问题; centralWidget()
;
self.someWindow.show()
)使用大写名称,对于类(Waiver
)使用小写名称,但应该相反。然后还有mixCase(popup_on_waiver
)和under_score(returnInterval
);选择一种样式并保留该样式(请在style guide for Python code(又名PEP-8中阅读有关样式)的详细信息; 我更喜欢只编辑代码的那些阻止程序正常工作的部分,但是您应该牢记上面的内容,即使它们“相对较小”(强调相对 )。
最后,(琐碎但无关紧要):应避免混合使用来自相同模块的导入模式:您可以使用hide_main
之类的通配符导入(但通常使用shouldn't)或{ {1}};对于PyQt5这样的大模块,通常会导入子模块,例如from module import *
:
好:
from module import ClassA, ClassB, [...]
也不错,但是却常常令人讨厌,因为每次需要一个新类时,您都必须记住要添加类,并且最终可能会得到很长的导入列表,最终可能会导致不必要的类。不使用某些功能(我也怀疑,至少在Qt上有很大的好处):
from PyQt5 import QtWidgets
不太好,但是可以(保留子模块名称来记住它们的“作用域”可能很有用),其行为与上一个相同:
from PyQt5 import QtWidgets
class SomeWidget(QtWidgets.QWidget):
# ...
这是错误(我的意思是,它可以工作,但是没有任何意义):
from PyQt5.QtWidgets import QWidget, QHBoxLayout # etc...
class SomeWidget(QWidget):
# ...