使用Qt自带的标准控件常见的界面搭建已经够用了,但是如果涉及到个性化很强或者比较特殊的控件标准控件就不够用了,这时候我们就需要自绘控件了。自绘控件简单理解就是,QT给你提供一个画板和绘画工具,你根据自己的需要绘制出各种各样的界面。通过自绘,我们可以实现各种各样的稀奇古怪的控件了。
下面介绍一下QT中自绘控件的实现方法。首先声明一个继承自QWidget的类,然后重写该类的绘画事件:
#include
#include
class CustomWidget: public QWidget
{
Q_OBJECT
public:
explicit CustomWidget(QWidget *parent = nullptr);
protected:
//控件的绘画事件
void paintEvent(QPaintEvent *event) override;
};
在绘画事件中,我们就可以根据自己的想象绘制各种各样的UI图形了。下面介绍一下绘制各种元素的方法。
void CustomWidget::paintEvent(QPaintEvent *event)
{
//控件的绘制工具,通过该工具我们可以进行常用的绘制了
QPainter paint(this);
//绘制文本,绘制红色的文字
painter.setPen(QPen(QColor(255,0,0)));
//添加绘制的字体和字号
painter.setFont(QFont("Microsoft YaHei",45));
painter.drawText(this->rect(),"测试显示");
}
void CustomWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//绘制矩形
QPen pen;
//矩形边框为蓝色,宽度为5
pen.setColor(QColor(0,0,255));
pen.setWidth(5);
painter.setPen(pen);
painter.drawRect(QRect(10,10,100,100));
//矩形内部填充颜色为#DDCCCC的内容
painter.fillRect(QRect(15,15,90,90),QColor("#DDCCCC"));
}
void CustomWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//开启抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
//绘制点、 线、圆弧
QPen pen;
//矩形边框为蓝色,宽度为5
pen.setColor(QColor(0,0,255));
pen.setWidth(10);
painter.setPen(pen);
//在(30,30)位置绘制一个点
painter.drawPoint(30,30);
//绘制(30,50)到(30,100)的一条线
painter.drawLine(QPoint(30,50),QPoint(30,100));
//绘制圆弧通过给定的矩形和起始和终止角度来确定的
//起始角度和终止角度代表着一度的1/16,360度对应的值是5760(16*360)
//其实就是通过矩形的内接椭圆和起始角度来确定圆弧
QRectF rectangle(50.0, 80.0, 60.0, 60.0);
int startAngle = 30 * 16; //起始角度30度
int spanAngle = 120 * 16; //终止角度120度
//正值代表着逆时针方向,负值代表着顺时针方向,0度在三点钟方向
painter.drawArc(rectangle,startAngle,spanAngle);
}
void CustomWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//开启抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
QPen pen;
//矩形边框为蓝色,宽度为5
pen.setColor(QColor(0,0,255));
pen.setWidth(5);
painter.setPen(pen);
//根据四个定点绘制一个多边形
const QPointF points[4] = {
QPointF(10.0, 80.0),
QPointF(20.0, 10.0),
QPointF(80.0, 30.0),
QPointF(90.0, 70.0),
};
painter.drawPolygon(points, 4);
//根据矩形内接椭圆和其实角度画饼状图
QRectF rectangle(100.0, 20.0, 80.0, 60.0);
int startAngle = 30 * 16;
int spanAngle = 120 * 16;
painter.setBrush(QBrush(QColor(0,0,255)));
painter.drawPie(rectangle, startAngle, spanAngle);
//绘制矩形的内接椭圆
QRectF ellipse_rectangle(200.0, 20.0, 80.0, 60.0);
painter.drawEllipse(ellipse_rectangle);
//绘制对应的弦
QRectF chrod_rectangle(300.0, 20.0, 80.0, 60.0);
painter.drawChord(chrod_rectangle,startAngle,spanAngle);
//绘制x方向和y方向圆角都为5的圆角矩形
QRectF round_rectangle(400.0, 20.0, 80.0, 60.0);
painter.drawRoundedRect(round_rectangle,5,5);
}
void CustomWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//开启抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
QPen pen;
//矩形边框为蓝色,宽度为5
pen.setColor(QColor(0,0,255));
pen.setWidth(5);
painter.setPen(pen);
//绘制外部的图片到矩形(x=30,y=30,width=100,height=100)中
painter.drawImage(QRect(30,30,100,100),QImage(":/ceshi.jpg"));
//绘制连续的路径
QPainterPath path;
//移动到起始位置然后画线
path.moveTo(130, 80);
path.lineTo(180, 80);
//通过插值实现圆弧曲线
path.cubicTo(200, 120, 130, 150, 180, 180);
painter.drawPath(path);
//也可以通过Path同时绘制多个图形
QPainterPath multiPath;
pen.setWidth(2);
painter.setPen(pen);
multiPath.moveTo(200,80);
multiPath.addText(200,80,QFont("Microsoft YaHei",25),"测试");
multiPath.addEllipse(QRect(250,80,100,100));
multiPath.addRect(QRect(350,80,100,100));
painter.drawPath(multiPath);
}
掌握了基本的元素的绘制方法,通过组合修改就可以绘制出各种各样的花里胡哨的自绘控件了。
依据上面的绘制方法我们简单的实现一个个性化钟表
代码如下:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void paintEvent(QPaintEvent* event);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widght.cpp
#include "widget.h"
#include "ui_widget.h"
#include
#include
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint|Qt::WindowMinimizeButtonHint|
Qt::WindowMaximizeButtonHint|Qt::Tool|Qt::WindowStaysOnTopHint);
this->setAttribute(Qt::WA_TranslucentBackground,true);
this->setFixedSize(300,300);
QTimer* timer = new QTimer(this);
timer->start(1000);
connect(timer,&QTimer::timeout,this,[&](){this->update();});
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QString date_Str = QDateTime::currentDateTime().toString("hh:mm:ss");
int hour = QTime::currentTime().hour();
int min = QTime::currentTime().minute();
int second = QTime::currentTime().second();
//绘制时间文字
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QPen pen(QColor(0,0,0));
painter.setPen(pen);
painter.setFont(QFont("Microsoft YaHei",20));
painter.drawText(QRect(55,0,140,30),date_Str);
//绘制秒钟的大圈
pen.setWidth(10);
pen.setColor(QColor("#4D9CF8"));
painter.setPen(pen);
QRectF sec_rectangle(25.0, 50.0, 200.0, 200.0);
int sec_startAngle = 90 * 16;
int sec_spanAngle = -1*(((double)second / 60.0)*360)*16;
painter.drawArc(sec_rectangle,sec_startAngle,sec_spanAngle);
//绘制分钟的小圈
QRectF min_rectangle(50.0, 75.0, 150.0, 150.0);
int min_startAngle = 90 * 16;
int min_spanAngle = -1*(((double)min / 60.0)*360)*16;
painter.drawArc(min_rectangle,min_startAngle,min_spanAngle);
//绘制小时的圈
QRectF hour_rectangle(75.0, 100.0, 100.0, 100.0);
int hour_startAngle = 90 * 16;
if(hour>12){hour -= 12;}
int hour_spanAngle = -1*(((double)hour / 12.0)*360)*16;
painter.drawArc(hour_rectangle,hour_startAngle,hour_spanAngle);
}
运行效果如下图所示: