鱼C论坛

 找回密码
 立即注册
查看: 751|回复: 2

[已解决]pyqt5将QMainWindow置于两个py文件进行点击跳转,但闪退,已加设置self

[复制链接]
发表于 2024-7-13 16:08:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Notodontidae 于 2024-7-13 16:11 编辑

如果将两个py的两个class同事放置于一个.py中,则在使用self时不会被__del__回收,但是分别放置到不同的.py里就会闪退
求教,除了使用global全局变量之外没有别的方法了吗?

第一个窗口ui(first_wind.py):
  1. from PyQt5 import QtCore, QtGui, QtWidgets


  2. class Ui_Dialog(object):
  3.     def setupUi(self, Dialog):
  4.         Dialog.setObjectName("Dialog")
  5.         Dialog.resize(1080, 720)


  6.         self.main_widget=QtWidgets.QWidget(Dialog)
  7.         self.main_widget.setObjectName("mainwidget")

  8.         self.test_button=QtWidgets.QPushButton(Dialog)
  9.         self.test_button.setGeometry(QtCore.QRect(200,200,200,50))
  10.         self.test_button.setText('dundun')
  11.       

  12.         self.retranslateUi(Dialog)
  13.         QtCore.QMetaObject.connectSlotsByName(Dialog)

  14.     def retranslateUi(self, Dialog):
  15.         _translate = QtCore.QCoreApplication.translate
  16.         Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
复制代码




第一个窗口事件:(first_wind_act.py):

  1. import sys
  2. import first_wind
  3. import sec_wind
  4. import time

  5. from PyQt5 import QtCore,QtGui,QtWidgets
  6. from PIL import Image

  7. sys.path.append(r'G:\\pythoncodes\\qt5')

  8. class FirstWindowAct(first_wind.Ui_Dialog,QtWidgets.QMainWindow):
  9.     def __init__(self):
  10.         super(first_wind.Ui_Dialog, self).__init__()
  11.         self.setupUi(self)

  12.         self.test_button.clicked.connect(self.opn_btn_clicked)
  13.         self.sec_wind=None

  14.     def opn_btn_clicked(self):
  15.         self.close()
  16.         self.sec_wind=sec_wind.SecWindowAct()        #sec_wind中要调用的class,点击之后就闪退,不知道为什么会这样
  17.         self.sec_wind.show()
  18.         time.sleep(5)


  19. if __name__=='__main__':
  20.     app = QtWidgets.QApplication(sys.argv)

  21.     root=FirstWindowAct()
  22.     root.show()
  23.     sys.exit(app.exec_())
复制代码



第二个窗口ui:略,除了没有QPushButton以外,其余之处和第一个窗口的结构完全一致
第二个窗口事件:(sec_wind_act.py):
  1. import sys
  2. import sec_wind

  3. from PyQt5 import QtCore,QtGui,QtWidgets
  4. from PIL import Image

  5. sys.path.append(r'G:\\pythoncodes\\qt5')


  6. class SecWindowAct(sec_wind.Ui_Dialog,QtWidgets.QMainWindow):
  7.     def __init__(self):
  8.         super(sec_wind.Ui_Dialog,self).__init__()
  9.         self.setupUi(self)
复制代码



最佳答案
2024-9-1 15:19:12
错误的super调用:
在FirstWindowAct和SecWindowAct的构造函数中,你错误地调用了super。你应该使用当前类名作为第一个参数,而不是Ui_Dialog(它不是一个QMainWindow的子类)。这会导致构造函数没有正确初始化QMainWindow的部分,可能导致程序行为异常。
修改前:

  1. super(first_wind.Ui_Dialog, self).__init__()
复制代码

修改后:

  1. super(FirstWindowAct, self).__init__()
  2. 同样,对于SecWindowAct也做相同的修改。
复制代码


