Qt双缓冲机制:实现一个简单的绘图工具(纯代码实现)

知识准备:

双缓冲机制:

在绘制控件时,首先将要绘制的内容绘制在一张图片中,再将图片一次性绘制到控件上。

在Qt的早期版本中,为了用户界面更加清爽,经常用这个技术来消除闪烁。

自Qt5版本后,QWidget能够自动处理闪烁,因此我们不用再担心这个问题。

双缓冲机制的使用场合:

  • 所需绘制的内容较复杂,并且需频繁刷新。
  • 每次只需刷新整个控件的一小部分。


笔的样式:Qt::PenStyle

图形表述:

文字描述:


实例:

实现一个简单的绘图工具,可以实现选择“线型”、“线宽”、“颜色”等基本功能,还有一个“清除”按钮。
效果图如下:



实现步骤:

1、新建Qt GUI应用。
项目名称为“DrawWidget”,基类选择“QMainWindow”,类名默认即可,取消“创建界面”复选框,完成项目工程的建立。
2、为工程添加提供实现绘图区的函数所在的文件。
在项目名上右击,选择“添加新文件 ...”,基类选择“QWidget”,类名为“DrawWidget”。



3、编辑“drawwidget.h”文件
添加如下代码:(主要定义需要用到的函数和变量)

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H

#include <QWidget>
#include <QtGui>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QColor>
#include <QPixmap>
#include <QPoint>
#include <QPainter>
#include <QPalette>
class DrawWidget : public QWidget
{
    Q_OBJECT

public:
    explicit DrawWidget(QWidget *parent = 0);
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
    void resizeEvent(QResizeEvent *);

signals:

public slots:
    void setStyle(int );
    void setWidth(int );
    void setColor(QColor );
    void clear();

private:
    QPixmap *pix;
    QPoint startPos;    //记录鼠标的当前位置
    QPoint endPos;
    int style;
    int weight;
    QColor color;
};

#endif // DRAWWIDGET_H


4、编辑“drawwidget.cpp”文件
在构造函数中完成窗体参数及部分功能初始化工作。

代码如下:

#include "drawwidget.h"

DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{
    setAutoFillBackground(true);    //允许调整控件背景颜色

    setPalette(QPalette(Qt::white));
    pix = new QPixmap(size());
    pix->fill(Qt::white);
    setMinimumSize(600,400);    //设置窗体最小大小
}

void DrawWidget::setStyle(int s)
{
    style = s;
}

void DrawWidget::setWidth(int w)
{
    weight = w;
}

void DrawWidget::setColor(QColor c)
{
    color = c;
}

void DrawWidget::mousePressEvent(QMouseEvent *e)
{
    startPos = e->pos();
}

void DrawWidget::mouseMoveEvent(QMouseEvent *e)
{
    QPainter *painter = new QPainter;

    QPen pen;
    pen.setStyle((Qt::PenStyle)style);
    pen.setWidth(weight);
    pen.setColor(color);

    painter->begin(pix);
    painter->setPen(pen);
    painter->drawLine(startPos, e->pos());
    painter->end();
    startPos = e->pos();

    update();
}

void DrawWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(QPoint(0,0), *pix);
}

void DrawWidget::resizeEvent(QResizeEvent *event)
{
    if(height() > pix->height() || width() > pix->width())
    {
        QPixmap *newPix = new QPixmap(size());
        newPix->fill(Qt::white);
        QPainter p(newPix);
        p.drawPixmap(QPoint(0,0), *pix);
        pix = newPix;
    }
    QWidget::resizeEvent(event);
}

void DrawWidget::clear()
{
    QPixmap *clearPix = new QPixmap(size());
    clearPix->fill(Qt::white);
    pix = clearPix;

    update();
}

5、编辑“mainwindow.h”文件

此文件主要用于申明创建工具栏的函数createToolBar( )和选择线型样式线型颜色的餐函数showStyle( )、showColor( ) 。以及定义需要用到的变量。

代码如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QToolButton>
#include "drawwidget.h"


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void createToolBar();

public slots:
    void showStyle();
    void showColor();

private:
    DrawWidget *drawWidget;
    QLabel *styleLabel;
    QComboBox *styleComboBox;
    QLabel *widthLabel;
    QSpinBox *widthSpinBox;
    QToolButton *colorBtn;
    QToolButton *clearBtn;
};

#endif // MAINWINDOW_H

6、编辑“mainwindow.cpp”文件

添加如下代码:

#include "mainwindow.h"
#include <QColorDialog>
#include <QToolBar>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    drawWidget = new DrawWidget;
    setCentralWidget(drawWidget);

    createToolBar();

    setMinimumSize(600, 400);

    showStyle();
    drawWidget->setWidth(widthSpinBox->value());
    drawWidget->setColor(Qt::black);
}

