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

时间:2018-01-18 08:15:38

标签: 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);
    */
}

1 个答案:

答案 0 :(得分:0)

您没有重新实现界面,这就是它无效的原因。

首先,请注意-to来自QWidgetAction a QAction;但是, 有一个 setVisible()函数,它实际上只是将调用转发给动作创建的所有小部件。

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

createCustomWidget

您可以将动作添加到您想要的任何容器,菜单,工具栏等......此示例将为每个容器创建一个新窗口小部件,并且这些创建的窗口小部件将不会同步(例如关于spinbox值)。

我刚刚在主窗口中测试了它,并在菜单和工具栏中添加了一个小部件操作,并且调用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 }; 可以完美地工作。