繁体   English   中英

在 PyQt5 中导入模块

[英]Import Modules in PyQt5

我在将带有 PyQt5 的小部件添加到一个使用不同模块的 QMainWindow 时遇到了一些问题。 基本上我的 GUI 有许多 windows 和小部件,我认为使用不同的模块会更有条理。 但是,当我尝试将一个小部件从一个模块添加到主模块时,它给了我一个错误,例如我尝试导入的 class 未定义。

为简化起见,下面您有一个非常简单的测试,我尝试过并得到与我的 GUI 脚本相同的错误。 我有两个模块,一个我称为“main_gui_file”,另一个是“widget_file”。

此示例中的 main_gui_file 是我在屏幕中加载的 QMainWindow,我想在 self.grid_01 中添加一个小部件,调用模块 widget_file 中的 function。

当我运行这个测试时,它给了我 NameError: name 'Add_Widgets' is not defined

下面你有两个测试模块

main_gui_file

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys

from teste.widget_file import *

class Main_GUI(QMainWindow):

    def __init__(self, *args, **kwargs):

        super(Main_GUI, self).__init__(*args, **kwargs)

        self.setGeometry(0, 0, 500, 500)

        self.main_widget = QStackedWidget()
        self.setCentralWidget(self.main_widget)

        self.widget_01 = QWidget()
        self.main_widget.addWidget(self.widget_01)
        self.grid_01 = QGridLayout()
        self.widget_01.setLayout(self.grid_01)
        self.main_widget.setCurrentWidget(self.widget_01)

        self.label1 = QLabel('a')
        self.label2 = QLabel('b')
        self.grid_01.addWidget(self.label1, 0, 0)
        self.grid_01.addWidget(self.label2, 1, 0)

        self.add_widgets = Add_Widgets()
        self.add_widgets.add_widget()

app = QApplication(sys.argv)
window = Main_GUI()

window.show()
app.exec_()

小部件文件

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

from teste.main_gui_file import *

class Add_Widgets(QMainWindow):

    def __init__(self, *args, **kwargs):

        super(Add_Widgets, self).__init__(*args, **kwargs)
        self.main_gui = Main_GUI()

    def add_widget(self):

        self.label3 = QLabel('c')
        self.main_gui.grid_01.addWidget(self.label3, 3, 0)

有谁知道为什么我在导入模块时遇到这个麻烦? 谢谢

您的代码中最重要的问题是您正在执行循环导入(这通常很糟糕)。

一般而言,这意味着在“发生”某些事情之前,它不会 go 进一步使用代码。

这就是(几乎)正在发生的事情:

  • main_gui_file已加载,并在某个时刻尝试从widget_file导入
  • 正在导入widget_file并尝试从main_gui_file加载
  • main_gui_file main_gui_file处理,widget_file尝试go
  • widget_file导入的main_gui_file现在正在尝试完成加载
  • 导入的main_gui_file还尝试创建 Main_GUI 的实例,这Add_Widgets Main_GUI它存在于widget_file中,但是此时尚未加载它,因为尝试完成加载仍然占用了导入处理main_gui_file
  • Python 对你大喊大叫,因为尚不存在Add_Widgets

但这还不够。

甚至还有一个逻辑问题(正如@NaufanRusydaFaikar部分解释的那样):您正在尝试在Add_Widgets class 中创建Main_GUI实例,这没有多大意义,因为一个已经存在,而且instance 是您要添加小部件的那个。

此外,出于同样的原因,如果您想将小部件添加到现有实例,您真的不应该创建新的 QMainWindow,因为您实际上不会使用它。

从您的代码中,我真的不明白为什么您需要另一个文件来完成所有这些工作(您可能有充分的理由,但您的代码没有显示任何内容),但我同意它建议进行以下修改:

main_gui_file.py:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys

from widget_file import *

class Main_GUI(QMainWindow):

    def __init__(self, *args, **kwargs):
        # ...
        add_widget(self, self.grid_01)

小部件文件.py:

from PyQt5.QtWidgets import *

def add_widget(parent, layout): # <-- note that there's no "self"
    parent.label3 = QLabel('c')
    layout.addWidget(parent.label3, 3, 0)

如您所见, add_widget现在是一个“孤儿” function (“孤儿”是指除了它所属的模块之外它没有任何关系,这可以从它没有缩进第一个参数的事实中看出不是一个可以与之相关的self论证)。
从技术上讲,您甚至可以通过仅使用 layout 参数调用add_widget并使用def add_widget(layout):来执行相同的操作,但这会阻止您将label3 object 设置为主要 window 的属性。

另一种更好的解决方案(也可以解决之前的逻辑问题)如下:

main_gui_file.py

# ...
class Main_GUI(QMainWindow):
    def __init__(self, *args, **kwargs):
        # ...
        self.label3 = add_widget(self.grid_01)

但只要您在widget_file.py中返回添加的小部件:

from PyQt5.QtWidgets import *

def add_widget(layout):
    label = QLabel('c')
    layout.addWidget(label, 3, 0)
    return label

请注意,这不是一种非常优雅的做事方式,因为像这样的单独导入通常是为“普通”函数(通常为不需要实例参数的普通任务调用的“util”函数)完成的,并且,当处理这些类型的对象时,通常只要导入的对象是要为其创建实例的类,就会这样做,但这确实是一个完全不同的问题。

首先,确保您的模块目录中有文件__init__.py 其次,从您的示例中,您尝试导入放置在同一目录中的两个文件。 因此,尝试导入相对路径, from teste.widget_file import *将是from.widget_file import *from teste.main_gui_file import *将是from.main_gui_file import *


编辑:

为避免循环导入,我建议将您的代码更改为

from PyQt5.QtCore import QObject

class Add_Widgets(QObject):

    def __init__(self, parent, *args, **kwargs):
        super(Add_Widgets, self).__init__(*args, **kwargs)
        self.main_gui = parent

    ...

所以你可以通过创建 Add_Widgets 实例

class Main_GUI(QMainWindow):

    def __init__(self, *args, **kwargs):

        super(Main_GUI, self).__init__(*args, **kwargs)

        ...

        self.add_widgets = Add_Widgets(self)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM