5

私はqtベースのc++アプリケーションを書いています。相互に排他的にしたいボタンがいくつかあります。一度に切り替えることができるのは1つだけです。私は通常、これにQButtonGroupを使用します。これは、ボタンのセットを管理するための優れた論理的な方法を提供します。押されると、前に押されたものは押されなくなります。これはまさに私が望む動作です。

ただし、今回はグループのチェックを完全に外したいと思います。残念ながら、これは許可されていないようですQButtonGroup

排他的:bool

このプロパティは、ボタングループが排他的であるかどうかを保持します。

このプロパティがtrueの場合、グループ内の1つのボタンのみを一度にチェックできます。ユーザーは任意のボタンをクリックしてチェックでき、そのボタンがグループ内のチェック済みボタンとして既存のボタンに置​​き換わります。

排他的グループでは、ユーザーは現在チェックされているボタンをクリックしてチェックを外すことはできません。代わりに、グループ内の別のボタンをクリックして、そのグループの新しいチェックボタンを設定する必要があります。

もちろん、これを回避する方法はいくつかあります。この動作を可能にする事前に作成された代替手段があるかどうか疑問に思って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

完全を期すために、私の場合は問題を解決したので、ここで問題の1つの可能な解決策を公開したいと思います。次のコードはQt3に有効であることに注意してください。Qt4とQt5でも機能する可能性があります。これは、多くのものを使用しないためです。

したがって、(CustomButtonタイプの)ボタンを含むウィジェットCustomWidgetがどこかにあり、ボタンを1つだけオンにできると仮定します。ウィジェット内の別のボタンをクリックすると、現在オンになっているボタンがオフになり、新しくクリックされたボタンがオンになります。

CustomWidgetに含まれるCustomButtonはすべて、次の方法で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();
}

これは、関連するfalseQButtonGroupに設定されているかどうかによって異なります。exclusive

于 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 に答える