综合实例开发:简易绘图程序
功能需求:
- 自由图形绘制
- 基本图形绘制 (直线,矩形,椭圆)
- 能够选择图形绘制颜色
简易绘图程序运行截图
界面解决方案
1. 以 QWidget 为基类创建绘图主窗口
2. 使用 QGroupBox 创建图形设置区域
3. 使用单选按钮 QRadioBox 实现目标图形的选择
4. 使用组合框 QComBox 实现绘图颜色的选择
问题
如何实现自由绘图?
分析
自由绘图的本质是跟踪鼠标的移动轨迹;因此,必须考虑什么时候开始?什么时候结束?如何记录鼠标移动?
提示一
从绘图参数的角度,可以将已绘制结束的图形与正在绘制的图形分开处理。
提示二
自由绘图必须记录鼠标移动时经过的所有点坐标;因此绘图参数必须有能力保存多个坐标值。
自由绘图解决方案
问题
如何实现基础图形动态绘制?
分析
基础图形的目标是固定的,但是开始点和结束点的不同会导致最终形状的差异;因此鼠标移动时根据当前坐标实时绘图,鼠标松开时确定最终图形。
提示三
基本图形绘制需要在鼠标按下并移动时进行动态绘图;但是,无论何时都只需要记录两个坐标值。
基础图形绘制解决方案
图形绘制
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QRadioButton>
#include <QComboBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QList>
#include <QPoint>
enum DrawType
{
NONE,
FREE,
LINE,
RECT,
ELLIPSE
};
class Widget : public QWidget
{
Q_OBJECT
private:
struct DrawParam
{
DrawType type;
Qt::GlobalColor color;
QList<QPoint> points;
};
QRadioButton m_freeBtn;
QRadioButton m_lineBtn;
QRadioButton m_rectBtn;
QRadioButton m_ellispeBtn;
QComboBox m_colorBox;
QGroupBox m_grpBox;
QList<DrawParam> m_drawList;
DrawParam m_current;
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
public:
Widget(QWidget *parent = nullptr);
DrawType drawType()
{
DrawType ret = NONE;
if(m_freeBtn.isChecked()) ret = FREE;
if(m_lineBtn.isChecked()) ret = LINE;
if(m_rectBtn.isChecked()) ret = RECT;
if(m_ellispeBtn.isChecked()) ret = ELLIPSE;
return ret;
}
Qt::GlobalColor 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 draw(QPainter &painter, DrawParam &p);
void append(QPoint p);
~Widget();
};
#endif // WIDGET_H
Widget.cpp
#include "Widget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_grpBox.setParent(this);
m_grpBox.resize(800, 70);
m_grpBox.move(20, 20);
m_grpBox.setTitle("Setting");
m_freeBtn.setParent(&m_grpBox);
m_freeBtn.resize(60, 20);
m_freeBtn.setText("Free");
m_freeBtn.setChecked(true);
m_lineBtn.setParent(&m_grpBox);
m_lineBtn.resize(60, 20);
m_lineBtn.setText("Line");
m_rectBtn.setParent(&m_grpBox);
m_rectBtn.resize(60, 20);
m_rectBtn.setText("Rect");
m_ellispeBtn.setParent(&m_grpBox);
m_ellispeBtn.resize(60, 20);
m_ellispeBtn.setText("Ellipse");
m_colorBox.addItem("Black");
m_colorBox.addItem("Blue");
m_colorBox.addItem("Green");
m_colorBox.addItem("Red");
m_colorBox.addItem("Yellow");
QHBoxLayout* layout = new QHBoxLayout();
layout->addWidget(&m_freeBtn);
layout->addWidget(&m_lineBtn);
layout->addWidget(&m_rectBtn);
layout->addWidget(&m_ellispeBtn);
layout->addWidget(&m_colorBox);
m_grpBox.setLayout(layout);
m_current.type = NONE;
m_current.color = Qt::white;
m_current.points.clear();
resize(840, 600);
}
void Widget::mousePressEvent(QMouseEvent *event)
{
m_current.type = drawType();
m_current.color = drawColor();
append(event->pos());
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
append(event->pos());
update();
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
append(event->pos());
m_drawList.append(m_current);
m_current.type = NONE;
m_current.color = Qt::white;
m_current.points.clear();
update();
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
for(int i = 0; i < m_drawList.count(); i++)
{
draw(painter, m_drawList[i]);
}
draw(painter, m_current);
}
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::draw(QPainter &painter, DrawParam &p)
{
painter.setPen(p.color);
painter.setBrush(p.color);
if(p.type != NONE && (p.points.count() >= 2))
{
int x = (p.points[0].x() < p.points[1].x() ? p.points[0].x() : p.points[1].x());
int y = (p.points[0].y() < p.points[1].y() ? p.points[0].y() : p.points[1].y());
int w = qAbs(p.points[0].x() - p.points[1].x());
int h = qAbs(p.points[0].y() - p.points[1].y());
switch (p.type)
{
case FREE:
for(int i = 0; i < p.points.count() - 1; i++)
{
painter.drawLine(p.points[i], p.points[i + 1]);
}
break;
case LINE:
painter.drawLine(p.points[0], p.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()
{
}
程序运行结果如下所示: