TriState QAction в QMenu

Мне нужен проверяемый QAction, который кроме режимов проверил и снял флажок опции частичной проверки. Это в основном уже то, что предоставляет QCheckBox, но, к сожалению, QAction не предоставляет.

В качестве первой попытки я предложил следующий подход, реализовав QWidgetAction,

TriState.h

#pragma once

#include <QWidgetAction>
#include <QCheckBox>
#include <QLabel>
#include <QFrame>
#include <QHBoxLayout>

class TriStateAction : public QWidgetAction {
Q_OBJECT
public:
TriStateAction(QWidget* parent=nullptr) : QWidgetAction(parent) {
mChkBox = new QCheckBox;
mChkBox->setTristate(true);
auto widget = new QFrame;
widget->setLayout(new QHBoxLayout);
widget->layout()->addWidget(mChkBox);
widget->layout()->addWidget(new QLabel("TriState"));

setDefaultWidget(widget);
connect(mChkBox, &QCheckBox::stateChanged, this, &QWidgetAction::changed);
}

void setCheckState(Qt::CheckState checkState) {
mChkBox->setCheckState(checkState);
}
Qt::CheckState checkState() const {
return mChkBox->checkState();
}private:
QCheckBox* mChkBox{ nullptr };

};

С помощью этого простого TestRunner:

main.cpp

#include <QApplication>
#include <QMenu>
#include <QAction>
#include "TriStateAction.h"
int main(int argc, char** args) {
QApplication app(argc, args);
auto label=new QLabel("Test");
label->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
label->connect(label, &QLabel::customContextMenuRequested, [&](const QPoint& point) {
QMenu menu(label);
auto globalPoint = label->mapToGlobal(point);
auto triStateAction = new TriStateAction();
auto normalAction = new QAction("Check");
normalAction->setCheckable(true);
normalAction->setChecked(true);
menu.addAction(triStateAction);
menu.addAction(normalAction);
menu.exec(globalPoint);
});

label->show();
app.exec();
}

Теперь появляется контекстное меню, и я могу с радостью проверить, снять флажок и частично проверить действие TriState. Но, в отличие от обычного QAction, TriState не будет закрывать меню при взаимодействии. Как это можно сделать?

Другая проблема — это другое расположение (визуальное представление) моего действия TriState. Как это можно сделать более похожим по сравнению с обычным QAction? (На самом деле, это кажется очень сложным вопросом.)

1

Решение

Пусть действие знать его меню, добавив эту строку в свой main:

triStateAction->setMenu(&menu);

В TriStateAction класс, добавить слот, чтобы поймать флажок stateChanged сигнал, и закройте меню оттуда:

private slots:
void checkBoxStateChanged(int)
{
if (menu() != nullptr)
{
menu()->close();
}
}

Не забудьте подключить слот, в TriStateAction конструктор:

connect(mChkBox, &QCheckBox::stateChanged, this, &TriStateAction::checkBoxStateChanged);
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]