gpt4 book ai didi

python - PyQt5 应用程序中的故障排除(QDialog -> QMainWindow)

转载 作者:行者123 更新时间:2023-12-04 04:03:59 24 4
gpt4 key购买 nike

我目前正在尝试解决我在使用 Python 开发的 Qt 应用程序时遇到的问题。我只有一个简单的主窗口和一个模态 QDialog 设置,用于在主窗口上触发菜单操作后收集用户输入。 QDialog 的行为符合预期,因为我已经能够确认测试打印是在 QDialog 返回 Accepted 时执行的,但是应用程序将在 print 语句之后完全崩溃,没有错误消息。当 QDialog 返回 Rejected 时会发生相同的行为。澄清一下,主窗口显示了几秒钟,应用程序崩溃了,没有错误消息。我希望该函数在收到来自下面的 Process 函数的任一结果后,将焦点返回到主窗口(它仍然打开以进行操作)。

我也曾尝试使 QDialog 成为无模式的(使用 show),并且 QDialog 的接受/拒绝函数似乎按预期返回到主窗口,但是再次调用调出 QDialog 的函数会使应用程序崩溃。我在这个项目中使用 pyqt 5.9,但我在 pyqt 5.6 的许多其他项目中使用了与下面代码基本相同的设置,但没有发生这种情况。我试图弄清楚 pyqt 5.9 是否存在任何可能导致此问题的已知问题,或者我的代码中是否存在导致此崩溃发生的错误。我正在考虑回滚到 5.6 看看是否可以解决这个问题,但我觉得可能是我误解了导致这种情况发生的原因。

我在 Windows 10 上通过 Anaconda 提示符(Anaconda 4.8.3、Python 3.7)运行代码,因为 Qt 应用程序在 Spyder 中重复运行时仍然存在问题。我正在使用 Anaconda 附带的 pyqt,并且没有对 pyqt 进行任何额外的 pip 安装。

主窗口代码

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout, QAction, QLabel
from PyQt5.QtWidgets import QDialog, QListWidget, QListWidgetItem, QAbstractItemView, QPushButton, QLineEdit, QSpacerItem, QSizePolicy


class FirstWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)

self.title = 'Window 1'
self.left = 350
self.top = 150
self.width = 800
self.height = 500

self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)

widget = QWidget()
self.setCentralWidget(widget)
grid = QGridLayout()
widget.setLayout(grid)

mainMenu = self.menuBar()
mainMenu.setNativeMenuBar(False)
subMenu = mainMenu.addMenu('File')

modifyDB = QAction('Test',self)
subMenu.addAction(modifyDB)
modifyDB.triggered.connect(self.Process)

self.statusBar().showMessage('Ready')

def Process(self):
dialog = DialogWin()
if dialog.exec_() == QDialog.Accepted:
print('test passed')

if __name__ == '__main__':
if not QApplication.instance():
app = QApplication(sys.argv)
else:
app = QApplication.instance()
mainWin = FirstWindow()
mainWin.show()
app.exec_()

对话代码

class DialogWin(QDialog):
def __init__(self,parent=None):
super(DialogWin,self).__init__(parent)

self.title = 'Database Table Name Selection'
self.left = 350
self.top = 150
self.width = 300
self.height = 300

self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)

vbox = QVBoxLayout()
spacer = QSpacerItem(10,10,QSizePolicy.Expanding,QSizePolicy.Expanding)

self.list_exp = QLabel('Select Existing Table to Overwrite')
vbox.addWidget(self.list_exp)

self.table_list = QListWidget()
self.table_list.setSelectionMode(QAbstractItemView.SingleSelection)
vbox.addWidget(self.table_list)

hbox = QHBoxLayout()
hbox.addItem(spacer)
self.option_exp = QLabel('<span style="font-size:8pt; font-weight:600; color:#aa0000;">OR</span>')
hbox.addWidget(self.option_exp)
hbox.addItem(spacer)
vbox.addLayout(hbox)

self.new_name = QLineEdit(placeholderText='Enter New Source Name')
vbox.addWidget(self.new_name)

hbox = QHBoxLayout()
self.okButton = QPushButton('OK')
hbox.addWidget(self.okButton)
self.okButton.clicked.connect(self.accept)

self.cancelButton = QPushButton('Cancel')
hbox.addWidget(self.cancelButton)
self.cancelButton.clicked.connect(self.reject)

vbox.addLayout(hbox)
self.setLayout(vbox)

item = QListWidgetItem('No Tables Available...')
item.setFlags(item.flags() ^ Qt.ItemIsSelectable)
self.table_list.addItem(item)

有关此问题的任何意见都将非常有帮助。我花了很多时间试图了解此设置如何在一个应用程序中为我工作而不在另一个应用程序中工作。

最佳答案

说明:

问题是您使用了同一个 QSpacerItem 2 次,当 QDialog 关闭时,因为它是一个局部变量,它将被删除,Qt 也会消除内部对象,在这种情况下,QSpacerItem 将有导致“段错误”的双重消除。

解决方案:

您必须创建 2 个 QSpacerItem:

# ...
hbox = QHBoxLayout()
hbox.addItem(spacer)
self.option_exp = QLabel('OR')
hbox.addWidget(self.option_exp)
<b>hbox.addItem(QSpacerItem(10,10,QSizePolicy.Expanding,QSizePolicy.Expanding))</b>
vbox.addLayout(hbox)
# ...

另一种选择是不使用 QSpacerItem 而是设置一个拉伸(stretch)因子:

# ...
hbox = QHBoxLayout()
<b>hbox.addStretch()</b>
self.option_exp = QLabel('OR')
hbox.addWidget(self.option_exp)
<b>hbox.addStretch()</b>
vbox.addLayout(hbox)
# ...

或者不使用QHBoxLayout,通过设置对齐方式直接将QLabel设置为QVBoxLayout:

# ...
self.table_list = QListWidget()
self.table_list.setSelectionMode(QAbstractItemView.SingleSelection)
vbox.addWidget(self.table_list)

self.option_exp = QLabel('OR')
<b>vbox.addWidget(self.option_exp, alignment=Qt.AlignHCenter)</b>

self.new_name = QLineEdit(placeholderText='Enter New Source Name')
vbox.addWidget(self.new_name)
# ...

关于python - PyQt5 应用程序中的故障排除(QDialog -> QMainWindow),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62767250/

24 4 0
文章推荐: python - 如何在 Python 中不使用带有 Selenium 的