Qt Designer 中的自定义小部件,框架中具有预先存在的布局
Custom widget in Qt Designer with pre-existing layout in frame
一个项目使用自定义框架小部件实现了一种 "cover" 隐藏小部件(将其视为防止按下按钮的安全盖)。这是必需的视觉设计。 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());
}
设计不是我的,我被要求修复它遇到的奇怪的视觉故障。此 "frame" 在 Qt 设计器中用作小部件之一。过了一会儿突然所有东西都调整了大小,这引发了问题 "what is wrong with this code"。 Qt 发出有关尝试添加已存在布局的警告:我想 that 可能会导致问题,因为一个框架必须同时只有一个布局? 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 也有类似的问题,它总是有自己的 "special" 布局,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 为:
#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";
}
所以我还没有使用过 QT,但我打算试一试。我认为,第一件事是您应该使用 QStackedLayout
来覆盖小部件 (source and QT manual)。但是你需要有一个堆栈。
所以栈应该是CQFrame的私有成员。例如
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.cpp and QLayout,似乎 QWidget 只能有一种布局。如果您添加另一个布局,则会出现错误。
再者,一个QStackedLayout就是一个QLayout,就是QObject。这可能表明它已被自动删除?
我不确定封面是否按预期在 QT 中实现。看起来你有一个你想要覆盖的 QWidget,在其之上你放置了一个未按设计使用的 QStackedLayout,即切换堆栈对象,在其之上 你放置了一个 new QWidget 是否可见。
也许底部的 QWidget 已经在(堆叠)布局中,等等。
一个项目使用自定义框架小部件实现了一种 "cover" 隐藏小部件(将其视为防止按下按钮的安全盖)。这是必需的视觉设计。 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());
}
设计不是我的,我被要求修复它遇到的奇怪的视觉故障。此 "frame" 在 Qt 设计器中用作小部件之一。过了一会儿突然所有东西都调整了大小,这引发了问题 "what is wrong with this code"。 Qt 发出有关尝试添加已存在布局的警告:我想 that 可能会导致问题,因为一个框架必须同时只有一个布局? 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 也有类似的问题,它总是有自己的 "special" 布局,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 为:
#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";
}
所以我还没有使用过 QT,但我打算试一试。我认为,第一件事是您应该使用 QStackedLayout
来覆盖小部件 (source and QT manual)。但是你需要有一个堆栈。
所以栈应该是CQFrame的私有成员。例如
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.cpp and QLayout,似乎 QWidget 只能有一种布局。如果您添加另一个布局,则会出现错误。 再者,一个QStackedLayout就是一个QLayout,就是QObject。这可能表明它已被自动删除?
我不确定封面是否按预期在 QT 中实现。看起来你有一个你想要覆盖的 QWidget,在其之上你放置了一个未按设计使用的 QStackedLayout,即切换堆栈对象,在其之上 你放置了一个 new QWidget 是否可见。 也许底部的 QWidget 已经在(堆叠)布局中,等等。