错误的窗口设置:
在Ui_Dialog类中,你尝试将main_widget和test_button添加到Dialog上,但实际上你应该将它们添加到self.main_widget上(如果你打算在QMainWindow中使用中央小部件的话)。不过,因为你直接继承自QMainWindow,你可能不需要main_widget,除非你有特定的布局需求。
__del__方法的误解:
在Python中,__del__方法(如果定义了)是在对象被垃圾回收时调用的。但是,Python的垃圾回收是不确定的,且依赖于对象的引用计数和循环引用检测。在你的情况下,self的回收与类定义在哪个文件中无关,而是与对象的引用和使用情况有关。
程序结构:
你的程序结构看起来有些混乱,特别是关于如何组织和导入模块。通常,UI类和相关的逻辑应该分开,并且每个窗口的UI和逻辑应该在同一个模块或包中。
示例


  1. # first_wind_act.py  
  2. import sys  
  3. from PyQt5 import QtWidgets  
  4. from first_wind import Ui_Dialog  
  5.   
  6. class FirstWindowAct(QtWidgets.QMainWindow):  
  7.     def __init__(self):  
  8.         super(FirstWindowAct, self).__init__()  
  9.         self.ui = Ui_Dialog()  
  10.         self.ui.setupUi(self)  # 将self(QMainWindow实例)传递给setupUi  
  11.   
  12.         self.ui.test_button.clicked.connect(self.opn_btn_clicked)  
  13.         self.sec_wind = None  
  14.   
  15.     def opn_btn_clicked(self):  
  16.         self.close()  
  17.         from sec_wind_act import SecWindowAct  
  18.         self.sec_wind = SecWindowAct()  
  19.         self.sec_wind.show()  
  20.   
  21. if __name__ == '__main__':  
  22.     app = QtWidgets.QApplication(sys.argv)  
  23.     root = FirstWindowAct()  
  24.     root.show()  
  25.     sys.exit(app.exec_())
复制代码

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-7-13 16:10:37 | 显示全部楼层
Hello,鱼油!在 PyQt5 中,你想实现两个窗口之间的跳转,但是分别放在不同的 .py 文件中会导致闪退。这个问题可以通过几种方式解决,而不需要依赖 global 全局变量。

我们先分析一下问题的根本原因:

### 问题原因
当你在两个不同的 .py 文件中分别定义了窗口类时,可能会出现以下几个问题:
1. **对象的生命周期管理**:在第一个窗口关闭后,第二个窗口的引用可能会被垃圾回收机制(`__del__`)回收,从而导致程序崩溃。
2. **线程问题**:使用 `time.sleep(5)` 会阻塞主线程,导致 GUI 停止响应。

### 解决方案
以下是几种可能的解决方案:

#### 1. 使用`QStackedWidget`
`QStackedWidget` 允许你在同一个主窗口中切换不同的窗口。这样可以避免窗口对象被回收的问题。

  1. # main.py
  2. import sys
  3. from PyQt5 import QtWidgets
  4. import first_wind
  5. import sec_wind

  6. class MainWindow(QtWidgets.QMainWindow):
  7.     def __init__(self):
  8.         super(MainWindow, self).__init__()
  9.         self.stacked_widget = QtWidgets.QStackedWidget()
  10.         self.setCentralWidget(self.stacked_widget)

  11.         self.first_window = first_wind.Ui_Dialog()
  12.         self.second_window = sec_wind.Ui_Dialog()

  13.         self.first_window.setupUi(self)
  14.         self.second_window.setupUi(self)

  15.         self.stacked_widget.addWidget(self.first_window)
  16.         self.stacked_widget.addWidget(self.second_window)

  17.         self.first_window.test_button.clicked.connect(self.show_second_window)

  18.     def show_second_window(self):
  19.         self.stacked_widget.setCurrentWidget(self.second_window)

  20. if __name__ == '__main__':
  21.     app = QtWidgets.QApplication(sys.argv)
  22.     main_window = MainWindow()
  23.     main_window.show()
  24.     sys.exit(app.exec_())
复制代码


#### 2. 保持窗口对象的引用
确保你在切换窗口时保持对窗口对象的引用,避免它们被垃圾回收。

  1. # first_wind_act.py
  2. import sys
  3. from PyQt5 import QtWidgets
  4. import first_wind
  5. import sec_wind_act

  6. class FirstWindowAct(first_wind.Ui_Dialog, QtWidgets.QMainWindow):
  7.     def __init__(self):
  8.         super(FirstWindowAct, self).__init__()
  9.         self.setupUi(self)
  10.         self.test_button.clicked.connect(self.open_second_window)
  11.         self.sec_window = None

  12.     def open_second_window(self):
  13.         self.sec_window = sec_wind_act.SecWindowAct()
  14.         self.sec_window.show()
  15.         self.close()

  16. if __name__ == '__main__':
  17.     app = QtWidgets.QApplication(sys.argv)
  18.     window = FirstWindowAct()
  19.     window.show()
  20.     sys.exit(app.exec_())

  21. # sec_wind_act.py
  22. import sys
  23. from PyQt5 import QtWidgets
  24. import sec_wind

  25. class SecWindowAct(sec_wind.Ui_Dialog, QtWidgets.QMainWindow):
  26.     def __init__(self):
  27.         super(SecWindowAct, self).__init__()
  28.         self.setupUi(self)

  29. if __name__ == '__main__':
  30.     app = QtWidgets.QApplication(sys.argv)
  31.     window = SecWindowAct()
  32.     window.show()
  33.     sys.exit(app.exec_())
