[Qt C++] UI的半自动化生成

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZJU_fish1996/article/details/88770703

效果演示 

      本次所做的工作主要是,由于物体属性的UI控件基本就那么几种类型,所以可以将UI生成、事件绑定等基本代码通过宏的形式来自动生成,可以减少开发时的编码量,达到快速迭代开发的目的。如上图右侧的面板,均通过半自动化生成。

        得到上图最右边所示界面,仍然需要一些代码,但主要是描述内容性质的代码,如下:

        // .h

        

       // .cpp

        

        

        以上描述性代码主要包括了三个部分:

        (1) 注册部分:在头文件中注册用到的控件。不同类型的控件使用不同的宏,注册名字在同一类中不可重复。

        (2) 初始化部分:在构造函数中做描述性初始化,如指定描述文本、取值范围一些基本设定。

        (3) 值绑定部分(也可在初始化中绑定,也可分离):在合适的位置绑定数据,之后UI相关操作会自动修改绑定的值。 

具体实现

        实现的基本思路将可以重复的编码放到宏中,通过宏定义来完成一系列复杂操作。

        如对于一个可以控制某一值的滑动条而言,我们在编写的时候就需要完成以下这些操作:

        (1) 生成一个滑动条,一个描述文本,一个值文本。

        (2) 设定这些UI的布局方式。

        (3) 初始化UI的基本内容,如滑动条的滑块位置,取值范围等。

        (4) 绑定滑动后值改变的信号与槽,并在槽中修改值、值文本等内容。

        现在,所有的这些操作都封装在宏中,所以,我们只需要定义宏,而无需再去做以上这些重复操作了,如实例代码中的:

        DECLARE_SLIDER(rough)

        首先,我们需要定义一个基类,使得之后的面板从该类中继承,以定义一些基本的属性和操作:

class QVBoxLayout;
using namespace std;
class PropertyWidget : public QWidget
{
public:
    PropertyWidget();
protected:
    QVBoxLayout* vlayout;
    void SetLabel(QString label);
};
#include "propertywidget.h"
#include <QVBoxLayout>

PropertyWidget::PropertyWidget()
{
    vlayout = new QVBoxLayout;
    setLayout(vlayout);
}

void PropertyWidget::SetLabel(QString label)
{
    QLabel* l = new QLabel(label);
    vlayout->addWidget(l);
}

        之后,通过宏定义实现基本控件。由于基本控件数量比较多,目前我只实现了一部分控件,其余控件会随着我个人的需求完善后补充到文章中。

        此处数据绑定的设计可优化,目前需要提供数据的裸指针,但是有时候我们无法访问到裸指针,而只能访问到对应的set,get方法,可改为传入set,get两个函数完成值的访问和修改:

slider控件

#define DECLARE_SLIDER(name)\
protected:                                                                                            \
    QSlider* name##slider;                                                                            \
    QLabel* name##label;                                                                              \
    float name##min,name##max;                                                                        \
    float* name##data;                                                                                \
