0

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

主要是我试图创建我将在几个地方使用的自定义 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()

它没有用。除了我测试的没有正面结果的其他方法之外,我期望我基于 Q tDesigner 构建的一种方法 - 创建自定义对象,该对象实际上添加到我的 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)

您能否建议我如何实现这一目标?如何创建自己的小部件,该小部件将从多个对象构建并将它们之间的整个逻辑保留在其类中?(根据逻辑,我理解按下一个按钮将显示另一个标签,而其他按钮将显示,等等......)

我遇到的问题之一是布局,它不允许我将这些标签放置在我想要的位置。

这是它应该是什么样子的示例。

4

1 回答 1

0

使用 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')

这是它的外观:

运行示例的屏幕截图

如您所见,我没有使用任何布局:您可以将子组件添加到“容器”小部件中,只需将该小部件添加为parent参数即可;这使得这些孩子出现容器内,并且可以在父边界内自由移动。

一些小笔记。
对于 3 个指标,我使用了已经“翻译”实际图像内容的图像(意味着它们被放置在小部件的左上角)。这是为了确保它们正确对齐并避免不断的试错测试以获得小部件上的位置;例如,第三张图片实际上是这样的:

显示 Alpha 通道的图像

为了使这项工作按预期进行,我必须使这些小部件“对鼠标事件透明”:因为它们是在按钮之后添加的,它们将位于它们之上,并且按钮不会接收任何鼠标事件,因为标签会在路上。另一种可能性是在标签之后添加按钮,或者,使用raise_()or 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())与我为按钮所做的类似的操作。这种方法的好处是可以从这些标签中正确接收鼠标事件,如果您需要它们的话。

于 2020-01-17T21:38:24.637 回答