复制代码


#### 3. 使用信号和槽机制
你可以利用 PyQt5 的信号和槽机制来管理窗口之间的通信,而不是简单地关闭和打开窗口。

  1. # first_wind_act.py
  2. import sys
  3. from PyQt5 import QtWidgets
  4. import first_wind
  5. import sec_wind_act

  6. class FirstWindowAct(first_wind.Ui_Dialog, QtWidgets.QMainWindow):
  7.     def __init__(self):
  8.         super(FirstWindowAct, self).__init__()
  9.         self.setupUi(self)
  10.         self.test_button.clicked.connect(self.open_second_window)
  11.         self.sec_window = sec_wind_act.SecWindowAct()
  12.         self.sec_window.close_signal.connect(self.show)

  13.     def open_second_window(self):
  14.         self.hide()
  15.         self.sec_window.show()

  16. if __name__ == '__main__':
  17.     app = QtWidgets.QApplication(sys.argv)
  18.     window = FirstWindowAct()
  19.     window.show()
  20.     sys.exit(app.exec_())

  21. # sec_wind_act.py
  22. import sys
  23. from PyQt5 import QtCore, QtWidgets
  24. import sec_wind

  25. class SecWindowAct(sec_wind.Ui_Dialog, QtWidgets.QMainWindow):
  26.     close_signal = QtCore.pyqtSignal()

  27.     def __init__(self):
  28.         super(SecWindowAct, self).__init__()
  29.         self.setupUi(self)
  30.         self.test_button.clicked.connect(self.close_and_emit_signal)

  31.     def close_and_emit_signal(self):
  32.         self.close_signal.emit()
  33.         self.close()

  34. if __name__ == '__main__':
  35.     app = QtWidgets.QApplication(sys.argv)
  36.     window = SecWindowAct()
  37.     window.show()
  38.     sys.exit(app.exec_())
复制代码


通过这些方法,可以有效地解决窗口切换导致的闪退问题,同时保持代码的清晰结构。如果你有任何疑问或需要进一步的解释,欢迎继续提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-9-1 15:19:12 | 显示全部楼层    本楼为最佳答案   
错误的super调用:
在FirstWindowAct和SecWindowAct的构造函数中,你错误地调用了super。你应该使用当前类名作为第一个参数,而不是Ui_Dialog(它不是一个QMainWindow的子类)。这会导致构造函数没有正确初始化QMainWindow的部分,可能导致程序行为异常。
修改前:

  1. super(first_wind.Ui_Dialog, self).__init__()
复制代码

修改后:

  1. super(FirstWindowAct, self).__init__()
  2. 同样,对于SecWindowAct也做相同的修改。
复制代码


错误的窗口设置:
在Ui_Dialog类中,你尝试将main_widget和test_button添加到Dialog上,但实际上你应该将它们添加到self.main_widget上(如果你打算在QMainWindow中使用中央小部件的话)。不过,因为你直接继承自QMainWindow,你可能不需要main_widget,除非你有特定的布局需求。
__del__方法的误解:
在Python中,__del__方法(如果定义了)是在对象被垃圾回收时调用的。但是,Python的垃圾回收是不确定的,且依赖于对象的引用计数和循环引用检测。在你的情况下,self的回收与类定义在哪个文件中无关,而是与对象的引用和使用情况有关。
程序结构:
你的程序结构看起来有些混乱,特别是关于如何组织和导入模块。通常,UI类和相关的逻辑应该分开,并且每个窗口的UI和逻辑应该在同一个模块或包中。
示例


  1. # first_wind_act.py  
  2. import sys  
  3. from PyQt5 import QtWidgets  
  4. from first_wind import Ui_Dialog  
  5.   
  6. class FirstWindowAct(QtWidgets.QMainWindow):  
  7.     def __init__(self):  
  8.         super(FirstWindowAct, self).__init__()  
  9.         self.ui = Ui_Dialog()  
  10.         self.ui.setupUi(self)  # 将self(QMainWindow实例)传递给setupUi  
  11.   
  12.         self.ui.test_button.clicked.connect(self.opn_btn_clicked)  
  13.         self.sec_wind = None  
  14.   
  15.     def opn_btn_clicked(self):  
  16.         self.close()  
  17.         from sec_wind_act import SecWindowAct  
  18.         self.sec_wind = SecWindowAct()  
  19.         self.sec_wind.show()  
  20.   
  21. if __name__ == '__main__':  
  22.     app = QtWidgets.QApplication(sys.argv)  
  23.     root = FirstWindowAct()  
  24.     root.show()  
  25.     sys.exit(app.exec_())
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 03:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表