python-3.x 在一行中创建和编辑PyQt元素的好方法

icnyk63a  于 2022-11-26  发布在  Python
关注(0)|答案(1)|浏览(113)

这是我的第一篇stackoverflow文章,所以我希望我做的是正确的。我正在python中使用PyQt 6编写一个gui,我用纯代码来做这个,因为我更喜欢Qt设计器的控制。当我向gui添加元素时,我注意到我的代码膨胀了,越来越难导航。下面是a picture of an element和我用来生成它的代码:

lbl_size = QLabel("Size:")
lbl_size.setObjectName("lbl_size")

line_height = QLineEdit()
line_height.setObjectName("line_heigth")
line_height.setFixedWidth(40)

lbl_by = QLabel("by")
lbl_by.setObjectName("lbl_by")

line_width = QLineEdit()
line_width.setObjectName("line_width")
line_width.setFixedWidth(40)

combo_3d = QComboBox()
combo_3d.setObjectName("combo_3d")
combo_3d.addItems("2D", "3D")

hlayout_size = QHBoxLayout()
hlayout_size.addWidget(lbl_size)
hlayout_size.addWidget(line_height)
hlayout_size.addWidget(lbl_by)
hlayout_size.addWidget(line_width)
hlayout_size.addWidget(combo_3d)
hlayout_size.addStretch()
hlayout_size.setContentsMargins(10, 10, 10, 10)

我喜欢这种方法的地方是它非常清晰易读。我不喜欢的地方是,以这种方式添加元素会很快地开始增加。我正处于这样一个点上,我为我的gui中的一些页面使用这么大的init函数感到难过。
我主要的抱怨是我需要使用函数来编辑我的小部件和布局,而不是在创建小部件时传递参数。我尝试通过创建自定义类来解决这个问题,这些自定义类只需要一行就可以按照我想要的方式设置我的小部件和布局。下面是我创建的一些自定义类的示例:

class CQLabel(QLabel):
    def __init__(self, text=None, obj_name=None):
        QLabel.__init__(self)
        if text:
            self.setText(text)
        if obj_name:
            self.setObjectName(obj_name)

class CQLineEdit(QLineEdit):
    def __init__(self, placeholder_text=None, width=None, obj_name=None):
        QLineEdit.__init__(self)
        if placeholder_text:
            self.setPlaceholderText(placeholder_text)
        if width:
            self.setFixedWidth(width)
        if obj_name:
            self.setObjectName(obj_name)

class CQComboBox(QComboBox):
    def __init__(self, items=None, obj_name=None):
        QComboBox.__init__(self)
        if items:
            self.addItems(items)
        if obj_name:
            self.setObjectName(obj_name)

class CQHBoxLayout(QHBoxLayout):
    def __init__(self, items=None, stretch=False, margins=None, obj_name=None):
        QHBoxLayout.__init__(self)
        if items:
            for item in items:
                if isinstance(item, QWidget):
                    self.addWidget(item)
                elif isinstance(item, QLayout):
                    self.addLayout(item)
        if stretch:
            self.addStretch()
        if margins:
            self.setContentsMargins(margins)
        if obj_name:
            self.setObjectName(obj_name)

使用这些类生成与前面完全相同的元素所需的代码如下:

lbl_size = CQLabel(text="Size:", obj_name="lbl_size")
line_height = CQLineEdit(width=40, obj_name="line_height")
lbl_by = CQLabel(text="by", obj_name="lbl_by")
line_width = CQLineEdit(width=40, obj_name="line_width")
combo_3d = CQComboBox(items=("2D", "3D"), obj_name="combo_3d")

hlayout_size = CQHBoxLayout(items=(lbl_size, line_height, lbl_by, line_width, combo_3d), stretch=True,
                            margins=(10, 10, 10, 10), obj_name="hlayout_size")

这些语句比之前的直接函数调用更难解释,但对我来说,这完全符合预期。这种构建GUI的方式随着我添加更多元素和对小部件进行更多编辑而变得更好。
我现在的“问题”是,我构建这些类的方法(主要依赖于if语句)是我以前从未见过的,这让我怀疑这是不是一个好方法。鉴于我几乎没有大型项目的工作经验,我真的很感谢对我的方法的一些评论。它是好的?是坏的?我完全错过了一个更简单的方法?提前感谢你的帮助!
(NB:我并不关注单行程序,只是在寻找一种对抗代码膨胀的方法)

vlju58qv

vlju58qv1#

PyQt本机支持使用关键字参数在类构造函数中设置属性;事实上,它还允许直接信号连接(参见the documentation)。
例如:

label = QLabel('Hello', objectName='someLabel', font=QFont('Verdana'))
lineEdit = QLineEdit(placeholderText='type something')
button = QPushButton('click me', cliked=self.buttonClicked)

请注意,这只能在以下情况下工作:

  • 对于QObject子类(因此,例如,对于QStandardItem是不可能的);
  • 对于可写的 *Qt属性 *,如果需要自定义属性,请使用pyqtProperty装饰器;
  • 使用确切的属性名称(而不是函数getter,它可能不同);

还要注意,只有在知道需要对象名时才设置对象名(通常是为了以后对动态创建的对象、特定的QSS选择器或数据序列化(如窗口设置)进行findChild*调用),否则通常是无用的。

相关问题