第68课 - 基础图形绘制(下) --- 简易绘图程序

版权声明:课程笔记内容整理于狄泰软件 https://blog.csdn.net/qq_39654127/article/details/81904630

1、基础图形绘制 

综合实例开发:简易绘图程序 

    -功能需求: 

             ★ 自由图形绘制 

             ★ 基本图形绘制(直线,矩形,椭圆) 

             ★ 能够选择图形绘制颜色 

 

简易绘图程序运行截图 

界面解决方案 

         1. 以QWdget为基类创建绘图主窗口 

         2. 使用QGroupBox创建图形设置区域 

         3. 使用单选按钮QRadioBox实现目标图形的选择

         4. 使用组合框Combox实现绘图颜色的选择

 

2、问题 

 如何实现自由绘图? 

分析 

        自由绘图的本质是跟踪鼠标的移动轨迹;因此,必须考

        虑什么时候开始?什么时候结束?如何记录鼠标移动? 

 

两个提示

         ★ 从绘图参数的角度,可以将已经绘制结

             束的图形与正在绘制的图形分开处理。 

         ★ 自由绘图必须记录鼠标移动时经过的所有点坐标;

             因此,绘图参数必须有能力保存多个坐标值。 

自由绘图解决方案 

       1. 以鼠标按下为开始,记录开始坐标 

              • mousePressEvent 

       2. 记录鼠标移动时经过的像素坐标 

              • mouseMoveEvent 

       3. 以鼠标释放为结束,记录结束坐标 

              • mouseReleaseEvent 

       4 . 按照记录顺序在俩俩坐标之间绘制直线 

              • paintEvent 

3、问题 

如何实现基础图形动态绘制? 

分析 

        基础图形的目标是固定的,但是开始点与结束点的不同

        会导致最终形状的差异;因此,鼠标移动时根据当前坐

        标实时绘图鼠标松开时确定最终图形。 

提示

         ★ 基本图形绘制需要在鼠标按下并移动时进行动态绘

             图;但是,无论何时都只需要记录两个坐标值。 

 

基础图形绘制解决方案 

       1. 以鼠标按下为开始,记录开始坐标 

              • mousePressEvent 

       2. 将鼠标移动时经过的每个坐标作为临时结束坐标 

              • mouseMoveEvent 

       3. 以鼠标释放为结束,确定最终结束坐标 

              • mouseReleaseEvent 

       4 在开始坐标和结束坐标之间绘制目标图形 

              • paintEvent 

4、编程实验 

基础图形绘制   68-1.pro 

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/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:
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>

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);

    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()
{
    
}

5、小结 

绘图程序需要重写鼠标事件处理函数 

模型视图的思想适用于绘图程序 

所有图形的绘制由paintEvent函数完成 

工程中需要避免在绘制时进行浮点运算 

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81904630
今日推荐