在PyQT5中创建自定义小部件

时间:2017-06-06 01:50:38

标签: python python-3.x qt pyqt pyqt5

我想知道如何在pyqt中创建自定义小部件。我已经看到了很多不同的C ++示例,以及pyqt的几个非描述性示例,但没有真正解释如何实现它并实现它。特别是没有一个例子基本上不只是修改了qt-designer输出,而且我从头开始编写我的代码,所以这不是很有帮助。

到目前为止,我能找到的最好的例子是basically just someone modifying qt-designer code并没有真正解释其中的任何内容。

有人可以告诉我一个如何创建自定义小部件的示例吗?

修改 我正在尝试使用嵌入式QStackedWidget创建一个小部件,并在底部按钮来循环页面。

我还计划为每个页面创建一个单独的小部件,但考虑到我实际上无法完成第一步,我认为当我到达它时我会越过那个桥。

2 个答案:

答案 0 :(得分:4)

下面展示了如何使用2个按钮实现QStackedWidget,基本思路是设计布局,为此我们分析必须放置QVBoxLayout来放置{{ 1}}和另一个布局,第二个布局将是一个QStackedWidget来拥有按钮。然后我们连接处理页面之间转换的信号。同样在这个例子中,我创建了3种类型的小部件,这些小部件将放置在每个页面上。

QHBoxLayout

enter image description here

enter image description here

enter image description here

答案 1 :(得分:2)

以下是一些不错的建议,示例和方法。

我认为您可以通过三种方式划分自定义窗口小部件或任何自定义“事物”。

  1. Behavior:当您使用所需的行为覆盖其默认方法时。
  2. Layout:您在布局中添加的所有qt对象,项目或窗口小部件都将遵循其位置规则及其政策。
  3. StyleSheet:如果你在Widget对象中设置了Widget的样式,那就设置它的“CSS”,只是为了简洁。以下是一些referencesexamples
  4. 注意:如果是非Widget对象,您将无法设置StyleSheet,因此您必须覆盖一些绘制方法,创建自己的Painters等等。

    以下是一些随机的示例,其中包含一些评论,我们接近上面提到的3个主题:

    import random
    import sys
    
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWidgets import QDialog
    from PyQt5.QtWidgets import QHBoxLayout
    from PyQt5.QtWidgets import QPushButton
    from PyQt5.QtWidgets import QVBoxLayout
    from PyQt5.QtWidgets import QWidget
    
    
    
    class MovableWidget(QWidget):
    
        def __init__(self):
            super(MovableWidget, self).__init__()
    
            #remove the frame
            self.setWindowFlags(Qt.CustomizeWindowHint)
            self.pressing = False
    
        # overriding the three next methods is a way to customize your Widgets
        # not just in terms of appearance but also behavioral.
    
        def mousePressEvent(self, QMouseEvent):
            #the pos of the widget when you first pressed it.
            self.start = QMouseEvent.pos()
            #to make sure you are holding mouse button down
            self.pressing = True
    
        def mouseMoveEvent(self, QMouseEvent):
    
            # You can Verify if it's also the left button and some other things
            # you need.
            if self.pressing : #and QMouseEvent.type() == Qt.LeftButton
                self.end = QMouseEvent.pos()
                self.delta = self.mapToGlobal(self.end-self.start)
                self.move(self.delta)
                self.end = self.start
    
        def mouseReleaseEvent(self, QMouseEvent):
            self.pressing = False
    
    # inherits from QDialog and from MovableWidget so we can have its properties.
    class CustomDialog(QDialog, MovableWidget):
    
        def __init__(self):
            super(CustomDialog, self).__init__()
    
            #Make the Dialog transparent
            self.setAttribute(Qt.WA_TranslucentBackground)
    
            # the widget will dispose itself according to the layout rules he's
            # inserted into.
            self.inner_widget = QWidget()
            self.inner_widget.setFixedSize(300,300)
            self.inner_layout = QHBoxLayout()
            self.inner_widget.setLayout(self.inner_layout)
    
            self.btn_change_color = QPushButton("Roll Color")
    
            self.btn_change_color.setStyleSheet("""
                background-color: green;
            """)
    
            # will connect to a function to be executed when the button is clicked.
            self.btn_change_color.clicked.connect(self.change_color)
            self.inner_layout.addWidget(self.btn_change_color)
    
            # Choose among many layouts according to your needs, QVBoxLayout,
            # QHBoxLayout, QStackedLayout, ... you can set its orientation
            # you can set its policies, spacing, margins. That's one of the main
            # concepts you have to learn to customize your Widget in the way
            # you want.
            self.layout = QVBoxLayout()
    
            # stylesheet have basically CSS syntax can call it QSS.
            # it can be used only on objects that come from Widgets
            # Also one of the main things to learn about customizing Widgets.
    
            # Note: The stylesheet you set in the "father" will be applied to its
            # children. Unless you tell it to be applied only to it and/or specify
            # each children's style.
    
            # The point I used inside the StyleSheet before the QDialog
            # e.g .QDialog and .QWidget says it'll be applied only to that
            # instance.
    
            self.setStyleSheet("""
                .QDialog{
                    border-radius: 10px;
                }
            """)
            self.inner_widget.setStyleSheet("""
                .QWidget{
                    background-color: red;
                }
            """)
    
    
            self.layout.addWidget(self.inner_widget)
            self.setLayout(self.layout)
    
        def change_color(self):
            red = random.choice(range(0,256))
            green = random.choice(range(0,256))
            blue = random.choice(range(0,256))
            self.inner_widget.setStyleSheet(
            """
                background-color: rgb({},{},{});
            """.format(red,green,blue)
            )
    
    # since MovableWidget inherits from QWidget it also have QWidget properties.
    class ABitMoreCustomizedWidget(MovableWidget):
    
        def __init__(self):
            super(ABitMoreCustomizedWidget, self).__init__()
    
            self.layout = QHBoxLayout()
            self.setLayout(self.layout)
    
            self.custom_button1 = CustomButton("Button 1")
            self.custom_button1.clicked.connect(self.btn_1_pressed)
            self.custom_button2 = CustomButton("Button 2")
            self.custom_button2.clicked.connect(self.btn_2_pressed)
    
            self.layout.addWidget(self.custom_button1)
            self.layout.addWidget(self.custom_button2)
    
        def btn_1_pressed(self):
            self.custom_button1.hide()
            self.custom_button2.show()
    
        def btn_2_pressed(self):
            self.custom_button2.hide()
            self.custom_button1.show()
    
    class CustomButton(QPushButton):
    
        # it could receive args and keys** so all the QPushButton initializer
        # would work for here too.
        def __init__(self, txt):
            super(CustomButton, self).__init__()
            self.setText(txt)
            self.setStyleSheet("""
                QPushButton{
                    background-color: black;
                    border-radius: 5px;
                    color: white;
                }
                QPushButton::pressed{
                    background-color: blue;
                }
                QPushButton::released{
                    background-color: gray;
                }
            """)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        custom_dialog = CustomDialog()
        custom_widget = ABitMoreCustomizedWidget()
        custom_dialog.show()
        custom_widget.show()
        sys.exit(app.exec_())
    

    提示:

    您还可以在窗口小部件中使用蒙版,以“疯狂”方式更改其格式。例如,如果您需要一个空心环状小部件,您可以使用这种格式和一些透明度的图像,从中创建一个QPixMap并将其作为掩码应用于您的小部件。不是一件微不足道的工作,而是一种很酷的工作。

    由于我向您展示了没有“TopBar”且没有Frame的示例,您还可以查看this其他问题,其中我将展示如何创建自己的顶栏,移动并调整概念大小。