public:                                                                                               \
    void name##Init(string na,float mi,float ma,float* da = nullptr)                                  \
    {                                                                                                 \
        name##min = mi,name##max = ma,name##data = da;                                                \
        QHBoxLayout* hlayout = new QHBoxLayout();                                                     \
        QLabel* text = new QLabel(QString::fromStdString(na));                                        \
        name##slider = new QSlider();                                                                 \
                                                                                                      \
        name##slider->setOrientation(Qt::Horizontal);                                                 \
        if(da)                                                                                        \
            name##label = new QLabel(QString::number(static_cast<double>(*da)));                      \
        else                                                                                          \
            name##label = new QLabel();                                                               \
        hlayout->addWidget(text,1);                                                                   \
        hlayout->addWidget(name##slider,2);                                                           \
        hlayout->addWidget(name##label,1);                                                            \
        vlayout->addLayout(hlayout);                                                                  \
        name##slider->setMinimum(0);                                                                  \
        name##slider->setMaximum(100);                                                                \
        connect(name##slider,&QSlider::valueChanged,this,[&](int value) {                             \
            float t = static_cast<float>(value) / 100 *(name##max - name##min) + name##min;           \
            char buffer[100];                                                                         \
            sprintf(buffer,"%.2f",static_cast<double>(t));                                            \
            name##label->setText(QString(buffer));                                                    \
            if(name##data)*name##data = t;});                                                         \
    }                                                                                                 \
    void name##SetData(float* da)                                                                     \
    {                                                                                                 \
        name##data = da;                                                                              \
        if(da)  {                                                                                     \
            char buffer[100];                                                                         \
            sprintf(buffer,"%.2f",static_cast<double>(*da));                                          \
            name##label->setText(QString(buffer));                                                    \
            name##slider->setValue(static_cast<int>((*da - name##min)/(name##max - name##min)*100));  \
        }                                                                                             \
    }                                                                                                 \

checkbox控件

#define DECLARE_CHECKBOX(name)                                                                        \
protected:                                                                                            \
    QCheckBox* name##check;                                                                           \
    bool* name##data;                                                                                 \
public:                                                                                               \
    void name##Init(string na, bool* da = nullptr)                                                    \
    {                                                                                                 \
        name##check = new QCheckBox(QString::fromStdString(na));                                      \
        if(da) name##check->setChecked(*da);                                                          \
        vlayout->addWidget(name##check);                                                              \
        connect(name##check,&QCheckBox::stateChanged,this,[&](int value) {                            \
            *name##data = value != 0;                                                                 \
        });                                                                                           \
    }                                                                                                 \
    void name##SetData(bool* da)                                                                      \
    {                                                                                                 \
        name##data = da;                                                                              \
        if(da) {                                                                                      \
            name##check->setChecked(*da);                                                             \
        }                                                                                             \
    }

image控件

#define DECLARE_IMAGE(name)                                                                           \
protected:                                                                                            \
    QImage* name##image;                                                                              \
    QLabel* name##label;                                                                              \
    QPushButton* name##btn;                                                                           \
    QString name##path;                                                                               \
public:                                                                                               \
    void name##Init(string na, QImage* image = nullptr)                                               \
    {                                                                                                 \
        QLabel* label = new QLabel(QString::fromStdString(na));                                       \
        name##image = image;                                                                          \
        QHBoxLayout* hlayout = new QHBoxLayout();                                                     \
        name##label = new QLabel();                                                                   \
        name##btn = new QPushButton(".");                                                             \
        name##btn->setFixedSize(20,20);                                                               \
        hlayout->addWidget(label);                                                                    \
        hlayout->addWidget(name##label);                                                              \
        hlayout->addWidget(name##btn);                                                                \
        vlayout->addLayout(hlayout);                                                                  \
                                                                                                      \
        connect(name##btn,&QPushButton::clicked,this,[&]() {                                          \
            QString fileName = QFileDialog::getOpenFileName(this, tr("File"),                         \
                   "D:",tr("img(*png *jpg *tga);;"));                                                 \
            if(name##image && fileName!="")                                                           \
            {                                                                                         \
                name##image->load(fileName);                                                          \
                QPixmap pixmap = QPixmap::fromImage(*name##image);                                    \
                pixmap = pixmap.scaled(QSize(40,40));                                                 \
                name##label->setPixmap(pixmap);                                                       \
            }                                                                                         \
        });                                                                                           \
    }                                                                                                 \
    void name##SetData(QImage* image)                                                                 \
    {                                                                                                 \
        name##image = image;                                                                          \
        if(image) name##label->setPixmap(QPixmap::fromImage(*image));                                 \
    }                                                                                                 \

color控件

#define DECLARE_COLOR(name)                                                                           \
protected:                                                                                            \
    QPushButton* name##colorBtn;                                                                      \
    QLabel* name##label;                                                                              \
    Vector3f* name##data;                                                                             \
public:                                                                                               \
    void name##Init(string na, Vector3f* da = nullptr)                                                \
    {                                                                                                 \
        name##colorBtn = new QPushButton();                                                           \
        name##colorBtn->setFixedSize(40,20);                                                          \
        name##label = new QLabel(QString::fromStdString(na));                                         \
        QHBoxLayout* hlayout = new QHBoxLayout();                                                     \
        if(da)                                                                                        \
        {                                                                                             \
            char buffer[500];                                                                         \
            sprintf(buffer,"background: rgb(%d,%d,%d)",int(da->x*255),int(da->y*255),                 \
                int(da->z*255));                                                                      \
            name##colorBtn->setStyleSheet(buffer);                                                    \
        }                                                                                             \
        hlayout->addWidget(name##label);                                                              \
        hlayout->addWidget(name##colorBtn);                                                           \
        vlayout->addLayout(hlayout);                                                                  \
        connect(name##colorBtn,&QPushButton::clicked,this,[&]() {                                     \
            QColor color = QColorDialog::getColor(Qt::red, this,tr("Color"),                          \
                QColorDialog::ShowAlphaChannel);                                                      \
            if(name##data)*name##data = Vector3f(1.0f*color.red()/255,1.0f*color.green()/255,         \
                1.0f*color.blue()/255);                                                               \
            char buffer[500];                                                                         \
            sprintf(buffer,"background: rgb(%d,%d,%d)",color.red(),color.green(),color.blue());       \
            name##colorBtn->setStyleSheet(buffer);                                                    \
        });                                                                                           \
    }                                                                                                 \
    void name##SetData(Vector3f* da)                                                                  \
    {                                                                                                 \
        name##data = da;                                                                              \
        if(da)                                                                                        \
        {                                                                                             \
            char buffer[500];                                                                         \
            sprintf(buffer,"background: rgb(%d,%d,%d)",int(da->x*255),int(da->y*255),                 \
                int(da->z*255));                                                                      \
            name##colorBtn->setStyleSheet(buffer);                                                    \
        }                                                                                             \
    }                                                                                                 \

猜你喜欢

转载自blog.csdn.net/ZJU_fish1996/article/details/88770703