绘图事件

绘图事件重写的情景

  • 当你需要创建一个自定义控件,并且这个控件需要显示特殊的图形、颜色或形状时,重写 paintEvent 是必要的。例如,如果你需要绘制一个自定义的进度条、按钮、图表等
  • 当你需要在窗口中绘制复杂的图形,或者在应用程序中实现动画时,paintEvent 可以用来每次刷新窗口内容

示例

  • 首先需要在窗口的头文件声明这方法,表示要重写
  • 然后书写具体规则
void MainWindow::paintEvent(QPaintEvent *) {
    // 实例化画家对象 this 指定的是绘图设备
    QPainter painter(this);
    // 设置画笔
    QPen pen(QColor(255,0,0));
    // 设置画笔宽度
    pen.setWidth(3);
    // 设置画笔风格
    pen.setStyle(Qt::DotLine);
    // 让画家 使用这个笔
    painter.setPen(pen);

    // 设置画刷,寄填充颜色
    QBrush brush(Qt::cyan);
    // 设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);
    // 让画家使用画刷
    painter.setBrush(brush);
  
    // 画线
    painter.drawLine(QPoint(0,0), QPoint(100,100));
    // 画圆 椭圆
    painter.drawEllipse( QPoint(100,100), 50,50);
    // 画矩形
    painter.drawRect(QRect(20,20,50,50));
    // 画文字,这个使用画刷不会填充,且这个矩形没有线框,默认
    painter.drawText(QRect(10,200,150,50), "好好学习,天天向上");
}

高级设置

void MainWindow::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    painter.drawEllipse(QPoint(100,50),50,50);
    //设置 抗锯齿能力 效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50),50,50);
    
    painter.drawRect(QRect(20,20,50,50));
    // 让画家移动到 (100, 0) 位置再画,此时以画家为基准,在 (20, 20) 位置画
    painter.translate(100,0);
    // 保存画家状态
    painter.save();
    painter.drawRect(QRect(20,20,50,50));
    translate(150, 0);
    // 恢复画家之前保存的状态
    painter.restore();
}

利用画家画资源图片,并且实现点击按钮就移动图片

// 首先在 mainwindow 头文件定义一个变量 posX,作为移动的指标
// 然后在 mainwindow.ui 中放一个按钮,取名为 btn
void MainWindow::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    // 超出屏幕范围,就从 0 开始
    if(posX > this->width()) {
        posX = 0;
    }
    painter.drawPixmap(posX, 0, QPixmap(":/111.png"));
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    connect(ui->btn, &QPushButton::clicked, this, [=]() {  
        posX += 20;
        // 如果要手动调用绘图事件 用 update 更新
        update();
    });
}

绘图设备

绘图设备简单来说就是绘图所在地,也就是画的东西画在上面

  • QPixmap 专门为图像在屏幕上的显示做了优化
  • QBitmapQPixmap 的一个子类,只有黑白两种颜色
  • QImage 专门为图像的像素级访问做了优化,也就是可以修改图片中的像素
  • QPicture 是用来记录和重现 QPainter 的各条命令
  • 上面的案例中在窗口画画,是因为串口是绘图设备,MainWindow 继承 QWidget, QWidget 继承 QObjectQPaintDevice,能够在窗口上画画

QPixmap

// QPixmap
// 定义绘图设备的大小
QPixmap pix(300,300);
// 填充颜色(默认为黑色)
pix.fill(Qt::white);

// 声明画家
QPainter painter(&pix);
painter.setPen(QPen(Qt::green));   // QPen 是画笔
// 画椭圆(圆)
painter.drawEllipse(QPoint(150,150), 100,100);  // 圆心,两个半径,一样就是圆

// 保存,保存在 E 盘,名字叫 pix.png
// 程序运行后,在 E 盘就能看到这个图片
pix.save("E:\\pix.png");

QImage

// QImage 绘图设备,后面参数是格式,查阅文档填写
QImage img(300,300, QImage::Format_RGB32);
img.fill(Qt::white);

QPainter painter(&img);
painter.setPen(QPen(Qt::blue));
painter.drawEllipse(QPoint(150,150),100,100);

//保存
img.save("E:\\img.png");

对像素修改例子

// 重写 painEvent 事件,需要现在 mainwindow 头文件定义
void MainWindow::paintEvent(QPaintEvent *) {
    QPainter painter(this);  // 这里 this 是指在这个窗口绘图、
    
    // 利用&Image对像素进行修改
    QImage img;
    img.load(":/111.png");

    // 修改像素点,会看到左上角部分有红色的矩形,这就是修改的
    for(int i = 50; i < 100; i++) {
        for(int j = 50; j < 100; j++) {
            QRgb value = qRgb(255,0,0);
            img.setPixel(i, j, value);
        }
    }
    // 在 (0, 0) 处绘图
    painter.drawImage(0, 0, img);
}

QPicture

QPicture pic;
QPainter painter;

// 开始往 pic 上画
painter.begin(&pic);  
painter.setPen(QPen(Qt::cyan));
painter.drawEllipse(QPoint(150,150),100,100);
// 结束画画
painter.end();  

//保存到磁盘
pic.save("E:\\pic.txt");

// 重现
QPainter painter1(this);
// 重现 QPicture 的绘图指令
QPicture pic1;
pic1.load("E:\\pic.txt");
painter.drawPicture(0, 0, pic);

说明:参考 https://space.bilibili.com/396491181

只管努力,剩下的交给天意