在 pushButton 中添加小部件?

Posted

技术标签:

【中文标题】在 pushButton 中添加小部件?【英文标题】:Add widgets inside pushButton? 【发布时间】:2019-11-14 07:35:48 【问题描述】:

您好,我对 PySide2 还比较陌生,并且在 maya 中设置了一些 UI。 是否有可能有一个 QPushButton 有其他小部件作为孩子?

例如,我想制作一对并排的 QPushButtona,当单击其中任何一个时,它们会相互切换打开和关闭,每个 QPushButtona 内部都应该有一个 spinBox。如果它的父按钮为“关闭”,则旋转框被禁用

我打算制作一个简单的按钮类,它可以关闭对应的按钮,所以这很简单,但我也看不到将 spinBox 放入其中的方法,也许我错过了什么?我可以在按钮中添加布局,然后在里面添加小部件吗?

感谢您的帮助

【问题讨论】:

你为什么不简单地使用QSpinBox 我正在使用 QSpinBox 。我想将一个关联的 / 放在一个可以打开或关闭的按钮内。我的问题不一定是关于旋转框,而是我是否可以将小部件作为按钮的父级 对不起,在按钮里面??这个小部件听起来很可怕!你能提供一些图片示例吗? 酷,因为我没有看到任何代码,所以我会等待图像。 我的大脑也被嵌套的东西炸了,xd。一张图片绝对可以帮助您了解您想要什么 【参考方案1】:

想看看这是否可能,看起来是的,您可以使用一个按钮并在其中嵌套另一个小部件。我认为您必须跳过更多的障碍才能使其正常工作,但这还不错。

您可以使按钮可检查,然后使用QButtonGroup 使按钮的行为类似于QRadioButton。尽管与QGroupBox 不同,您需要自己处理旋转框的启用状态。所以这是一个工作示例:

from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets


class ButtonContainer(QtWidgets.QPushButton):

    def __init__(self, parent=None):
        super(ButtonContainer, self).__init__(parent)

        self.setMinimumHeight(50)  # Set minimum otherwise it will collapse the container
        self.setCheckable(True)

        self.setStyleSheet("""
            QPushButton 
                background-color: rgb(50, 50, 50);
                border: none;
            

            QPushButton:checked 
                background-color: green;
            
        """)


class Win(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(Win, self).__init__(parent)
        self.resize(300, 0)

        # 1st groupbox and spinbox.
        self.container_layout1 = QtWidgets.QVBoxLayout()

        self.container1 = ButtonContainer()
        self.container1.setChecked(True)
        self.container1.setLayout(self.container_layout1)
        self.container1.clicked.connect(self.on_container_clicked)

        self.spinbox1 = QtWidgets.QSpinBox(parent=self.container1)  # Set the container as its parent so that we can use `findChildren` in the event later.
        self.container_layout1.addWidget(self.spinbox1)

        # 2nd groupbox and spinbox.
        self.container_layout2 = QtWidgets.QVBoxLayout()

        self.container2 = ButtonContainer()
        self.container2.setLayout(self.container_layout2)
        self.container2.clicked.connect(self.on_container_clicked)

        self.spinbox2 = QtWidgets.QSpinBox(parent=self.container2)  # Set the container as its parent so that we can use `findChildren` in the event later.
        self.container_layout2.addWidget(self.spinbox2)

        # Group buttons together so they behave as radio buttons.
        self.button_group = QtWidgets.QButtonGroup()
        self.button_group.addButton(self.container1)
        self.button_group.addButton(self.container2)

        self.main_layout = QtWidgets.QHBoxLayout()
        self.main_layout.addWidget(self.container1)
        self.main_layout.addWidget(self.container2)
        self.setLayout(self.main_layout)

        # Trigger event to set initial enabled states.
        self.on_container_clicked()

    def on_container_clicked(self):
        for container in [self.container1, self.container2]:  # Loop through all of our custom containers.
            for child in container.findChildren(QtWidgets.QWidget):  # Get all of the container's children.
                child.setEnabled(container.isChecked())  # Set its enabled state based if the container is checked.


win = Win()
win.show()

从技术上讲,您实际上并不需要子类化 QPushButton,尽管这样可以更轻松地回收代码。

【讨论】:

如果这回答了您的问题,请接受它,以便其他人知道它已经解决。否则你应该编辑你的问题并澄清它。 抱歉 - 是绿色的勾号,对应用来说比较新 ^ 是的,绿色勾号!很高兴听到解决方案有所帮助。【参考方案2】:

您实际上可以使用QGroupBox,因为您已经可以将其设为可检查并在其中添加项目。当 groupbox 的复选框被勾选时,它将禁用其任何内容。所以大部分框架已经存在。唯一的问题是而不是复选框,您希望它像QRadioButton 一样工作,以便其他禁用。我们可以用一些简单的逻辑来处理:

from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets


class Win(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(Win, self).__init__(parent)
        self.resize(300, 0)

        # 1st groupbox and spinbox.
        self.spinbox1 = QtWidgets.QSpinBox()

        self.group_layout1 = QtWidgets.QVBoxLayout()
        self.group_layout1.addWidget(self.spinbox1)

        self.groupbox1 = QtWidgets.QGroupBox("1")
        self.groupbox1.setCheckable(True)
        self.groupbox1.setLayout(self.group_layout1)
        self.groupbox1.toggled.connect(self.on_groupbox_toggled)

        # 2nd groupbox and spinbox.
        self.spinbox2 = QtWidgets.QSpinBox()

        self.group_layout2 = QtWidgets.QVBoxLayout()
        self.group_layout2.addWidget(self.spinbox2)

        self.groupbox2 = QtWidgets.QGroupBox("2")
        self.groupbox2.setCheckable(True)
        self.groupbox2.setChecked(False)
        self.groupbox2.setLayout(self.group_layout2)
        self.groupbox2.toggled.connect(self.on_groupbox_toggled)

        self.main_layout = QtWidgets.QHBoxLayout()
        self.main_layout.addWidget(self.groupbox1)
        self.main_layout.addWidget(self.groupbox2)
        self.setLayout(self.main_layout)

    def on_groupbox_toggled(self, enabled):
        # Force user to not be able to uncheck it.
        if not enabled:
            self.sender().setChecked(True)

        # Block signals so this function doesn't get triggered by other groupbox.
        self.groupbox1.blockSignals(True)
        self.groupbox2.blockSignals(True)

        # Check off other groupbox.
        if self.sender() == self.groupbox1:
            self.groupbox2.setChecked(False)
        else:
            self.groupbox1.setChecked(False)

        # Restore signals.
        self.groupbox1.blockSignals(False)
        self.groupbox2.blockSignals(False)


win = Win()
win.show()

【讨论】:

这是一个很好的方法,我仍然希望能够没有复选框,并且有一个可点击的窗格,但对于我目前的目标,这将是可行的。谢谢 还带有样式表编辑 - 这看起来很棒,感谢代码 我认为这是可能的,但您必须开始子分类并且可能需要处理更多开销。

以上是关于在 pushButton 中添加小部件?的主要内容,如果未能解决你的问题,请参考以下文章

如何验证 qtable 小部件不为空

将 Matplotlib 图形嵌入到小部件中 - PyQt5

如何在小部件扩展中添加超过 5 个小部件? WidgetBundle 的小部件的最大数量不能超过 5

Flutter:如何在 10 分钟后已经有一些小部件的列中添加小部件

Flutter:在堆栈小部件中动态添加拖放小部件

Kivy 在布局末尾添加小部件