Qt-绘图软件的直线绘制是如何将点连接为直线的?

Qt-绘图软件的直线绘制是如何将点连接为直线的?

甜柠檬 发布于 2017-09-11 字数 2653 浏览 1289 回复 2

最近在写一个绘图软件,借助Qt的强大功能,还算比较顺利,但在深入绘图功能的时候,我有一个疑问,即:绘图的点是如何连接成为直线的?

Qt和其它界面库一样提供了lineTo之类的函数可以直接绘制直线,但这种情况仅仅只有粗细、颜色等几个非常有限的API,如果要提供笔刷这样的选项,就无能为力了。所以转而采用drawPixmap这样的函数来连续绘制准备好的笔刷。

但是笔刷本身是一个近似于圆形的图形,连续绘制仍然是孤立的点。我将这些点绘制的非常密集,结果半透明笔刷由于密集点的叠加,变成了不透明。

所以我非常想知道现有的绘图软件是怎么绘制直线的,这些密集的点怎样可以成为看起来连贯的直线?

希望我把我的问题说清楚了。。

看图说话:
第一张图是我目前的问题描述:
这个是问题的图形说明

第二张图是我理想的效果(airbrush),由GIMP生成:
这个是期望的效果

第三张图,使用drawLine,然后给QPen使用一个setBrush,在QBrush中设置了笔刷:

使用drawLine

补充第三张图所使用的关键代码:

void Widget::paintEvent(QPaintEvent */*ev*/)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawPixmap(50, 50, 100, 100, *p1); // 绘制笔刷的原图
painter.drawPixmap(150, 50, 100, 100, *p3); // 绘制上色之后的笔刷
painter.drawPixmap(250, 50, 100, 100, *p2); //绘制加入噪点的笔刷
painter.drawImage(0,0,*canvas); //绘制鼠标绘图到屏幕
}

void Widget::mousePressEvent(QMouseEvent *ev)
{
if(ev->buttons() & Qt::LeftButton){
QPainter painter(canvas);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawPixmap(ev->pos().x()-50,ev->pos().y()-50,*p3); //鼠标按下时产生一个点
update();
lastPos = ev->pos();
}
}

void Widget::mouseMoveEvent(QMouseEvent *ev)
{
if(ev->buttons() & Qt::LeftButton){
QPainter painter(canvas); //canvas是一个指向QImage对象的指针,最终将被绘制到屏幕上
painter.setRenderHint(QPainter::Antialiasing);

QPen pen;
pen.setWidth(p3->width()); //p3是一个指向QImage对象的指针,代表的是笔刷图形
QBrush brush;
brush.setTexture(*p3);
pen.setBrush(brush);
painter.setPen(pen);
painter.drawLine(lastPos, ev->pos()); //lastPos是记录的上一次绘制的最后坐标
update();
lastPos = ev->pos(); //更新坐标
}
}

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

归属感 2017-10-13 2 楼

没有太明白你的意思。怎么会出现你说的情况的呢。qt提供的功能可以提供笔刷的功能呀。呵呵
要是你想自己去实现的话,那就是一个path路径的绘制了。通过鼠标走过的轨迹,然后绘制下来。道理还是和绘制直线是一样,一开始,是有起始点和终止点进行绘制可以使一条直线,鼠标一开始按下的时候,是起始点,鼠标移动就是终止点,每次都在鼠标移动事件里面进行处理,让终止点的坐标变为起始点,这些操作都是在paint里面完成的,然后进行完上面的操作的时候,刷新界面,这个界面的刷新时每写一个直线就刷新一下。如果像你上面说的那个问题的话,你画下一个点的时候不要清空原来的图像,这样的话就能够连接在一起了。

想挽留 2017-09-25 1 楼

直线的原理就是先画点,再画线。但是这里的点还是很有含义的,涉及到到底是逻辑点还是物理点。程序里面指定的就是逻辑点,但是每个逻辑点需要几个物理点来显示是不确定的。取决于输出设备的精度。关于这点,推荐LZ去看看PPI与DPI的区别,应该会有一个很深的了解