【问题标题】:MainWindow closes after initializationMainWindow 初始化后关闭
【发布时间】:2025-12-20 08:30:06
【问题描述】:

我想使用 PyQt5 和 QtDesigner 开始一个新项目。首先,我只是复制了 PyQt4 中以前项目中的代码,并将其调整为 PyQt5 中的更改。因此,启动Main Window 和更新应用程序的Timer 的代码如下所示:

# ====Python=============================================================
#                               SticksNStones
# =======================================================================
import ...    

FPS = 45
dt = 1000.0 / FPS

class SNSMainWindow(WindowBaseClass, Ui_Window):
    def __init__(self, parent=None):
        WindowBaseClass.__init__(self, parent)
        Ui_Window.__init__(self)
        self.setupUi(self)

        self.paused = False
        self.timer = None

        self.init()

    def init(self):    
        # Setup Display
        self.display.setup()

        # Setup timer
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_loop)

        self.timer.start(self.dt)

    def update_loop(self):
        if not self.paused:
            self.display.update(dt)
        else:
            pass


# ==================================
#           Start Application
# ==================================
_dialog = None


def start_sns():
    global _dialog

    # Start App and frame
    app = QtWidgets.QApplication(sys.argv)
    _dialog = SNSMainWindow()
    _dialog.show()

    # Exit if window is closed
    sys.exit(app.exec_())


if __name__ == "__main__":
    start_sns()

但是一旦我启动应用程序,它就会在初始化后关闭。调试显示计时器处于活动状态,但从未调用过 update_loop

我从中复制的 PyQt4 代码运行良好,但我无法理解为什么它不起作用,因为我在网上找到的所有示例都有相同的代码。

问题是:为什么应用程序在启动时会自行关闭?

更新

问题不在于计时器,而在于自定义 .ui 的使用。如果我用

运行代码
class SNSMainWindow(QtWidgets.QFrame):
    def __init__(self, parent=None): 
        QtWidgets.QFrame.__init__(self, parent) 
        ...

一个窗口打开,它一直打开,直到我关闭它。但是一个准系统

ui_path = os.path.dirname(os.path.abspath(__file__)) + "/ui/sns_main.ui"
Ui_Window, WindowBaseClass = uic.loadUiType(ui_path)

class SNSMainWindow(WindowBaseClass, Ui_Window):
    def __init__(self, parent=None):
        WindowBaseClass.__init__(self, parent)
        Ui_Window.__init__(self)
        self.setupUi(self)

# ==================================    

if __name__ == "__main__":
    # Start App and frame
    app = QtWidgets.QApplication(sys.argv)
    _dialog = SNSMainWindow()
    _dialog.show()

    # Exit if window is closed
    sys.exit(app.exec_())

在显示后几毫秒内消失。再说一次,在 PyQt4 中使用自定义小部件也保持打开状态。我添加了uic.load 部分,它运行得很好。转换为 PyQt5 时我错过了什么吗?

解决方案

我在自定义显示类中找到了问题的解决方案。在paintEvent 的情况下,显示将尝试获取(尚未)未定义的属性。但是并没有引发属性未定义的异常,而是关闭了窗口。

在初始化小部件时定义属性解决了这个问题。 这只是让我想知道,为什么在这种情况下没有引发异常,因为小部件显然试图调用一些未定义的属性。一个简单的

AttributeError: 'NoneType' object has no attribute 'xxx'

就够了。

【问题讨论】:

  • 猜猜应该是app.exec_()
  • 问题中的错字。这不会改变程序的行为方式。
  • @Domino。 self.dt 的值是多少?另外:什么是self.display,它的setup() 方法有什么作用? (PS:你更新中的代码什么都不做的原因是因为计时器需要一个正在运行的事件循环)。
  • 您的计时器示例不起作用,因为它需要QApplication 才能运行。所以把它夹在app = QApplication( sys.argv )app.exec_()之间,你会发现你的计时器会很开心。
  • 另一个翻译错误。计时器似乎不是问题。即使没有设置计时器,我希望窗口保持打开状态。

标签: python qt pyqt5 qt-designer qapplication


【解决方案1】:

我会尝试更改一些行,首先尝试将app 定义更改为

app = QtGui.QApplication(sys.argv)

然后删除Ui_Window init 并将其设置为self.ui = Ui_Window()

class SNSMainWindow(WindowBaseClass):
    def __init__(self, parent=None):
        WindowBaseClass.__init__(self, parent)
        self.ui = Ui_Window()
        self.ui.setupUi(self)

        self.paused = False
        self.timer = None

        self.init()

【讨论】:

  • QApplication 自 PyQt5 以来在 QtWidgets 模块中找到。由于我通过 QtDesigner 创建了 UI,因此您的提议将不起作用,因为 Ui_Window 是通过 uic 导入的。简而言之,您的建议不起作用,因为 Ui_Window 已经是一个实例。
  • @Domino,首先,即使您使用 uic 导入您的 Ui_Window,它也将不是是一个实例。其次,子类化时不能使用对象的实例,因此,从@user3544092 获取它,并将代码更改为他建议的。如果您对 uic 的工作原理有很大的疑问,请参考 qt 示例,如this,其中展示了正确使用 ui 和 uic 的方法
  • 好吧,失礼就在我这边。这些建议确实有效,我不得不调整访问我的自定义框架。不过,这些更改不会影响我的代码的行为。