QMenu中的TriState QAction

时间:2018-12-17 10:03:07

标签: c++ qmenu qcheckbox qwidgetaction

我需要一个可检查的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 Action。但是,与普通的QAction不同,TriState在交互时不会关闭菜单。这怎么办?

另一个问题是我的《 TriState动作》的布局(视觉表示)不同。与普通的QAction相比,如何使其更相似? (实际上,这似乎是一个非常困难的问题。)

1 个答案:

答案 0 :(得分:1)

action 知道其菜单,并在您的PdfDocument GlobalPdfDocument = new PdfDocument(new PdfWriter(multiContentPdf)); PdfWriter Writer = new PdfWriter(memStreamOfAddressAndBarcode); Writer.SetCloseStream(false); // Prevent the Writer from closing the MemoryStream PdfDocument InitialPdfDoc = new PdfDocument(Writer); InitialPdfDoc.AddNewPage(); InitialPdfDoc.Close(); // Closing the document finishes the result PDF memStreamOfAddressAndBarcode.Position = 0; // Re-position the stream to the start of the PDF InitialPdfDoc = new PdfDocument(new PdfReader(memStreamOfAddressAndBarcode)); // Create r/o document InitialPdfDoc.CopyPagesTo(1, InitialPdfDoc.GetNumberOfPages(), GlobalPdfDocument); 中添加以下行:

foreach ($data["results"] as $row) {
if ( $this->session->get_userdata('sessiondata')['maxid'] > $row->id)
$this->session->unset_userdata('maxid');
$this->session->set_userdata('maxid',$row->id);
echo "new value".$this->session->get_userdata('sessiondata')['maxid'];
}

main类中,添加一个插槽以捕获复选框triStateAction->setMenu(&menu); 信号,然后从此处关闭菜单:

TriStateAction

不要忘记在stateChanged构造函数中连接插槽:

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