• 10134阅读
  • 34回复

widget显示点图片怎么就这么难呢 [复制链接]

上一主题 下一主题
离线wjz2047
 

只看楼主 倒序阅读 楼主  发表于: 2014-02-27
由于需要,我使用QGraphicsWidget显示图片,代码如下,
mywidget.h:
  1. #ifndef MYWIDGET_H
  2. #define MYWIDGET_H
  3. #include <QGraphicsWidget>
  4. #include<QPixmap>
  5. class MyWidget : public QGraphicsWidget
  6. {
  7. public:
  8.     MyWidget(QString s);
  9.     QRectF boundingRect() const;
  10.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget*widget);
  11. private:
  12.     QPixmap p;
  13. };
  14. #endif // MYWIDGET_H

mywidget.cpp:
  1. #include "mywidget.h"
  2. #include<QPainter>
  3. MyWidget::MyWidget(QString s)
  4. {
  5.     p.load(s);
  6. }
  7. QRectF MyWidget::boundingRect() const
  8. {
  9.     qreal penWidth = 1;
  10.     return QRectF(0 - penWidth / 2, 0 -penWidth / 2,
  11.                20 + penWidth, 20 + penWidth);
  12. }
  13. void MyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
  14. {
  15.     Q_UNUSED(option);  //标明该参数没有使用
  16.     Q_UNUSED(widget);
  17.     //painter->setBrush(Qt::red);
  18.     //painter->drawRect(0,0,20,20);
  19.     painter->drawPixmap(0,0,p);
  20. }

最后我把它们放在QGraphicsView显示。这段代码看起来是对的,而且显示一些图像也是对的。
问题是当我显示1000多张大尺寸图像时,程序报错:


assert bitmap in file image qnativeimage.cpp


这是为什么?
离线wjz2047

只看该作者 1楼 发表于: 2014-02-27
补充说明的是:程序刚运行时,窗口的确把图片显示出来了,可当我最大化窗口时,就报那个错误了。
离线wjz2047

只看该作者 2楼 发表于: 2014-02-27
还有一点就是,我把 QPixmap p 作为类的私有成员,如果我直接在类的构造函数里这样写
    QPixmap p;
    p.load(s);
程序就不会出现问题了。
难道不能把一个QPixmap对象声明为QGraphicsWidget类的成员吗?显然是可以的啊。
这个问题纠缠了我很久,请大家帮忙
离线noidea

只看该作者 3楼 发表于: 2014-02-27
你先看一下你的Qt版本
Qt之前有bug report https://bugreports.qt-project.org/browse/QTCREATORBUG-7727

Qt Creator 2.5.2, 看看你是否中了。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 4楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:你先看一下你的Qt版本
Qt之前有bug report https://bugreports.qt-project.org/browse/QTCREATORBUG-7727
Qt Creator 2.5.2, 看看你是否中了。
 (2014-02-27 15:46) 

这种说法我也听过,可是我是qt 4.8.5,qt creator2.8.1,我这可是高配啊
离线wjz2047

只看该作者 5楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:你先看一下你的Qt版本
Qt之前有bug report https://bugreports.qt-project.org/browse/QTCREATORBUG-7727
Qt Creator 2.5.2, 看看你是否中了。
 (2014-02-27 15:46) 

另外值得一提的是,我的系统也是win7 64位
离线noidea

只看该作者 6楼 发表于: 2014-02-27
回 wjz2047 的帖子
wjz2047:还有一点就是,我把 QPixmap p 作为类的私有成员,如果我直接在类的构造函数里这样写
    QPixmap p;
    p.load(s);
程序就不会出现问题了。
难道不能把一个QPixmap对象声明为QGraphicsWidget类的成员吗?显然是可以的啊。
....... (2014-02-27 15:29) 

这个问题是构造列表顺序问题。

