QT学习=====QPainter,PaintEvent,setRenderHint(防止图形走样)

https://jingyan.baidu.com/article/ad310e80cd7bf61849f49ec9.html

update();

repaint();

Qt里面的重绘和Windows编程里面的重绘差不多。但是Qt的重绘更有特色,更加智能。

在讲之前,先说说paintEvent()

paintEvent()是一个虚函数槽(slot),子类可以对父类的paintEvent进行重写。当调用 update(),repaint()的时候,paintEvent()会被调用,另外,当界面有任何改变的时候,paintEvent()也会被调用,这种界面的改变包括界面从隐藏到显示,界面尺寸改变,当然还包括界面内容改变的时候会被调用。paintEvent()是已经被高度优化过的函数,它本身已经自动开启并实现了双缓冲(X11系统需要手动去开启双缓冲),因此Qt中重绘不会引起任何闪烁。

有了paintEvent的知识,现在再来看看update()和repaint()

update和repaint是一类的,需要重绘的对象主动去调用,然后重绘。update和repaint调用之后,都回去调用paintEvent().

repaint(),被调用之后,立即执行重绘,因此repaint是最快的,紧急情况下需要立刻重绘的可以使用repaint()。但是调用 repaint的函数不能放到paintEvent中调用。举个例子:有一个继承于QWidget的子类MyWidget,并在子类中对 paintEvent进行了重写。我们在MyWidget::myrepaint()中调用repaint()。但是,myrepaint()又被重写的 paintEvent()调用。这样调用repaint()的函数又被paintEvent()调用,由于repaint()是立即重绘,而且repaint()在调用 paintEvent之前几乎不做任何优化操作,而是会造成死循环,即:先调用repaint(),继而调用 paintEvent(),paintEvent()反过来有调用repaint()…如此死循环。

update()跟repaint()比较,update则更加有优越性。update()调用之后并不是立即重绘,而是将重绘事件放入主消息循环中,由main的event loop来统一调度的(其实也是比较快的)。update在调用paintEvent之前,还做了很多优化,如果update被调用了很多次,最后这些 update会合并到一个大的重绘事件加入到消息队列,最后只有这个大的update被执行一次。同时也避免了repaint()中所提到的死循环。因此,一般情况下,我们调用update就够了,跟repaint()比起来,update是推荐使用的。

如果在paintEvent中有改变某一个变量(假设为a)值的代码,这个时候要注意,调用update后,如果显示a的值,则此时由于updata()没有立即执行,a的值并没有改变。而调用repaint()又引起闪烁,这个时候可以考虑将改变变量a的值的代码改写到paintEvent()的外

Qt中的函数应用

反走样技术

painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿

案例:


    QPainter painter(this);
    painter.setPen(QPen(Qt::black,5,Qt::DashDotLine,Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(50,150,200,150);

    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setPen(QPen(Qt::black,5,Qt::DashDotDotLine,Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(300,150,200,150);

QPainter函数参数:
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
第一个参数: 画笔的颜色: black
第二个参数: 画笔的粗细: 5px
第三个参数: 画笔的类型: DashDotLine(线和点相间)
: 用了一个圆形的笔冒
用了一个黄色填充了圆(从50,150)处开始画,然后在半径为200(横向),150(纵向)

antialiasing 防止走样

QPainter是一个状态机,因此,只要这里我们打开了它,之后所有
的代码都会是反走样绘制的了。

看到这里你会发现,反走样的效果其实比不走样要好得多,那么,为什么不默认打开反走样呢?
这是因为,反走样是一种比较复杂的算法,在一些对图像质量要求不高的应用中,
是不需要进行反走样的。为了提高效率,一般的图形绘制系统, 如Java2D、
OpenGL之类都是默认不进行反走样的。

还有一个疑问,既然反走样比不反走样的图像质量高很多,不进行反走样的绘制还有什么作用呢?
答:(1) 前面说的是一个方面,也就是,在一些对图像质量要求不高的环境下,或者说性能受
限的环境下,比如嵌入式和手机环境,是不必须要进行反走样的。
(2)另外还有一点,在一些必须精确操作像素的应用中,也是不能进行反走样的。

Photoshop里面的铅笔工具是不进行反走样,而画笔是要进行反走样的。在放大的情况下就会知道,
有反走样的情况下是不能进行精确到1像素的操作的。因为反走样很难让你控制到1个像素。这不是
Photoshop画笔工具的缺陷,而是反走样算法的问题。如果你想了解为什么这样,请查阅计算机图
形学里面关于反走样的原理部分。

DrewLine进行画线:
“`

  QPainter painter(this);
  QPen pen; // 调整线条宽度
  pen.setWidth(2);
  painter.setPen(pen);
  painter.setRenderHint(QPainter::Antialiasing,true);

 for(int i=0;i<100;i++)
 {
 painter.drawLine(20+ 10 * i, 20, 20+ 10 * i, size().height() - 20);
 从(20,20)开始,到(20,h-20)结束,依次纵座标向横座标向有右偏移
 painter.drawLine(20, 20 + 10 * i, size().width() - 20, 20 + 10 * i);
 从(20,20)开始,到(w-20,20)结束,依次纵座标向后偏移10
 }

“`
DrawLine的参数介绍,(int x1,int y1,int x2,int y2)

发布了57 篇原创文章 · 获赞 35 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章