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

知识准备:

双缓冲机制:

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

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

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

双缓冲机制的使用场合:

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


笔的样式:Qt::PenStyle

图形表述:
Qt双缓冲机制:实现一个简单的绘图工具(纯代码实现)_第1张图片
文字描述:
Qt双缓冲机制:实现一个简单的绘图工具(纯代码实现)_第2张图片

实例:

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



实现步骤:

1、新建Qt GUI应用。

项目名称为“DrawWidget”,基类选择“QMainWindow”,类名默认即可,取消“创建界面”复选框,完成项目工程的建立。

2、为工程添加提供实现绘图区的函数所在的文件。

在项目名上右击,选择“添加新文件 ...”,基类选择“QWidget”,类名为“DrawWidget”。

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


3、编辑“drawwidget.h”文件

添加如下代码:(主要定义需要用到的函数和变量)

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#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 
#include 
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(Qt::SolidLine));
    styleComboBox->addItem(tr("DashLine") , static_cast(Qt::DashLine));
    styleComboBox->addItem(tr("DotLine") , static_cast(Qt::DotLine));
    styleComboBox->addItem(tr("DashDotLine") , static_cast(Qt::DashDotLine));
    styleComboBox->addItem(tr("DashDotDotLine") , static_cast(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(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 

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哈哈~


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

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

你可能感兴趣的:(Qt编程)