Qt关于画图的问题

jiangzy80 2010-05-31 01:13:36
hi, 小弟刚接触Qt不久,现在想做一个小例子,就是把一幅图片(jpg格式的)显示在窗口上,图片是从屏幕左边移动到屏幕右边的,在移动过程中,图片也作了360度的旋转。

我定义了一个类:
class JoneyView : public QWidget
{
Q_OBJECT

protected:
void paintEvent(QPaintEvent *event = 0);

public:
JoneyView(QWidget *parent, QRect pRect);
~JoneyView();

.........



}


void JoneyView::paintEvent(QPaintEvent *event)
{
static QPixmap pix(this->size());
pix.fill(this, this->rect().topLeft());
QPainter p(&pix);

p.setRenderHint(QPainter::Antialiasing, true);
p.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
p.setBrush(QBrush(Qt::green, Qt::SolidPattern));
p.drawEllipse(mRect3);

p.end();

QPainter painter(this);
painter.begin(this);
painter.drawPixmap(rect(), pix);
painter.end();


/*
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, false);

if (!mTimerIsStarted)
painter.drawPixmap(mRect3, mImage3);
*/

}

其中的mRect3是一个由QTimer控制的从左到右不断变化的QRect.
mImage3是在别的地方加载的一个图片,调用update来触发paintEvent重绘图片
但是在paintEvent函数中,不管是没有注释的双缓冲画图部分还是已经注释了的显示图片的部分,在图像移动的过程中都出现了很明显的闪烁现象,如果图片不移动,只是在原位置旋转都看不见闪烁现象,往高手帮忙解决下,谢谢了

主要就是一旦移动图片,就出现闪烁,我把图片变小了试都还是有闪烁,Qt应该是比较成熟的了,像这类的问题应该是可以实现的吧。
...全文
998 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
npuhuxl 2010-06-12
  • 打赏
  • 举报
回复
http://www.qtcn.org/bbs/read.php?tid=8116

在使用qt3.3.2开发实时系统的图形时,如果我们需要设置图形的背景图,需要使用下面的函数进行绘制:

void QPainter::drawImage ( const QPoint &, const QImage &, const QRect & sr, int conversionFlags = 0 )或者是

void QPainter::drawPixmap ( int x, int y, const QPixmap & pixmap, int sx = 0, int sy = 0, int sw = -1, int sh = -1 )

如果你在绘制大的背景图时使用了drawImage()函数,你将会发现背景图刷新的速度会比较慢,这一点在qt的文档中也进行了说明:

There are functions to draw pixmaps/images, namely drawPixmap(), drawImage() and drawTiledPixmap(). drawPixmap() and drawImage() produce the same result, except that drawPixmap() is faster on-screen and drawImage() faster and sometimes better on QPrinter and QPicture.

还有在drawImage()函数的说明中:

This function may convert image to a pixmap and then draw it, if device() is a QPixmap or a QWidget, or else draw it directly, if device() is a QPrinter or QPicture.

所以我们要做的第一步就是要把程序中使用drawImage()函数的地方转化为drawPixmap();

Ok,完成了上面的第一步之后,背景图刷新快多了,但出现了第二个问题又出现了,将QImage转换为QPixmap或者直接将图形加载为QPixmap依然很慢,这样就造成第一次打开某个图形文件时,背景图的加载会变得比较慢(当然,打开后只需要drawpixmap,就会比较流畅了),为了解决这个问题,我们设置如下结构:

Struct file2qpixmap

{

Char filename[256];

QPixmap qpixmap;

};

将背景图片文件与相应的QPixmap数据结合起来做成一个全局的链表,每次打开图形文件后到链表中查找相应的背景图形对应的QPixmap数据是否已经存在,如果存在则直接使用,如果不存在,就插入一个新的节点.这样,对于使用同一副背景图片的图形文件而言,背景图形的QPixmap数据只需要加载一次.这样就再一次提高了图形文件刷新和切换的速度.

