复合小部件包含按钮、标签等。如何构建这样的小部件以及如何使用它

2024-06-16 10:48:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找创建复合小部件的最合适的解决方案,我可以在应用程序中的几个地方重用这些小部件(图形控制界面,其中有几个子菜单,可以重用一些复杂的小部件)

我主要是尝试创建定制的QWidget、QLabel和QFrame对象,我将在多个地方使用它们。我准备了这样的例子:

class FansLabelsRight(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        print('is it working?')
        self.setGeometry(275,65,110,140)
        self.setStyleSheet("background: rgba(255,0,0,50)")
        #self.layout = QLayout(self)
        self.pane1 = QLabel(self)
        self.pane2 = QLabel(self)
        self.pane3 = QLabel(self)
        pixmap1 = QPixmap('rtC.png')
        pixmap2 = QPixmap('rtB.png')
        pixmap3 = QPixmap('rtA.png')
        self.pane1.setPixmap(pixmap1)
        self.pane2.setPixmap(pixmap2)
        self.pane3.setPixmap(pixmap3)
        #self.layout.addWidget(self.pane1)
        #self.layout.addWidget(self.pane2)
        #self.layout.addWidget(self.pane3)
        self.pane1.setGeometry(30,10,pixmap1.width(), pixmap1.height())
        self.pane2.setGeometry(35,30,pixmap2.width(), pixmap2.height())
        self.pane3.setGeometry(40,30,pixmap3.width(), pixmap3.height())
        self.setLayout(self.layout)

        self.show()

它不起作用。除此之外,我测试过的其他一些方法没有得到积极的结果,除了我基于qtdesigner构建的一种方法——创建自定义对象,它实际上向我的QMainWindow类添加了其他小部件,但这不是我所期望的,也不是我所读到的。换言之,我考虑使用带有子窗口小部件的容器。真的有可能吗

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        self.label = QLabel(Form)
        self.label.setGeometry(QtCore.QRect(60, 10, 61, 81))
        self.label.setPixmap(QPixmap("rtA.png"))
        self.label.setObjectName("label")
        self.label_2 = QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(70, 30, 51, 111))
        self.label_2.setPixmap(QPixmap("rtB.png"))
        self.label_2.setObjectName("label_2")
        self.label_3 = QLabel(Form)
        self.label_3.setGeometry(QtCore.QRect(60, 90, 47, 61))
        self.label_3.setPixmap(QPixmap("rtC.png"))
        self.label_3.setObjectName("label_3")
        self.pushButton = QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(0, 0, 75, 61))
        self.pushButton.setFlat(True)
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(0, 100, 75, 61))
        self.pushButton_2.setFlat(True)
        self.pushButton_2.setObjectName("pushButton_2")

        QtCore.QMetaObject.connectSlotsByName(Form)

你能建议我如何做到这一点吗?如何创建自己的小部件,该小部件将从多个对象构建,并将它们之间的整个逻辑保持在其类中?(按照逻辑,我理解按下一个按钮将显示另一个标签,而其他按钮将显示法令等。)

我遇到的一个问题是布局,它不允许我将这些标签放在我想要的地方

下面是它应该是什么样子的示例


Tags: selfformpng部件labellayoutqtcorepushbutton
1条回答
网友
1楼 · 发布于 2024-06-16 10:48:54

使用Qt提供的基本小部件可以做您想要做的事情,但是要记住一些缺点和注意事项

我假设您要显示的三个图像是右侧的“级别”形状,如果是这种情况,您不能使用布局,因为它们的几何体重叠:对于这种类型和外观的小部件,您必须“嵌入”子小部件,而不将其分配给布局

然后,如果您想让这些半圆箭头作为按钮进行反应,显然不能使用基本的QPushButtons,因为它们是矩形的。解决方案是子类化、覆盖paintEvent(使用图像提供按钮的自定义绘图),然后使用图像为小部件创建掩码,这样单击事件只会在其边界内发生

这是一个基本的例子:

class MyButton(QtWidgets.QPushButton):
    def __init__(self, image, parent):
        super().__init__(parent)
        self.image = QtGui.QPixmap(image)
        self.setFixedSize(self.image.size())
        self.setMask(self.image.createHeuristicMask())

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.drawPixmap(QtCore.QPoint(), self.image)


class MyWidget(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setFixedSize(110, 140)
        self.upButton = MyButton('uparrow.png', self)
        self.downButton = MyButton('downarrow.png', self)
        self.downButton.move(0, self.height() - self.downButton.height())

        self.rtcA = QtWidgets.QLabel(self)
        self.rtcA.setPixmap(QtGui.QPixmap('rtcA.png'))

        self.rtcB = QtWidgets.QLabel(self)
        self.rtcB.setPixmap(QtGui.QPixmap('rtcB.png'))

        self.rtcC = QtWidgets.QLabel(self)
        self.rtcC.setPixmap(QtGui.QPixmap('rtcC.png'))

        for label in self.rtcA, self.rtcB, self.rtcC:
            label.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)

        self.upButton.clicked.connect(self.up)
        self.downButton.clicked.connect(self.down)

        p = self.palette()
        p.setColor(p.Window, QtGui.QColor(57, 57, 57))
        self.setPalette(p)

    def up(self):
        print('going up')

    def down(self):
        print('going down')

下面是它的外观:

screenshot of the running example

如您所见,我没有使用任何布局:您只需将小部件添加为parent参数,就可以将子部件添加到“容器”小部件;这将使这些子对象显示在容器内,并且可以在父边界内自由移动

一些小音符。
对于3个指示器,我使用了已经“翻译”了实际图像内容的图像(这意味着它们被放置在小部件的左上角)。这是为了确保它们正确对齐,并避免为了获得小部件上的位置而进行的连续尝试和错误测试;例如,第三个图像实际上是这样的:

image with alpha channel shown

为了使这项工作如预期的那样有效,我必须使这些小部件“对鼠标事件透明”:因为它们是在按钮之后添加的,它们将位于按钮之上,并且按钮不会收到任何鼠标事件,因为标签将在途中。另一种可能是在标签后添加按钮,或者使用raise_()lower()

    self.upButton.raise_()
    self.downButton.raise_()
    # or, alternatively
    for label in self.rtcA, self.rtcB, self.rtcC:
        label.lower()

作为进一步的可能性,您可以为每个标签创建“遮罩图像”(每个部分的边界周围有一个坚实的非alpha背景),并使用setMask(QtGui.QPixmap('rtcA_mask.png').createHeuristicMask())类似于我对按钮所做的操作。这种方法的好处是,如果需要,可以从这些标签正确接收鼠标事件

相关问题 更多 >