admin管理员组

文章数量:1666583

一、什么是自定义Widget组件

  • Qt的UI设计器提供了很多GUI设计的界面组件,可以满足常见的界面设计需求。但是某些时候需要设计特殊的界面组件,而在UI设计器的组件面板里没有合适的组件,这时就需要设计自定义的界面组件

二、如何设计自定义的Widget组件

  • 所有组件的基类是QWidget,要设置自定义的界面组件,可以从QWidget继承一个自定义的类,重定义其paintEvent()事件,利用Qt的绘图功能绘制组件外观,并实现需要的其它功能
  • 然后在窗体中放置一个Widget,右击Widget组件,“Protomed to”提升为我们上面定义的那个类(看后面的演示案例)

三、演示案例

  • 设计一个这样的电池组件

第一步:

  • 先创建一个基于QWidget的应用窗体

第二步:

  • 然后再添加一个从QWidget继承的类QmyBattery
  • 在此项目的基础上,点击Qt Creator的“File” ==>"New File or Project" ==>“C++ Class” ==>创建一个基于QWdiget的“qmybattery”类

第三步:

  • 向qmybattery.h文件中书写代码,内容如下
#include <QWidget>
#include <QColor>
#include <QPainter>

class qmybattery : public QWidget
{
    Q_OBJECT
private:
    QColor mColorBack=Qt::white;  //背景色
    QColor mColorBorder=Qt::black;//电池边框颜色
    QColor mColorPower=Qt::green; //电量柱颜色
    QColor mColorWarning=Qt::red; //电量短缺时的颜色
    int mPowerLevel=60;           //当前电量(0-100)
    int mWarnLevel=20;            //电量低警示阀值
protected:
    void paintEvent(QPaintEvent *event)Q_DECL_OVERRIDE; //绘图
public:
    explicit qmybattery(QWidget *parent = nullptr);
    void setPowerLevel(int pow); //设置当前电量
    int powerLevel(); //得到当前电量
    void setWarnLevel(int warn); //设置电量低阀值
    int warnLevel(); //得到电量低阀值
    QSize sizeHint(); //返回组件的缺省大小
signals:
    //当电量值改变时发射此信号
    void powerLevelChanged(int);
public slots:
};

第四步:

  • 定义paintEvent()函数
void qmybattery::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    
    //设置QPainter的绘图区
    QRect rect(0,0,width(),height());
    painter.setViewport(rect);
    painter.setWindow(0,0,120,50);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::TextAntialiasing);
    
    //设置画笔
    QPen pen;
    pen.setWidth(2);
    pen.setColor(mColorBorder);
    pen.setStyle(Qt::SolidLine);
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::BevelJoin);
    //设置画刷
    QBrush brush;
    brush.setColor(mColorBack);
    brush.setStyle(Qt::SolidPattern);
    
    painter.setPen(pen);
    painter.setBrush(brush);
    
    //改变rect的区域,绘制电池边框
    rect.setRect(1,1,109,48);
    painter.drawRect(rect);
    
    //改变画刷颜色,改变rect的区域,绘制电池的正极头
    brush.setColor(mColorBorder);
    painter.setBrush(brush);
    rect.setRect(110,15,10,20);
    painter.drawRect(rect);
    
    //画电池柱
    if(mPowerLevel>mWarnLevel) //正常颜色电量柱
    {
        brush.setColor(mColorPower);
        pen.setColor(mColorPower);
    }
    else//电量低时电量柱
    {
        brush.setColor(mColorWarning);
        pen.setColor(mColorWarning);
    }
    painter.setBrush(brush);
    painter.setPen(pen);
    if(mPowerLevel>0)//如果当前有电量,绘制电量柱
    {
        rect.setRect(5,5,mPowerLevel,40);
        painter.drawRect(rect);
    }
    
    //绘制电量百分比文字
    QFontMetrics textSize(this->font());
    QString powerStr=QString::asprintf("%d%%",mPowerLevel);
    QRect textRect=textSize.boundingRect(powerStr); //得到字符串的rect
    painter.setFont(this->font());
    pen.setColor(mColorBorder);
    painter.setPen(pen);
    painter.drawText(55-textRect.width()/2,23+textRect.height()/2,powerStr);;
    
}

第五步:

  • 定义其他成员函数
//设置当前电量
void qmybattery::setPowerLevel(int pow)
{
    mPowerLevel=pow;
    emit powerLevelChanged(pow);
    repaint();
}

//得到当前电量
int qmybattery::powerLevel()
{
    return mPowerLevel;
}
//设置电量低阀值
void qmybattery::setWarnLevel(int warn)
{
    mWarnLevel=warn;
    repaint();
}

//得到电量低阀值
int qmybattery::warnLevel()
{
    return mWarnLevel;
}
返回组件尺寸大小
QSize qmybattery::sizeHint()
{
    int H=this->height();
    int W=H*12/5;
    QSize size(W,H);
    return size;
}

第六步:

使用“提升法”,将我们自定义的类对象提升为UI组件

  • ①在UI界面中,移动一个Widget组件到主窗体中,然后右击组件,点击“Promote to”菜单项

  • ②点击之后,出现下面的UI画框

  • ③我们将“Base class name”改为“QWidget”。将Promoted class name改为“qmybattery”。勾选一些选项,然后点击Promote(如果我们有其他的自定义类也可以添加到Promoted Classes中,以便我们选择使用)

  • ④可以看到这个组件的类名称变为了qmybattery

  • ⑤右击这个组件,将其object name改为“battery”

第七步:

  • 在主窗体中再放置一个Horizontal Slider组件和一个QLabel组件,然后与battery这个组件进行排版

第八步:

  • 我们书写Horizontal Slider组件的valueChanged信号,然后调用setPowerLevel函数,这样的话,我们的qmybattery类就会接收到powerLevelChanged信号了

void Widget::on_horizontalSlider_valueChanged(int value)
{
    ui-> battery->setPowerLevel(value);
    QString str=QStringLiteral("当前电量:")+QString::asprintf("%d %%",value);
    ui->label->setText(str);
}

 

本文标签: 自定义组件QTpromotedWidget