更进一步,我们可以把上述链表的内容写入内存映射文件或者数据库,每次程序启动的时候只需要将链表映射到当前程序的内存中就可以使用了,这样就进一步加快了背景图形的刷新,而且这样跳开了对qpixmap数据的加载.但这种方法我没有进行测试,有兴趣的朋友可以试一下.
「已注销」 2010-06-11
  • 打赏
  • 举报
回复
1:短期内的解决办法:
不要用QTime,使用时间线试下。

2:最好的解决办法:
如果有时候,修改下,不要再用QWidget,转去使用QGraphicsWidget, 这样的话:我们可以直接旋转QGraphicsWidget本身,而不用费劲去旋转上边的图片。从而不需要重写paintEvent(),这样绝地不会出现这个问题。
jiangzy80 2010-06-02
  • 打赏
  • 举报
回复
还望各位高手支招啊
jiangzy80 2010-06-01
  • 打赏
  • 举报
回复
谢谢3楼的兄弟,关键是我其它部分都已经做好了,而且我要移动的不止是一幅图片,而是好几幅,而且每个图片都要旋转,这样如果都加label可能在移动的过程中算rect有点麻烦,而且有的地方要交替哈。不过还是很谢谢你的代码。


[Quote=引用 4 楼 dext 的回复:]

楼上 的方法可以轻松实现移动,但是旋转就要麻烦死了,还要新继承一个类,然后 加入 rotate 之类的。

其实 这个问题就是利用一个双缓存技术,每次将 要画的结果 花在一个 QPixmap, 然后再 窗口的 paintEvent 中 只需要调用

painter.drawPixmap(...);

就行了

每次 Timeout 的时候 update 就行了。

楼主已经差……
[/Quote]

首先说声谢谢你哈,我代码paintEvent中没有注释的部分应该就是双缓冲技术了吧,我在每次Timeout的时候只是计算了下rect的值而已,然后就update了,这个应该就是你说的方法吧,但是明显的看出这个椭圆有闪烁,我用的是黑色背景,每次移动的过程中,很明显的能看见有些白色的线条在闪烁,但是闪烁的不是很大哈,但是肉眼能看见。

不知是不是我哪里还没有处理好?望指出,谢谢了!
dext 2010-06-01
  • 打赏
  • 举报
回复
楼上 的方法可以轻松实现移动,但是旋转就要麻烦死了,还要新继承一个类,然后 加入 rotate 之类的。

其实 这个问题就是利用一个双缓存技术,每次将 要画的结果 花在一个 QPixmap, 然后再 窗口的 paintEvent 中 只需要调用

painter.drawPixmap(...);

就行了

每次 Timeout 的时候 update 就行了。

楼主已经差不多了,稍微修改一下就行了。
Aisy_D 2010-05-31
  • 打赏
  • 举报
回复
这是移动部分,绝对不闪烁, 旋转你自己解决....

class MainWindow : public QWidget
{
public:

MainWindow(QWidget *parent = 0) : QWidget(parent)
{

QLabel *tootbtn = new QLabel("",this);
tootbtn->setPixmap(QPixmap("E:/QTLearning/wxq2.jpg" ));



QPropertyAnimation *anim = new QPropertyAnimation(tootbtn, "geometry" );
anim->setStartValue(QRect(-400,200,600,620));
anim->setKeyValueAt(.8, QRect(1600,200,600,620));
anim->setEndValue(QRect(800,200,600,620));
anim->setDuration(2000);
anim->setEasingCurve(QEasingCurve::InBounce);
anim->start();



}

};



int main(int argc, char **argv)
{
QApplication app(argc, argv);


MainWindow window;

window.showMaximized();

return app.exec();
}
jiangzy80 2010-05-31
  • 打赏
  • 举报
回复
iTimer->start(100);
这个应该还是比较慢了吧
  • 打赏
  • 举报
回复
计时器间隔?

16,240

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