Qt——基础图形绘制(下)

1.综合实例开发:简易绘图程序,需求:

  • 自由图形绘制
  • 基本图形绘制(直线、矩形、椭圆)
  • 能够选择图形绘制颜色

2.自由绘图解决方案:

  • 以鼠标按下为开始,记录开始坐标 mousePressEvent
  • 记录鼠标移动时经过的像素坐标 mouseReleaseEvent
  • 以鼠标释放为结束,记录结束坐标 mouseMoveEvent
  • 按照记录顺序在两个坐标之间绘制直线 paintEvent

Widget.h

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QRadioButton>
#include <QComboBox>
#include <QGroupBox>
#include <QList>
#include <QPoint>

class Widget : public QWidget
{
    Q_OBJECT

    enum DrawType
    {
        NONE,
        FREE,
        LINE,
        RECT,
        ELLIPSE
    };
    struct DrawParam
    {
        DrawType type;
        Qt::GlobalColor color;
        QList<QPoint> points;
    };

    QGroupBox m_group;
    QRadioButton m_freeBtn;
    QRadioButton m_lineBtn;
    QRadioButton m_rectBtn;
    QRadioButton m_ellipseBtn;
    QComboBox m_colorBox;

    QList<DrawParam> m_drawList; //已经绘制结束的图形参数
    DrawParam m_current; //当前正在绘制的图形

    DrawType drawType();
    Qt::GlobalColor drawColor();
    void draw(QPainter& painter, DrawParam& param);
    void append(QPoint p);

protected:
    void mousePressEvent(QMouseEvent* evt);
    void mouseMoveEvent(QMouseEvent* evt);
    void mouseReleaseEvent(QMouseEvent* evt);
    void paintEvent(QPaintEvent* );
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget() override;
};
#endif // WIDGET_H

Widget.cpp

复制代码
#include "Widget.h"
#include <QMouseEvent>
#include <QBrush>
#include <QPen>
#include <QPainter>
#include <math.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_group.setParent(this);
    m_group.setTitle("Setting");
    m_group.resize(600, 65);
    m_group.move(20, 20);

    m_freeBtn.setParent(&m_group);
    m_freeBtn.setText("Free");
    m_freeBtn.resize(70, 30);
    m_freeBtn.move(35, 20);
    m_freeBtn.setChecked(true);

    m_lineBtn.setParent(&m_group);
    m_lineBtn.setText("Line");
    m_lineBtn.resize(70, 30);
    m_lineBtn.move(140, 20);

    m_rectBtn.setParent(&m_group);
    m_rectBtn.setText("Rect");
    m_rectBtn.resize(70, 30);
    m_rectBtn.move(245, 20);

    m_ellipseBtn.setParent(&m_group);
    m_ellipseBtn.setText("Ellipse");
    m_ellipseBtn.resize(70, 30);
    m_ellipseBtn.move(350, 20);

    m_colorBox.setParent(&m_group);
    m_colorBox.resize(80, 25);
    m_colorBox.move(480, 23);
    m_colorBox.addItem("Black");
    m_colorBox.addItem("Blue");
    m_colorBox.addItem("Green");
    m_colorBox.addItem("Red");
    m_colorBox.addItem("Yellow");

    setFixedSize(width(), 600); //是 Qt 中用于固定窗口或控件大小

    //初始化
    m_current.type = NONE;
    m_current.color = Qt::white;
    m_current.points.clear();
}
Widget::DrawType Widget::drawType()
{
    DrawType ret = NONE;
    if( m_freeBtn.isChecked() )
        ret = FREE;
    if( m_lineBtn.isChecked() )
        ret = LINE;
    if( m_rectBtn.isChecked() )
        ret = RECT;
    if( m_ellipseBtn.isChecked() )
        ret = ELLIPSE;

    return ret;
}
Qt::GlobalColor Widget::drawColor()
{
    Qt::GlobalColor ret = Qt::black;

    if( m_colorBox.currentText() == "Black" )
        ret = Qt::black;
    if( m_colorBox.currentText() == "Blue" )
        ret = Qt::blue;
    if( m_colorBox.currentText() == "Green" )
        ret = Qt::green;
    if( m_colorBox.currentText() == "Red" )
        ret = Qt::red;
    if( m_colorBox.currentText() == "Yellow" )
        ret = Qt::yellow;
    return ret;
}

void Widget::mousePressEvent(QMouseEvent* evt)
{
    m_current.type = drawType();
    m_current.color = drawColor();
    m_current.points.append(evt->pos()); //将当前鼠标位置记录到数组中

}
void Widget::mouseMoveEvent(QMouseEvent* evt)
{
    append(evt->pos());

    update();
}
void Widget::mouseReleaseEvent(QMouseEvent* evt)
{
    append(evt->pos());
    m_drawList.append(m_current);
    m_current.type = NONE;
    m_current.color = Qt::white;
    m_current.points.clear();

    update();
}
void Widget::append(QPoint p)
{
    if( m_current.type != NONE )
    {
        if( m_current.type == FREE )
        {
            m_current.points.append(p);
        }
        else
        {
            if( m_current.points.count() ==2 )
            {
                m_current.points.removeLast();
            }
            m_current.points.append(p);
        }
    }
}
void Widget::paintEvent(QPaintEvent* )
{
    QPainter painter(this);
    for(int i=0; i<m_drawList.count(); i++)
    {
        draw(painter, m_drawList[i]);
    }
    draw(painter, m_current);
}

void Widget::draw(QPainter& painter, DrawParam& param)
{
    if( (param.type != NONE) && (param.points.count() >= 2) )
    {
        int x = (param.points[0].x() < param.points[1].x()) ? param.points[0].x() : param.points[1].x();
        int y = (param.points[0].y() < param.points[1].y()) ? param.points[0].y() : param.points[1].y();
        int w = qAbs(param.points[0].x() - param.points[1].x()) + 1;
        int h = qAbs(param.points[0].y() - param.points[1].y()) + 1;
        painter.setPen(QPen(param.color));
        painter.setBrush(QBrush(param.color));
        switch (param.type)
        {
        case FREE:
            for(int i=0; i<param.points.count()-1; i++)
            {
                painter.drawLine(param.points[i], param.points[i+1]);
            }
            break;
        case LINE:
            painter.drawLine(param.points[0], param.points[1]);
            break;
        case RECT:
            painter.drawRect(x, y, w, h);
            break;
        case ELLIPSE:
            painter.drawEllipse(x, y, w, h);
            break;
        default:
            break;
        }
    }
}

Widget::~Widget() = default;