создание подкласса QGroupBox, чтобы он мог быть членом QButtonGroup - PullRequest
0 голосов
/ 24 апреля 2020

QButtonGroups может иметь флажки. Но вы не можете добавить их в QButtonGroup, потому что они не наследуют QAbstractButton.

Было бы очень хорошо, если бы некоторые пользовательские интерфейсы могли иметь несколько 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_())

Этот код не работает, как только вы пытаетесь добавить супергруппу в группу кнопок. PyQt5 явно не поддерживает множественное наследование. Но есть несколько примеров в дикой природе, например, из этого блога .

В этом простом примере было бы легко управлять кликами программным способом. Но когда вы добавляете больше групповых блоков, это становится все более грязным. Или что, если вы хотите QButtonGroup с кнопками, флажками и групповыми полями? Тьфу.

1 Ответ

4 голосов
/ 24 апреля 2020

Нет необходимости создавать класс, который наследуется от QGroupBox и QAbstractButton (к тому же это невозможно в pyqt или Qt / C ++). Решение состоит в том, чтобы создать QObject, который обрабатывает состояния другого QGroupBox, когда проверяется любой QGroupBox, и я реализовал это для старого ответа для Qt / C ++, так что этот ответ - просто перевод:

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_())
...