class MyWidget : public QGraphicsWidget
{
public:
     explicit MyWidget(0
private:
     QPixmap p;
}

那么在调用 MyWidget() 之前,私有成员QPixmap被初始化。
class MyWidget : public QGraphicsWidget
{
public:
     explicit MyWidget()
    {
        QPixmap p;
    }
}

这里QPixmap p在你的构造函数中初始化。

如果你收到这个影响,多半是初始化时间没判断好。比如,你想用QPixmap时候,他还没有被初始化,所以根本就没有内容,这样它也没什么图片要显示给你看的。

我只能猜测你的问题。
talk in code
Qt5.2.1 + MacOSX10.9
离线noidea

只看该作者 7楼 发表于: 2014-02-27
回 wjz2047 的帖子
wjz2047:另外值得一提的是,我的系统也是win7 64位 (2014-02-27 15:51) 

Ok,对这个GraphicView有销毁操作?

比如,你分配了内存给MyWidget,然后显示图片,然后销毁,然后又分配... 这样的循环?

你的代码上看不出这样问题。比如,你是否使用多线程,或者是否使用Camera抓frame,或者抓video的frame?
talk in code
Qt5.2.1 + MacOSX10.9
离线noidea

只看该作者 8楼 发表于: 2014-02-27
最后你有没有监测你的memory leak问题? 你程序运行的时候,内存是否一直在增加?
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 9楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:这个问题是构造列表顺序问题。
class MyWidget : public QGraphicsWidget
{
....... (2014-02-27 16:08) 

那现在我要在paint函数中使用drawpixmap(0,0,pixmap);
请问这个pixmap怎么初始化呢,在哪初始化呢?当然不能在paint函数中初始化,求教
离线wjz2047

只看该作者 10楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:
Ok,对这个GraphicView有销毁操作?
比如,你分配了内存给MyWidget,然后显示图片,然后销毁,然后又分配... 这样的循环?
.......

