QButtonGroup的替代品,不允许选择?

时间:2013-03-02 18:17:23

标签: qt radio-button

我正在编写一个基于qt的c ++应用程序。我有一些我希望互相排斥的按钮 - 一次只能切换一个按钮。我通常使用QButtonGroup - 它提供了一种很好的逻辑方式来管理按钮组。当一个人被按下时,先前按下的那个被按下,这正是我想要的行为。

但是,这一次,我想允许该组完全取消选中。不幸的是,QButtonGroup

似乎不允许这样做
  独家:bool

     

此属性保存按钮组是否为独占。

     

如果此属性为true,则组中只能有一个按钮   在任何给定时间检查。用户可以单击任何按钮进行检查   它,该按钮将替换现有的按钮作为选中   组中的按钮。

     

在专属群组中,用户无法取消选中当前选中的内容   单击按钮; ,而组中的另一个按钮必须是   单击以设置该组的新选中按钮。

当然,有很多方法可以解决这个问题。我想知道是否有QButtonGroup的预制替代品允许这种行为,以便1)我没有重新发明轮子和2)我可以保持在惯用的qt {{1}} 1}}以便将来更轻松地进行项目管理。

有什么建议吗?

5 个答案:

答案 0 :(得分:2)

在Qt5中,我使用与Laurent Michel相似的解决方案,但使用发布事件而不是新闻事件:

// Allow to uncheck button in exclusive group
void CustomButton::mouseReleaseEvent(QMouseEvent* a_Event) {
    if(group()->checkedId()==group()->id(this)) {
        if(isDown()) group()->setExclusive(false);
    }
    QToolButton::mouseReleaseEvent(a_Event);
    group()->setExclusive(true);
}

答案 1 :(得分:1)

为了完整起见,我想在这里发布一个可能的问题解决方案,因为我刚刚解决了这个问题。请注意以下代码对Qt3有效。它可能适用于Qt4和Qt5,因为它不会使用很多东西。

所以,我假设我有一个小部件CustomWidget,其中包含按钮(类型为CustomButton),并且只能打开一个按钮。如果单击窗口小部件中的另一个按钮,则会关闭当前打开的按钮,并打开新单击的按钮。

CustomWidget中包含的CustomButtons以下列方式包含在QButtonGroup中:

QButtonGroup* m_ButtonGroup = new QButtonGroup(this);
m_ButtonGroup->hide();
m_ButtonGroup->insert(Btn1);
m_ButtonGroup->insert(Btn2);
m_ButtonGroup->insert(Btn3);
m_ButtonGroup->setExclusive(true);

这里,Btn1,Btn2和Btn3的类型为CustomButton

class CustomButton : public QToolButton
{
    Q_OBJECT

  public:
    CustomButton (QWidget* apo_parent = 0, const char* as_name = 0);
    virtual ~CustomButton ();

  protected:
    virtual void mousePressEvent(QMouseEvent* a_Event);
};

您想要特别实现的方法是mousePressEvent。如果它的主体以下列方式实现:

void CustomButton ::mousePressEvent(QMouseEvent* a_Event)
{
  if(group() && isToggleButton())
  {
    CustomButton* selectedButton(dynamic_cast<CustomButton*>(group()->selected()));
    if(selectedButton)
    {
      if(selectedButton->name() == name())
      {
        group()->setExclusive(false);
        toggle();
        group()->setExclusive(true);
        return;
      }
    }
  }
  QToolButton::mousePressEvent(a_Event);
}

然后窗口小部件就像你想要的那样。

答案 2 :(得分:1)

另一个与先前答案类似的解决方案,但使用nextCheckState()似乎是我的更自然的扩展点:

void MyButton::setSemiExclusive(bool value)
{
  mSemiExclusive = value;
}

void MyButton::nextCheckState()
{
  if (mSemiExclusive)
  {
    if (auto g = group())
    {
      auto old = g->exclusive();
      if (g->checkedButton() != this)
        g->setExclusive(true);

      QAbstractButton::nextCheckState();
      g->setExclusive(old);
      return;
    }
  }

  QAbstractButton::nextCheckState();
}

这取决于关联的QButtonGroup已将exclusive设置为false。

答案 3 :(得分:1)

如果您不想扩展按钮类,也可以通过使用信号(Qt5,Python)来实现:

from PySide import QtGui

class View(QtGui.QWidget):
    def __init__(self):
        self.buttonGroup = QtGui.QButtonGroup(self)
        for button in buttons:
            self.buttonGroup.addButton(button)
            button.pressed.connect(buttonPressed)
            button.released.connect(buttonReleased)

    def buttonPressed(self):
        button = self.sender()
        checkedButton = self.buttonGroup.checkedButton()
        if checkedButton != None and checkedButton.objectName() == button.objectName():
            self.buttonGroup.setExclusive(False)

    def buttonReleased(self):
        button = self.sender()
        if self.buttonGroup.exclusive() == False:
            button.setChecked(False)
            self.buttonGroup.setExclusive(True)

    def manualDeselection:
        self.buttonGroup.setExclusive(False)
        self.buttonGroup.checkedButton().setChecked(False)
        self.buttonGroup.setExclusive(True)

答案 4 :(得分:0)

我的解决方案是派生QButtonGroup,将其设置为非排他性内部结构,并自行管理状态

class myQButtonGroup : public QButtonGroup
{
    Q_OBJECT

public:
    explicit myQButtonGroup(QObject *parent = Q_NULLPTR) : QButtonGroup(parent) {
        _bExclusive = true;
        QButtonGroup::setExclusive(false);
        connect(this, SIGNAL(buttonClicked(QAbstractButton *)), SLOT(buttonClicked(QAbstractButton *)));
    }

    void setExclusive(bool bExclusive) { _bExclusive = bExclusive; }
    bool exclusive() const { return _bExclusive; }

protected slots:
    void buttonClicked(QAbstractButton *button) {
        if (_bExclusive) {
            // just uncheck all other buttons regardless of the state of the clicked button
            QList<QAbstractButton *> buttonlist = buttons();
            for (auto iBtn = buttonlist.begin(); iBtn != buttonlist.end(); ++iBtn) {
                QAbstractButton *pBtn = *iBtn;
                if (pBtn && pBtn != button && pBtn->isCheckable()) pBtn->setChecked(false);
            }
        }
    }

protected:
    bool _bExclusive;
};