MainWindow::~MainWindow()
{

}

void MainWindow::createToolBar()
{
    QToolBar *toolBar = addToolBar("Tool");

    styleLabel = new QLabel(tr("线型风格: "));  //线型风格
    styleComboBox = new QComboBox;
    styleComboBox->addItem(tr("SolodLine") , static_cast<int>(Qt::SolidLine));
    styleComboBox->addItem(tr("DashLine") , static_cast<int>(Qt::DashLine));
    styleComboBox->addItem(tr("DotLine") , static_cast<int>(Qt::DotLine));
    styleComboBox->addItem(tr("DashDotLine") , static_cast<int>(Qt::DashDotLine));
    styleComboBox->addItem(tr("DashDotDotLine") , static_cast<int>(Qt::DashDotDotLine));
    connect(styleComboBox,SIGNAL(activated(int)),this,SLOT(showStyle()));

    widthLabel = new QLabel(tr("线宽:")); //设置笔的线宽
    widthSpinBox = new QSpinBox;
    connect(widthSpinBox,SIGNAL(valueChanged(int)),drawWidget,SLOT(setWidth(int)));

    colorBtn = new QToolButton; //设置按钮的格式
    QPixmap pixmap(30,30);
    pixmap.fill(Qt::red);
    colorBtn->setIcon(QIcon(pixmap));
    connect(colorBtn,SIGNAL(clicked(bool)),this,SLOT(showColor()));

    clearBtn = new QToolButton;
    clearBtn->setText(tr("清除"));
    connect(clearBtn,SIGNAL(clicked(bool)),drawWidget,SLOT(clear()));

    toolBar->addWidget(styleLabel);
    toolBar->addWidget(styleComboBox);
    toolBar->addWidget(widthLabel);
    toolBar->addWidget(widthSpinBox);
    toolBar->addWidget(colorBtn);
    toolBar->addWidget(clearBtn);
    toolBar->setMovable(false); //设置工具条不可拖动
}

void MainWindow::showStyle()
{
    drawWidget->setStyle(styleComboBox->itemData(styleComboBox->currentIndex(),Qt::UserRole).toInt());
}

void MainWindow::showColor()
{
    QColor color = QColorDialog::getColor(static_cast<int>(Qt::black) ,this);
    if(color.isValid())
    {
        drawWidget->setColor(color);
        QPixmap p(20,20);
        p.fill(color);
        colorBtn->setIcon(QIcon(p));
    }
}

7、编辑“main.cpp”文件

设置一下程序界面中出现的文字的字体和颜色

代码如下:

#include "mainwindow.h"
#include "drawwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QFont font("楷体", 15);
    a.setFont(font);

    MainWindow w;
    w.show();

    return a.exec();
}


至此,整个程序的编码工作便完成了。

注:

程序有一点小瑕疵,当鼠标的移动速度较慢时,线型就体现不出来,不管是DashLine还是DotLine,都显示为实线,我也请在讨论群里请教了一些朋友,结果越讨论越复杂,没有一个较好切简单的解决办法。
如果哪位看客有好的方法,可以留言哦。人多力量大嘛。O(∩_∩)O哈哈~


使用博客目录阅读博客,会让思路结构更加清晰哦。(仅支持电脑端)


  • 13
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
本课程详细、全面地介绍了 Qt 开发中的各个技术细节,并且额外赠送在嵌入式端编写Qt程序的技巧。整个课程涵盖知识点非常多,知识模块囊括 Qt-Core 组件、QWidgets、多媒体、网络、绘图、数据库,超过200个 C++ 类的分析和使用,学完之后将拥有 Qt 图形界面开发的非常坚实的功底。 每个知识点不仅仅会通过视频讲解清楚,并且会配以精心安排的实验和作业,用来保证学习过程中切实掌握核心技术和概念,通过实验来巩固,通过实验来检验,实验与作业的目的是发现问题,发现技术盲点,通过答疑和沟通夯实技术技能。注意:本套视频教程来源于线下的实体班级,因此视频中有少量场景对话和学生问答,对此比较介意的亲们谨慎购买。注意:本套视频教程包含大量课堂源码,包含对应每个知识点的精心编排的作业。由于CSDN官方规定在课程介绍中不能出现作者的联系方式,因此在这里无法直接给出QQ答疑号,视频中的源码、资料和作业文档链接统一在购买后从CSDN平台跟我沟通,我会及时回复跟进。注意:本套视频教程包含全套10套作业题,覆盖所有视频知识点,循序渐进,各个击破,作业总纲如下:下面是部分作业题目展示,每道题都有知识点说明,是检验学习效果的一大利器:(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)…… ……

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值