文章目录
- QPainter绘制时【数据类型】和【抗锯齿】对绘制效果的影响【2】
- 1、概述
- 2、关键代码
- 3、源代码
1、概述
- Qt版本:V5.12.5
- 本文内容
- 使用【浮点数】进行绘制,绘制的圆会更加均匀;
- 使用【整形】进行绘制,比浮点数计算快,适用于频繁、大量的重绘,但绘制效果较差;
- 开启【抗锯齿】后线条会更加平滑;
- 将布局改为使用设计器布局,减少使用代码布局,使关注点更多在绘制图形上;
- 将使用定时器更新绘制改为使用滑动条更新,增加可控性,便于观察绘制细节。
- 整体效果
2、关键代码
- circlewidget.h
#ifndef CIRCLEWIDGET_H
#define CIRCLEWIDGET_H
#include <QObject>
#include <QWidget>
class CircleWidget : public QWidget
{
Q_OBJECT
public:
explicit CircleWidget(QWidget *parent = nullptr);
void setFloatBased(bool flag); // 设置是否使用浮点型数据类型来保存绘制图案的数据
void setAntialiased(bool flag); // 是否使用抗锯齿渲染
void setFrame(int value);
signals:
public slots:
protected:
void paintEvent(QPaintEvent *event) override;
private:
bool floatBased = false; // 是否使用浮点类型数绘制
bool antialiased = false; // 是否开启抗锯齿
int frameNo = 0;
};
#endif // CIRCLEWIDGET_H
- circlewidget.cpp
#include "circlewidget.h"
#include <qdebug.h>
#include <qpainter.h>
CircleWidget::CircleWidget(QWidget *parent) : QWidget(parent)
{
}
/**
* @brief 设置是否使用浮点型数据类型来保存绘制图案的数据
* @param flag true:使用 false:不使用
*/
void CircleWidget::setFloatBased(bool flag)
{
this->floatBased = flag;
this->update();
}
/**
* @brief 是否使用抗锯齿渲染
* @param flag true:使用 false:不使用
*/
void CircleWidget::setAntialiased(bool flag)
{
this->antialiased = flag;
this->update();
}
/**
* @brief 设置绘制的参数
* @param value
*/
void CircleWidget::setFrame(int value)
{
this->frameNo = value;
this->update();
}
void CircleWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, antialiased); // 设置抗锯齿(开启后线条会更加平滑)
painter.drawRect(QRect(0, 0, this->width() - 1, this->height() - 1)); // 画一个边框
painter.translate(this->rect().center()); // 将坐标轴原点移动到中心位置
for(int diameter = 0; diameter < 256; diameter += 9) // 由于QColor透明度通道最大值为255,这里为了方便也设置最大255
{
int delta = (diameter / 2) - frameNo;
int alpha = 255 - (delta * delta) / 4 - diameter; // 计算透明度
if(alpha <= 0) continue; // 如果颜色透明度不为正值则不进行绘制
painter.setPen(QPen(QColor(0, 127, 127, alpha), 3)); // 设置画笔,颜色透明度渐变
if(floatBased)
{
painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0, diameter, diameter)); // 使用浮点数进行绘制,绘制的圆会更加均匀
}
else
{
painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter)); // 使用整形进行绘制,比浮点数计算快,适用于频繁、大量的重绘,但绘制效果较差
}
}
}
- widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("QPainter绘制时【数据类型】和【抗锯齿】对效果的影响");
ui->widget_2->setAntialiased(true); // 开启抗锯齿
ui->widget_4->setAntialiased(true);
ui->widget_3->setFloatBased(true); // 使用浮点数据类型进行绘制
ui->widget_4->setFloatBased(true);
}
Widget::~Widget()
{
delete ui;
}
/**
* @brief 因为Qt的Demo使用定时器更新参数会一直刷新,不便于观察细节,这里改为通过滑动条设置绘制的参数
* @param value
*/
void Widget::on_horizontalSlider_valueChanged(int value)
{
ui->widget->setFrame(value);
ui->widget_2->setFrame(value);
ui->widget_3->setFrame(value);
ui->widget_4->setFrame(value);
}