5

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

然而,这一次,我想允许该组完全不受检查。不幸的是,这似乎是不允许的QButtonGroup

独占:布尔

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

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

在独占组中,用户不能通过点击取消选中当前选中的按钮;相反,必须单击组中的另一个按钮才能为该组设置新的选中按钮。

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

有什么建议么?

4

5 回答 5

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);
}
于 2016-07-28T21:21:14.930 回答
1

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

所以,我假设我在某处有一个包含按钮(CustomButton 类型)的小部件 CustomWidget,并且只有一个按钮可以打开。如果单击小部件中的另一个按钮,则当前打开的按钮将关闭,而新单击的按钮将打开。

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);
}

然后小部件的行为如你所愿。

于 2015-06-10T13:08:01.307 回答
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。

于 2019-01-09T09:30:58.610 回答
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)
于 2019-01-10T23:05:29.020 回答
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;
};
于 2020-01-25T14:49:27.080 回答