一、什么是自定义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); }