【问题标题】:subclassing QGroupBox so that it can be member of QButtonGroup子类化 QGroupBox 使其可以成为 QButtonGroup 的成员
【发布时间】:2020-04-24 18:56:43
【问题描述】:

QButtonGroups 可以有复选框。但是您不能将它们添加到 QButtonGroup,因为它们不继承 QAbstractButton。

如果某些 UI 能够拥有一些带有专用复选框的 QGroupBox,那就太好了。也就是说,您选中一个,其他 QGroupBox 将自动取消选中。

在理想的世界里,我可以这样做:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QGroupBox, QWidget, QApplication, 
                             QAbstractButton, QButtonGroup)

class SuperGroup(QGroupBox, QAbstractButton):
    def __init__(self, title, parent=None):
        super(SuperGroup, self).__init__(title, parent)
        self.setCheckable(True)
        self.setChecked(False)

class Example(QWidget):

    def __init__(self):
        super().__init__()

        sg1 = SuperGroup(title = 'Super Group 1', parent = self)
        sg1.resize(200,200)
        sg1.move(20,20)

        sg2 = SuperGroup(title = 'Super Group 2', parent = self)
        sg2.resize(200,200)
        sg2.move(300,20)

        self.bgrp = QButtonGroup()
        self.bgrp.addButton(sg1)
        self.bgrp.addButton(sg2)


        self.setGeometry(300, 300, 650, 500)
        self.setWindowTitle('SuperGroups!')
        self.show()



if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

一旦您尝试将 SuperGroup 添加到按钮组,此代码就会失败。 PyQt5 明确不支持多重继承。但是有一些examples out in the wild, like from this blog

在这个简单的示例中,以编程方式管理点击会很容易。但是,当您添加更多组框时,它会变得更加混乱。或者如果你想要一个带有按钮、复选框和分组框的 QButtonGroup 怎么办?啊。

【问题讨论】:

    标签: python pyqt pyqt5 qbuttongroup


    【解决方案1】:

    没有必要创建一个继承自 QGroupBox 和 QAbstractButton 的类(另外在 pyqt 或 Qt/C++ 中是不可能的)。解决方案是创建一个 QObject 来在检查任何 QGroupBox 时处理另一个 QGroupBox 的状态,我为 Qt/C++ 的old answer 实现了这一点,所以这个答案只是一个翻译:

    import sys
    from PyQt5.QtCore import pyqtSlot, QObject, Qt
    from PyQt5.QtWidgets import QGroupBox, QWidget, QApplication, QButtonGroup
    
    
    class GroupBoxManager(QObject):
        def __init__(self, parent=None):
            super().__init__(parent)
            self._groups = []
    
        @property
        def groups(self):
            return self._groups
    
        def add_group(self, group):
            if isinstance(group, QGroupBox):
                group.toggled.connect(self.on_toggled)
                self.groups.append(group)
    
        @pyqtSlot(bool)
        def on_toggled(self, state):
            group = self.sender()
            if state:
                for g in self.groups:
                    if g != group and g.isChecked():
                        g.blockSignals(True)
                        g.setChecked(False)
                        g.blockSignals(False)
    
            else:
                group.blockSignals(True)
                group.setChecked(False)
                group.blockSignals(False)
    
    
    class Example(QWidget):
        def __init__(self):
            super().__init__()
    
            sg1 = QGroupBox(
                title="Super Group 1", parent=self, checkable=True, checked=False
            )
            sg1.resize(200, 200)
            sg1.move(20, 20)
    
            sg2 = QGroupBox(
                title="Super Group 2", parent=self, checkable=True, checked=False
            )
            sg2.resize(200, 200)
            sg2.move(300, 20)
    
            self.bgrp = GroupBoxManager()
            self.bgrp.add_group(sg1)
            self.bgrp.add_group(sg2)
    
            self.setGeometry(300, 300, 650, 500)
            self.setWindowTitle("SuperGroups!")
            self.show()
    
    
    if __name__ == "__main__":
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    【讨论】:

    • 你是个邪恶的天才!我没有想到要制作自己的按钮组版本。您的代码非常适合组合框,但是当我尝试添加单选按钮或按钮时,它们没有排他行为。
    • 要扩展此解决方案,以便其他可检查的小部件可以成为组的一部分,您可以将add_group 中的if 语句修改为if type(group) in (QGroupBox, QPushButton, QRadioButton, QCheckBox):
    • @bfris 最好使用if isinstance(group, (QGroupBox, QPushButton, QRadioButton, QCheckBox)):
    • 是的。同样,您的解决方案更好!我不知道isinstance 的语法。
    • @bfris 或更通用和简短:if isinstance(group, (QGroupBox, QAbstractButton)):
    猜你喜欢
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    相关资源
    最近更新 更多