Qt Designer中的自定义小部件,具有预先存在的框架布局

时间:2017-02-22 07:13:21

标签: c++ user-interface widget qt4 qt-creator

项目使用自定义框架小部件来实现一种"封面"隐藏小部件(将其视为防止按下按钮的安全封面)。这是必需的视觉设计。 Qt版本是4.6

#ifndef CQFRAME_H
#define CQFRAME_H

#include <QFrame>

#include <QtDesigner/QDesignerExportWidget>

//! [0] //! [1]
class CQFrame : public QFrame   
// our agreement about "custom" widgets is to start them with CQ
{
    Q_OBJECT
    Q_ENUMS(FrameColorStyle)

    Q_PROPERTY(FrameColorStyle colorStyle READ getColorStyle WRITE setColorStyle)
    Q_PROPERTY(bool border READ border WRITE setBorder)
//! [0]
private:
    bool curCover;
    QFrame *frameCover;
public:
    enum FrameColorStyle  {fcDark, fcLight, fcTransparent, fcSystemDefault, fcRed, fcGreen, fcBlue};

    CQFrame(QWidget *parent = 0);

    void setCoverPropertie();
    void setCover(bool state);
protected:
    void resizeEvent(QResizeEvent *event);
    FrameColorStyle m_colorStyle;
    QString pstylebord;
    bool m_border;
//! [2]
};
//! [1] //! [2]

#endif

我省略了与问题无关的getter和setter。这是实施:

void CQFrame::setCoverPropertie()
{
    QString str, strAlpha, gradient1, gradient2;
    strAlpha.setNum(200);
    gradient1 = "rgba("+str.setNum(cwDisableColor.red())+", "
                +str.setNum(cwDisableColor.green())
                +", "+str.setNum(cwDisableColor.blue())
                +" ," +strAlpha+ " )";
    gradient2 = "rgba("+str.setNum(cwLbColor.red())+", "
                +str.setNum(cwLbColor.green())+", "
                +str.setNum(cwLbColor.blue())+" ," +strAlpha+ " )";

    QStackedLayout *stackedLayout = new QStackedLayout(this);
    frameCover  = new QFrame(this);     
    frameCover->setGeometry(rect());
    frameCover->setStyleSheet("QFrame{border:5px solid  "+strLbColor+"; "
                                  "border-radius: 10px; background-color: "
                                  "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.5, stop: 0 "
                                  +gradient1+" , stop: 1 "+gradient2+"); }");

    stackedLayout->addWidget(frameCover);
    stackedLayout->setStackingMode(QStackedLayout::StackAll);
}

void CQFrame::setCover(bool state)
{
    frameCover->setVisible(curCover = state);
}

void CQFrame::resizeEvent(QResizeEvent *event)
{
    if (curCover)
        frameCover->setGeometry(rect());
}

设计不是我的,我被要求修复它遇到的奇怪的视觉故障。这个&#34;框架&#34;在Qt设计器中用作小部件之一。过了一会儿,突然间一切都调整了大小,这引发了问题&#34;这个代码有什么问题&#34;。当一个已经存在时,Qt会发出关于尝试添加布局的警告:我认为 可能会导致问题,因为一个框架必须只有一个布局? Qt Creator生成的代码类似于

void setupUi(CQFrame *CQWnd1T2SeparateONForm)
    {
        if (CQWnd1T2SeparateONForm->objectName().isEmpty())
            CQWnd1T2SeparateONForm->setObjectName(QString::fromUtf8("CQWnd1T2SeparateONForm"));
        CQWnd1T2SeparateONForm->resize(735, 241);
        QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        sizePolicy.setHorizontalStretch(0);
        sizePolicy.setVerticalStretch(0);
        sizePolicy.setHeightForWidth(CQWnd1T2SeparateONForm->sizePolicy().hasHeightForWidth());
        CQWnd1T2SeparateONForm->setSizePolicy(sizePolicy);
        gridLayout = new QGridLayout(CQWnd1T2SeparateONForm); // warning here
}

标准的QMainWindow也有类似的问题,它始终拥有自己的特殊&#34; Qt Creator自动解决的布局,通过向布局添加中央窗口小部件,并将其他所有内容添加到该窗口小部件。我不知道的是如何使用Qt Creator插件模拟自定义小部件的相同行为。 或者可以使用CQFrame的替代设计。 CQFrame在十几个项目中重复使用,在大约30多个面板中,因此对它们重用代码都是严格的要求。 当前的插件非常基础:

class QDESIGNER_WIDGET_EXPORT CQFramePlugin : public QObject,
                             public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)

public:
    CQFramePlugin(QObject *parent = 0);

    bool isContainer() const;
    bool isInitialized() const;
    QIcon icon() const;
    QString domXml() const;
    QString group() const;
    QString includeFile() const;
    QString name() const;
    QString toolTip() const;
    QString whatsThis() const;
    QWidget *createWidget(QWidget *parent);
    void initialize(QDesignerFormEditorInterface *core);

private:
    bool initialized;
};

.cpp for it:

#include "cqframe.h"
#include "cqframeplugin.h"

#include <QtPlugin>

CQFramePlugin::CQFramePlugin(QObject *parent)
    : QObject(parent)
{
    initialized = false;
}

void CQFramePlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
    if (initialized)
        return;

    initialized = true;
}

bool CQFramePlugin::isInitialized() const
{
    return initialized;
}

QWidget *CQFramePlugin::createWidget(QWidget *parent)
{
    return new CQFrame(parent);
}

QString CQFramePlugin::name() const
{
    return "CQFrame";
}

QString CQFramePlugin::group() const
{
    return "CustomWidgets";
}

QIcon CQFramePlugin::icon() const
{
    return QIcon(":/Resources/frame_icon.png");
}

QString CQFramePlugin::toolTip() const
{
    return "";
}

QString CQFramePlugin::whatsThis() const
{
    return "";
}

bool CQFramePlugin::isContainer() const
{
    return true;
}

QString CQFramePlugin::domXml() const
{
    return "<ui language=\"c++\">\n"
           " <widget class=\"CQFrame\" name=\"Frame\">\n"
           "  <property name=\"geometry\">\n"
            "   <rect>\n"
            "    <x>0</x>\n"
            "    <y>0</y>\n"
            "    <width>120</width>\n"
            "    <height>80</height>\n"
            "   </rect>\n"
            "  </property>\n"
           " </widget>\n"
           "</ui>";
}

QString CQFramePlugin::includeFile() const
{
    return "cqframe.h";
}

1 个答案:

答案 0 :(得分:0)

所以我还没有和QT合作过,但是我会尝试一下。首先,我认为,您应该使用QStackedLayout来覆盖小部件(sourceQT manual)。但是你需要一个堆栈。

因此堆栈应该是CQFrame的私有成员。 E.g。

class CQFrame : public QFrame   
{
[...]
private:

    QWidget* _frame; // Frame to cover.
    QFrame* _frameCover;
    QStackedLayout* _stackedLayout;
[...]

可能:

CQFrame::~CQFrame()
{
    delete _stackedLayout;
    delete _frameCover;
}

然后你可以初始化构造函数中的所有内容

CQFrame::CQFrame(QWidget* parent = 0, QWidget* frame)
    : QFrame(parent)
    , _frame(frame)
    , _frameCover(new QFrame(this))
    , _stackedLayout(new QStackedLayout(this))
{
        _frameCover->setGeometry(rect());
        [...]
        _stackedLayout->addWidget(frame);
        _stackedLayout->addWidget(frameCover);
        //default:_stackedLayout->setStackingMode(QStackedLayout::StackOne);
}

然后,您可以使用

在堆栈中的小部件之间切换
void CQFrame::SetCover(bool state)
{
    if (state) _stackedLayout->setCurrentWidget(_frameCover);
    else _stackedLayout->setCurrentWidget(_frame);
}

也许这有助于你。

<强> EDIT2: 我删除了这段代码,因为它不正确,无论是编码格式,还是想法 所以我检查了QT源QStackedLayout.cppQLayout,看起来QWidget只能有一个布局。如果添加其他布局,则会出现错误。 此外,QStackedLayout是QLayout,是QObject。这可能表明它被自动删除了?

我不确定封面是否在QT中实现。看起来你有一个想要覆盖的QWidget,在其上你放了一个未按设计使用的QStackedLayout,即切换堆栈对象,在其上你放置一个 new QWidget,它是否可见。 也许底部的QWidget已经处于(堆叠)布局等等。