我正在编写一个基于qt
的c ++应用程序。我有一些我希望互相排斥的按钮 - 一次只能切换一个按钮。我通常使用QButtonGroup - 它提供了一种很好的逻辑方式来管理按钮组。当一个人被按下时,先前按下的那个被按下,这正是我想要的行为。
但是,这一次,我想允许该组完全取消选中。不幸的是,QButtonGroup
独家:bool此属性保存按钮组是否为独占。
如果此属性为true,则组中只能有一个按钮 在任何给定时间检查。用户可以单击任何按钮进行检查 它,该按钮将替换现有的按钮作为选中 组中的按钮。
在专属群组中,用户无法取消选中当前选中的内容 单击按钮; ,而组中的另一个按钮必须是 单击以设置该组的新选中按钮。
当然,有很多方法可以解决这个问题。我想知道是否有QButtonGroup
的预制替代品允许这种行为,以便1)我没有重新发明轮子和2)我可以保持在惯用的qt
{{1}} 1}}以便将来更轻松地进行项目管理。
有什么建议吗?
答案 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;
};