【问题标题】:Creating custom widget in pyqt5在 pyqt5 中创建自定义小部件
【发布时间】:2020-11-10 00:00:43
【问题描述】:

我知道有特定于该主题的答案,但我正在尝试创建如下所示的节点小部件

这是我试过的代码。

from PyQt5.QtWidgets import *


class NNodeLayout(QWidget):

    def __init__(self, container):
        super(NNodeLayout, self).__init__(container)
        
        self.node_frame = QFrame(container)

        self.node_frame.setFrameShape(QFrame.StyledPanel)
        self.node_frame.setStyleSheet('background-color: blue')
        self.node_frame.setMinimumSize(50, 50)

        self.node_frame_layout = QVBoxLayout()
        self.node_frame_grid_layout = QGridLayout()  
        self.node_frame_layout.setSpacing(0)
        self.node_frame_layout.setContentsMargins(0, 0, 0, 0)
        self.node_frame_grid_layout.setContentsMargins(5, 0, 5, 0)

        self.node_frame_layout.addWidget(QLabel('hello: '))
        self.node_frame_layout.addLayout(self.node_frame_grid_layout)
        self.node_frame.setLayout(self.node_frame_layout)


    def n_label(self, lbl_name):
        print(lbl_name)
        lbl = QLabel(lbl_name)
        lbl.setStyleSheet('background-color:blue')
        self.node_frame_grid_layout.addWidget(lbl)

    def n_input(self, place_holder = ""):
        text_input = QLineEdit()
        text_input.placeholderText(place_holder)
        self.node_frame_grid_layout.addWidget(text_input)

    def n_input_point_shape_color(self):
        pass

    def n_top_bar(self):
        pass

    def n_move(self, x, y):
        self.node_frame.move(x, y)

    def n_resize(self, width, height):
        self.node_frame.resize(width, height)

    def n_geometry(self):
        return self.node_frame.geometry()

我需要添加那些标记为红色的套接字以显示在文本旁边

【问题讨论】:

    标签: python qt pyqt pyqt5


    【解决方案1】:

    很遗憾,您不能直接从子部件中绘制父部件。或者,更好的是,您可以这样做,但如果您有很多孩子,这可能会导致一些性能问题,因为每个孩子都会要求重新绘制父母,这并不好。

    另一方面,您的方法存在一些问题:不仅您的 NNodeLayout 不是布局,而且您实际上并没有使用它,因为您正在添加 another em> 小部件(框架)。

    最简单的解决方案是创建一个包含 2 个嵌套垂直布局的 QFrame 子类,并重新实现绘制事件。

    class NodeFrame(QFrame):
        _margin = 4
        _styleSheet = '''
                NodeFrame {{
                    border: 1px solid white;
                    border-radius: {0}px;
                    background: #3f3f3f;
                    margin: {0}px;
                }}
                QWidget {{
                    color: white;
                }}
                QLineEdit {{
                    color: palette(text);
                }}
            '''
        def __init__(self, parent=None):
            super().__init__(parent)
    
            layout = QVBoxLayout(self)
            self.headerLayout = QVBoxLayout()
            layout.addLayout(self.headerLayout)
            self.contentLayout = QVBoxLayout()
            layout.addLayout(self.contentLayout)
    
            self.options = []
            self.setMargin(self._margin)
    
        def setMargin(self, margin):
            self._margin = max(4, margin)
            self.setStyleSheet(self._styleSheet.format(self._margin))
    
        def addHeaderWidget(self, widget):
            self.headerLayout.addWidget(widget)
    
        def removeHeaderWidget(self, widget):
            self.headerLayout.removeWidget(widget)
    
        def addOption(self, widget, color=Qt.white):
            self.insertOption(-1, widget, color)
    
        def insertOption(self, index, widget, color=Qt.white):
            if index < 0:
                index = self.contentLayout.count()
            self.contentLayout.insertWidget(index, widget)
    
            self.options.insert(index, (widget, color))
    
        def removeOption(self, index):
            widget, color = self.options.pop(index)
            self.contentLayout.removeWidget(widget)
            widget.deleteLater()
            self.update()
    
        def paintEvent(self, event):
            super().paintEvent(event)
            qp = QPainter(self)
            qp.setPen(Qt.darkGray)
            for label, color in self.options:
                geo = label.geometry()
                top = geo.y() + geo.height() / 2 - self._margin
                qp.setBrush(color)
                qp.drawEllipse(0, top, self._margin * 2, self._margin * 2)
    
    
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        w = NodeFrame()
        w.addHeaderWidget(QLabel('I am a header'))
        w.addOption(QLabel('Test 1'), Qt.green)
        w.addOption(QLabel('Test 2'), Qt.white)
        w.addOption(QLineEdit('Hello'), QColor('orange'))
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 在removeOption下我应该传递标签参数吗?
    • @JacksonPro 如果你看函数,参数是index,这是你要删除的小部件的索引。如果您想使用小部件实例删除,您只需调用self.contentLayout.removeWidget(widget) and cycle through the contents of self.options`并检查参数中给出的小部件是否相同。
    • 感谢评论,但我在 removeOption 方法下收到错误,称为未解析的引用“标签”。
    • 您显然需要将参数从index 更改为widget
    • 我在询问 removeOption 下的 label.deleteLater()
    猜你喜欢
    • 2017-11-06
    • 1970-01-01
    • 2022-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    • 2023-03-20
    • 2019-11-20
    相关资源
    最近更新 更多