首页 > 解决方案 > PyQt5多页应用:将主类分成几个文件?

问题描述

我正在尝试使用 PyQT5 和 python 3.8 构建一个相当复杂的 GUI 应用程序,但我一直坚持如何将代码划分为可管理的文件。我一般是 GUI 编程和面向对象编程的新手,并且尝试了几种我可以在互联网上找到的解决方案,但我无法让它们为我工作。所以我很抱歉,如果这个问题以前被问过很多次,但我认为我需要一些专门针对我的项目量身定制的提示。

我还不能发布图片,所以这里是应用程序外观的链接: Application GUI

我的应用程序有一个始终可见的侧边栏和一个包含多个页面的堆叠小部件(在上面的链接中可见是 14 WEL)。我有一个 main.py 文件,我想用它来设置 ui 并连接所有页面的按钮。然后我想要几个 .py 文件来处理用户输入和计算(每页一个文件)。我还有一个 helper_functions.py 文件,用于将我需要的函数存储在一页以上。到目前为止的工作是将页面类(例如 OutWelPageControl)导入 init 中的 MainWindow 类,但是我似乎无法从 OutWelPageControl 中的 getFile() 调用 createPreview() (当我使用 code=1073741845 时应用程序终止单击触发 getFile()) 的按钮。没有调用 createPreview(self, welFiles_num) 它确实有效。

主要.py:

import sys
import os
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
from helper_functions import *

# GUI FILE
from ui_main import Ui_MainWindow

class MainWindow(qtw.QMainWindow):
    def __init__(self):
        qtw.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        ## PAGE CONNECTION
        ########################################################################
        self.ui.btn_out_wel.clicked.connect(lambda: self.ui.stackedWidget.setCurrentWidget(self.ui.page_out_wel))
        #... (other pages)

        
        # This is probably wrong
        from out_wel import OutWelPageControl
        
        ## BUTTONS
        # How I want it to work
        self.ui.btn_file.clicked.connect(lambda: OutWelPageControl.getFile(self))

        self.show()
    
if __name__ == "__main__":
    app = qtw.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

helper_functions.py:

from main import *

class HelperFunctions(MainWindow):
    def getFile(self):
        fnames = qtw.QFileDialog.getOpenFileNames(self, 'WEL-Datei öffnen', 'C:\\',"*.WEL")[0]
        return (fnames)

页面 out_wel.py:

from main import *
from helper_functions import *

class OutWelPageControl(MainWindow):
    def getFile(self):
        welFiles = HelperFunctions.getFile(self)

        # Label Input File
        welFiles_string = []
        for wel in welFiles:
            welFiles_string.append(os.path.basename(wel))
        welFiles_string2 = ', '.join(welFiles_string)
        self.ui.lbl_filepath.setText(welFiles_string2)

        welFiles_num = []
        for wel in welFiles:
            welFiles_num.append(os.path.splitext(os.path.basename(wel))[0])
        
        # Call another function
        createPreview(self, welFiles_num)
    
    def createPreview(self, welFiles_num):
        pass

所以我的问题基本上是如何划分应用程序代码,让每个页面都有自己的 .py 文件,并且仍然可以更改 ui 的元素?页面文件是否必须包含 MainWindow 的子类,或者是否有其他选项可以使其工作?

标签: pythonpyqt5

解决方案


这里有相当多的代码没有一个特定的问题,但我可以尝试提供一些一般性建议,看看是否对您有任何帮助。

  1. 在 helper_functions 中,您不能from main import *像在 main 中导入 helper_functions 那样,这会导致循环导入(它们一遍又一遍地相互导入)
  2. 同样在 helper_functions 中,如果您所需要的只是不同页面中可用的一些功能,它不应该是一个类。您可以在那里拥有函数并使用helper_functions.func_name(args).
  3. from out_wel import OutWelPageControl应该在 .py 文件的顶部,而不是在主类的 init 中
  4. 对于导入和使用您的 ui 代码,请使用双重继承,这样您就不必self.ui到处使用:
class MainWindow(qtw.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self.setup_ui()
  1. 您不应该在为不同页面构建的其他类中子类化您的主类。
  2. 我会看看这个关于如何使用堆叠小部件的页面。但我相信您必须为不同的“页面”类继承 QWidget,以便它们成为可以添加到堆叠小部件的小部件。
  3. 如果你正在制作类,你应该实例化对象,例如你应该有self.out_wel_page = OutwelPageControl()
  4. 如果您在子小部件的功能中需要父小部件的某些功能,您可以随时从父小部件传递给子小self部件

如果这里有任何帮助,请告诉我,找不到一件具体的事情来解决您遇到的问题,但想尝试提供帮助。


推荐阅读