如何在QWidgetAction的子类中设置小部件的可见性

Joe*_*Joe 7 c++ qt

Qt 5.6.3,eglfs Linux平台.

我有一些从QWidgetAction派生的类.QWidgetActions都是菜单中的父级,它们包含的小部件都是同一菜单中的父级.包含的小部件都被设置为QWidgetAction的默认小部件.QWidgetAction没有重新实现任何内容.

我认为设置QWidgetAction的可见性会自动设置包含在其中的自定义窗口小部件集的可见性?这是不正确的,因为这样做肯定不会显示和隐藏小部件所需的!?我必须做其他事情才能将可见性更改传递给包含的小部件吗?我必须直接从QWidgetAction请求窗口小部件,然后直接应用它的可见性(这似乎是一个黑客攻击)?

我对如何实现QWidgetActions感兴趣.文档几乎不存在,所以我追随人们对它们的体验.我有一个间歇性的问题,看起来像双重删除自定义小部件和可见性不按预期行事.

class Base : public QWidgetAction
{
    Q_OBJECT
public:
    explicit Base(QWidget* parent, QString labelText = "", QString iconPath = "", Qt::AlignmentFlag alignment = Qt::AlignHCenter) :
    QWidgetAction(parent),
    mCustomWidget(nullptr),
    mParentWidget(nullptr),
    mTextLabel(nullptr),
    mAlignment(alignment),
    mLabelText(labelText),
    mIconPath(iconPath) {}

    virtual ~Base() {}

protected:
    QWidget *mCustomWidget;

    QWidget *createTheWidgetSet(QWidget *parent)
    {
        if (mParentWidget == nullptr) {
            mParentWidget = new QWidget(parent);
            mCustomWidget = createCustomWidget(mParentWidget);

            if (mCustomWidget != nullptr) {
                if (!mLabelText.isEmpty()) {
                    mCustomWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
                }
            }

            int rightMargin = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);

            QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight, mParentWidget);
            layout->setContentsMargins(1, 2, rightMargin, 2);
            if (!mLabelText.isEmpty()) {
                QString some_calced_text{};
                mTextLabel = new QLabel(some_calced_text, mParentWidget);
                layout->addWidget(mTextLabel);
            } else {
                if(mAlignment == Qt::AlignLeft){
                    int some_calced_val{20};
                    layout->addSpacing(some_calced_val);
                }
            }

            if(mAlignment == Qt::AlignRight){
                layout->addStretch();
            }

            layout->addWidget(mCustomWidget);

            if(mAlignment == Qt::AlignLeft){
                layout->addStretch();
            }
        }

        setDefaultWidget(mParentWidget);

        return mCustomWidget;
    }

    virtual QWidget *createCustomWidget(QWidget *parent) = 0;

private:
    Q_DISABLE_COPY(Base)

    QWidget *mParentWidget;
    QLabel  *mTextLabel;
    Qt::AlignmentFlag mAlignment;
    QString mLabelText;
    QString mIconPath;
};

class SpinBoxActionWidget : public Base
{
    Q_OBJECT
    public:
        explicit SpinBoxActionWidget(QWidget* parent, QString labelText = "", QString iconPath = "") :
            Base(parent, labelText, iconPath),
            mSpinBox(nullptr)
        {
                createTheWidgetSet(parent);
        }

        virtual ~SpinBoxActionWidget() {}

        QSpinBox* getSpinBox() const
        {
            return mSpinBox;
        }

    protected:
        QWidget *createCustomWidget(QWidget *parent) override
        {
            if (mSpinBox == nullptr) {
                mSpinBox = new QSpinBox(parent);
                mSpinBox->setFixedHeight(22);
            }

            return mSpinBox;
        }

    private:
        Q_DISABLE_COPY(SpinBoxActionWidget)

        QSpinBox *mSpinBox;
};

/* Elsewhere in code.... */
{
    QMenu theMenu = new QMenu(parentWindow);
    SpinBoxActionWidget theAct = new SpinBoxActionWidget(theMenu);
    SpinBoxActionWidget theSecondAct = new SpinBoxActionWidget(theMenu);

    theMenu->addAction(theAct);
    theMenu->addAction(theSecondAct);

    /* I now assume that I can do this, and the entire entry in the menu
     * represented by "theAct" can be made visible and invisible.
     * This doesn't work however, either the widget remains visible,
     * or is partially hidden.
    theAct->setVisible(true);
    theAct->setVisible(false);
    */
}
Run Code Online (Sandbox Code Playgroud)

Syn*_*xis 0

您没有重新实现接口,这就是它不起作用的原因。

首先,请注意,QWidgetAction源自QActionwhich不是QWidget; 但是,它确实有一个setVisible()函数,该函数实际上只会将调用转发给该操作创建的所有小部件。

您必须重新实现QWidgetAction::createWidget(parent)才能添加新的小部件;你createCustomWidget没有做任何有用的事情。这是一个非常简单的例子:

class SpinAction : public QWidgetAction
{
    Q_OBJECT
public:
    SpinAction(QObject* parent) : QWidgetAction(parent) {}
    virtual ~SpinAction() {}
    QWidget* createWidget(QWidget* parent) { return new QSpinBox(parent); }
 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 // reimplement this function
};
Run Code Online (Sandbox Code Playgroud)

您可以将操作添加到您想要的任何容器、菜单、工具栏等...此示例将为每个容器创建一个新的小部件,并且这些创建的小部件将不会同步(例如在旋转框值上)。

我刚刚在主窗口中测试了它,将小部件操作添加到菜单和工具栏,并且调用setVisible()工作完美。