  1. k=0;
  2.     for(i=0;i<row;i++)
  3.     {
  4.     for(j=0;j<column;j++)
  5.     {
  6.          MyWidget *wg = new MyWidget(imagelist[k++]);
  7.          layout->addItem(wg,i,j);
  8.     }
  9.     }

也就是把一些widget放到布局里
离线wjz2047

只看该作者 11楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:最后你有没有监测你的memory leak问题? 你程序运行的时候,内存是否一直在增加? (2014-02-27 16:13) 

程序运行的时候要load很多图片,内存肯定在增加的,这属于泄露吗?
离线noidea

只看该作者 12楼 发表于: 2014-02-27
我这边打开qtcn很慢很慢,还一个问题,你是多大的图片不能显示?

我回去帮你做个测试算了。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 13楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:我这边打开qtcn很慢很慢,还一个问题,你是多大的图片不能显示?
我回去帮你做个测试算了。 (2014-02-27 17:23) 

没关系,我可以等。我显示的是1626张1280x854的图片。如果可以,我可以把工程和图片集全部给你,先谢谢了,你的回答对我来说很有帮助。
离线noidea

只看该作者 14楼 发表于: 2014-02-27
那你把你的项目上传到git上,或者什么方式给我也行。
我就不用去猜你到底出了什么问题了。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 15楼 发表于: 2014-02-27
回 noidea 的帖子
noidea:那你把你的项目上传到git上,或者什么方式给我也行。
我就不用去猜你到底出了什么问题了。 (2014-02-27 17:38) 

不好意思,晚上有点事出去了,我上传到网盘了,给你个链接
http://pan.baidu.com/s/1dDxKFex,这是源码,图片集有点大,就先不传了
离线wjz2047

只看该作者 16楼 发表于: 2014-02-27
呵呵,直接添加附件好了
源码.zip (5 K) 下载次数:7
离线noidea

只看该作者 17楼 发表于: 2014-02-27
我修改了你的代码 https://github.com/heefan/qtcn, wjz2047 branch

我试了1000张5000x5000的图片,消耗内存太大。
你试试看你那边吧。

有问题你再告诉我。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 18楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:我修改了你的代码 https://github.com/heefan/qtcn, wjz2047 branch
我试了1000张5000x5000的图片,消耗内存太大。
你试试看你那边吧。
....... (2014-02-27 23:47) 

能碰上你这么耐心为我解答的朋友,我很荣幸。只是撇开内存消耗,你修改后的代码能够实现窗口最大化不出错吗?
离线noidea

只看该作者 19楼 发表于: 2014-02-28
可以。

我截视频在google
https://drive.google.com/file/d/0B2DZwhOu-SysY3BCVnRkRklvV3M/edit?usp=sharing

我的测试环境 :
MacOS 10.9 + Qt5.2.1

我不太方面使用windows,没有Qt4.8
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 20楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:可以。
我截视频在google
https://drive.google.com/file/d/0B2DZwhOu-SysY3BCVnRkRklvV3M/edit?usp=sharing
....... (2014-02-28 09:46) 

那说明这个错误不是程序设计导致的,而是环境或版本导致的,对吗?
离线noidea

只看该作者 21楼 发表于: 2014-02-28
这种可能性不大,除非你是自己编译的Qt SDK。
更改后的代码你有测试过吗?

此外,我想提示一点改程序的潜在问题,
你用for循环去添加MyWidget,当图片数量大了就发生了问题,为什么?

因为MyWidget里边有repaint函数,repaint函数在event queue里边,当你view->show() (main.cpp)显示时候,就会大量调用repaint方法,而你的Qpixmap又不能释放掉,因为释放了,你就什么也显示不了了。所以占用大量的CPU和内存。

首先从你的软件设计上我觉得有待斟酌。

通常来说,都是显示一个大图,不用了,删除资源,没有保留那些狂耗内存资源的。
要么就是好像collection view,列出几行几列的图片到屏幕上,用户操作后,销毁上次载入到屏幕的图片,然后再载入新的几行几列的图片,这样内存就不会无端消耗了。

你的内存释放(QPixmap)最后都是在程序关闭后,而不是程序不需要的时候。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 22楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:可以。
我截视频在google
https://drive.google.com/file/d/0B2DZwhOu-SysY3BCVnRkRklvV3M/edit?usp=sharing
....... (2014-02-28 09:46) 

我看了你的视频,你只打开了一张图片进行测试,而且尺寸不大,你用1000张5000x5000的图片集测试过吗?
离线noidea

只看该作者 23楼 发表于: 2014-02-28
这个在家测试过,没有出现你说的bitmap那个问题,
最后是程序没法响应了,我内存没了。
程序只是吃内存,完全没有内存的回收。我最后只好kill到这个程序。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 24楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:这种可能性不大,除非你是自己编译的Qt SDK。
更改后的代码你有测试过吗?
此外,我想提示一点改程序的潜在问题,
你用for循环去添加MyWidget,当图片数量大了就发生了问题,为什么?
....... (2014-02-28 10:02) 

有些事情没办法,假设有1000张图片,我需要一次性的把它们在窗口中显示出来,而且在窗口中我还要对这些图片做缩放和移动的操作。在此期间,它们肯定得占用资源。我不担心资源的问题,只要它不出错就好。
离线wjz2047

只看该作者 25楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:这个在家测试过,没有出现你说的bitmap那个问题,
最后是程序没法响应了,我内存没了。
程序只是吃内存,完全没有内存的回收。我最后只好kill到这个程序。 (2014-02-28 10:05) 

我觉得,在我的这种“无理”需求下,想完成内存的及时回收是不可能的。
离线wjz2047

只看该作者 26楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:这个在家测试过,没有出现你说的bitmap那个问题,
最后是程序没法响应了,我内存没了。
程序只是吃内存,完全没有内存的回收。我最后只好kill到这个程序。 (2014-02-28 10:05) 

有点遗憾的是,你没有重现我的错误。我还有一点点的要求,如果可以,你把图片数量缩减到几百张的样子,在内存够用的情况下,运行我的程序。然后在图片显示出来后,最大化一下窗口,看看有没有我的那个bitmap错误。
唉,顿时感到很忧伤。你能重现我的错误又如何,不能重现又如何?
离线noidea

只看该作者 27楼 发表于: 2014-02-28
比较贱一点的方法,你试试看QImage代替QPixmap。
你出现bitmap什么错误,或许因为是和device相关,QPixmap是和device相关的。
QImage和Device无关。


talk in code
Qt5.2.1 + MacOSX10.9
离线noidea

只看该作者 28楼 发表于: 2014-02-28
回 wjz2047 的帖子
wjz2047:有点遗憾的是,你没有重现我的错误。我还有一点点的要求,如果可以,你把图片数量缩减到几百张的样子,在内存够用的情况下,运行我的程序。然后在图片显示出来后,最大化一下窗口,看看有没有我的那个bitmap错误。
唉,顿时感到很忧伤。你能重现我的错误又如何,不能重现又如何? (2014-02-28 10:24) 

我试试看吧,重现了好找问题,不然怎么知道你到底问题在哪里。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 29楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:我试试看吧,重现了好找问题,不然怎么知道你到底问题在哪里。 (2014-02-28 10:34) 

我先谢谢了,不知道要谢你多少次才能表达我的感激。问题暂时搁在这,有新情况再讨论
离线noidea

只看该作者 30楼 发表于: 2014-02-28
回 wjz2047 的帖子
wjz2047:我先谢谢了,不知道要谢你多少次才能表达我的感激。问题暂时搁在这,有新情况再讨论 (2014-02-28 10:37) 

