首页 > 解决方案 > 我无法完全关闭 PyQt5 脚本

问题描述

当我运行以下名为 test2.py 的脚本时,如果单击“确定”或“取消”按钮,窗口将关闭,但没有收到提示。我想我忘记了一些愚蠢的事情......

这是 test2.py 脚本:

from PyQt5 import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
import sys
import unittest

class MainAppWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        
        dialog = Qt.QDialog()
        
        buttonbox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel)
        
        layout = Qt.QVBoxLayout()
        
        param_box = Qt.QGroupBox('Iterate over parameters:')

        pblayout = Qt.QVBoxLayout()
        pblayout.setContentsMargins(0, 0, 0, 0)

        scroll = Qt.QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setFrameStyle(scroll.NoFrame)
        scroll.setViewportMargins(0, 0, 0, 0)

        pblayout.addWidget(scroll)

        param_lay = Qt.QGridLayout()

        wid = Qt.QWidget()
        
        scroll.setWidget(wid)

        wid.setLayout(param_lay)

        param_box.setLayout(pblayout)

        layout.addWidget(param_box)
        layout.addWidget(buttonbox)

        dialog.setLayout(layout)

        buttonbox.accepted.connect(dialog.accept)
        buttonbox.rejected.connect(dialog.reject)

        param_lay.addWidget(Qt.QLabel('iter. / database:'), 0, 0, 1, 3)
        param_lay.addWidget(Qt.QLabel('iter.:'), 0, 3, 1, 2)
        param_lay.setColumnStretch(2, 1)
        param_lay.setColumnStretch(4, 1)
        param_lay.setRowStretch(0, 0)
 
        res = dialog.exec_()

        if res != dialog.Accepted:
            print('dialog not accepted')
        else:
            print('dialog accepted')




if __name__ == "__main__":

    app = QApplication(sys.argv)
    win = MainAppWindow()
    sys.exit(app.exec_())

当我使用 运行脚本时python3 test2.py,我在标准输出中观察到dialog accepteddialog not accepted取决于单击的按钮,窗口关闭但我没有得到提示。我必须手动停止(CtrLZ)才能获得提示。

标签: pythonpyqt5

解决方案


问题是你有 2 个事件循环:dialog.exec_() 所以app.exec_()当第一个事件循环完成时,另一个事件循环开始。另一方面,创建一个从 MainAppWindow 继承的类是没有用的,因为该窗口从未被使用或显示。

一种可能的解决方案是只启动一个事件循环:

import sys
from PyQt5.QtWidgets import (
    QApplication,
    QDialog,
    QDialogButtonBox,
    QGridLayout,
    QGroupBox,
    QLabel,
    QMainWindow,
    QScrollArea,
    QVBoxLayout,
    QWidget,
)


def main():
    dialog = QDialog()

    buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

    layout = QVBoxLayout(dialog)

    param_box = QGroupBox("Iterate over parameters:")

    pblayout = QVBoxLayout()
    pblayout.setContentsMargins(0, 0, 0, 0)

    scroll = QScrollArea()
    scroll.setWidgetResizable(True)
    scroll.setFrameStyle(scroll.NoFrame)
    scroll.setViewportMargins(0, 0, 0, 0)

    pblayout.addWidget(scroll)

    param_lay = QGridLayout()

    wid = QWidget()

    scroll.setWidget(wid)

    wid.setLayout(param_lay)

    param_box.setLayout(pblayout)

    layout.addWidget(param_box)
    layout.addWidget(buttonbox)

    buttonbox.accepted.connect(dialog.accept)
    buttonbox.rejected.connect(dialog.reject)

    param_lay.addWidget(QLabel("iter. / database:"), 0, 0, 1, 3)
    param_lay.addWidget(QLabel("iter.:"), 0, 3, 1, 2)
    param_lay.setColumnStretch(2, 1)
    param_lay.setColumnStretch(4, 1)
    param_lay.setRowStretch(0, 0)

    res = dialog.exec_()

    if res != dialog.Accepted:
        print("dialog not accepted")
    else:
        print("dialog accepted")


if __name__ == "__main__":

    app = QApplication(sys.argv)
    main()

推荐阅读