 问题解决最重要。
关键你应该知道坑在什么地方。

我把QPixmap改成QImage,然后测试562张大图。
载入完最大化,没有问题。

测试参看视频:https://drive.google.com/file/d/0B2DZwhOu-SysVzhzVllsTi1LZzg/edit?usp=sharing

代码我更新了github,你可以自行测试
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 31楼 发表于: 2014-02-28
回 noidea 的帖子
noidea:
问题解决最重要。
关键你应该知道坑在什么地方。
我把QPixmap改成QImage,然后测试562张大图。
.......

我看了你的视频,你成功了。但是我这边还是老样子


这让我彻底绝望了
离线noidea

只看该作者 32楼 发表于: 2014-02-28
回 wjz2047 的帖子
wjz2047:我看了你的视频,你成功了。但是我这边还是老样子
[图片]
这让我彻底绝望了 (2014-02-28 11:45) 

 我看一下Qt的源代码,首先Qt5.2和Qt4.8里边的QNativeImage确实不一样。

Qt4.8里边的源代码关于你这个错误,

line 115 - line 118
  1. uchar *bits = 0;
  2. bitmap = CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO *>(&bmi), DIB_RGB_COLORS, (void**) &bits, 0, 0);
  3. Q_ASSERT(bitmap);
  4. Q_ASSERT(bits);


你的错误发生在117行,说明bitmap创建失败,bitmap HBITMAP 类型(定义在"qnativeimage_p.h")
CreateDIBSection 是windows的API函数。参见:http://msdn.microsoft.com/en-us/library/windows/desktop/dd183494(v=vs.85).aspx
所以你的程序失败在这个函数上,显然这个函数不是我的Mac调用的。

我简单看了下QPixmap和QImage的实现,
qnativeimage类是被QPixmap使用的,在QImage里边没有调用这个函数(我只是大致看一下)

如果你有兴趣你可以再次测试一下:
1. QPixmap改成QImage, (我在github里边改了,不知道你改了没有)
2. 你可以打印出出错时候的那个图片,第几个序列,看看载入时候的图片是否有值。
talk in code
Qt5.2.1 + MacOSX10.9
离线wjz2047

只看该作者 33楼 发表于: 2014-02-28
回 noidea 的帖子
noidea: 我看一下Qt的源代码,首先Qt5.2和Qt4.8里边的QNativeImage确实不一样。
Qt4.8里边的源代码关于你这个错误,
....... (2014-02-28 13:21) 

      你上次成功的时候,使用的是QImage,而之前你使用QPixmap未成功,是因为内存不够,(我不知道你有没有用500多张图片测试过QPixmap的版本)。我使用了你最新的QImage版本,错误依旧。

    有一个问题我一直没说,现在你建议我打印出错图片,我还是说下。当我用程序打开1000多张图片时,其实显示出来的只有几百张。我在for循环中加了句代码
qDebug()<<image.width();,这时输出为0,你怎么看?
离线noidea

只看该作者 34楼 发表于: 2014-03-01
回 wjz2047 的帖子
wjz2047:      你上次成功的时候,使用的是QImage,而之前你使用QPixmap未成功,是因为内存不够,(我不知道你有没有用500多张图片测试过QPixmap的版本)。我使用了你最新的QImage版本,错误依旧。
    有一个问题我一直没说,现在你建 .. (2014-02-28 15:31)

QPixmap还是QImage和我的Mac都没关系,因为Qt调用的是wnidows的API出错。
所以在Mac上用QImage和QPixmap都不影响。

1. 判断width=0的图片是否损坏?
你需要找出这个图片名字,是不是图片损坏,或者你剔除掉这个图片再测试。

2. 你也可以测试小图片,100x100左右的,测试载入1000张,如果没有问题,基本上说明你没有足够的系统资源来跑你的程序。
talk in code
Qt5.2.1 + MacOSX10.9
快速回复
限100 字节
 
上一个 下一个