QT 5.6:第二次调用QGraphicsScene :: addItem()

时间:2016-05-17 14:23:56

标签: c++ qt qgraphicsscene qpixmap

我在第二次调用QGraphicsScene :: addItem()时一直遇到分段违规。

以下代码第一次工作,但是在终止/重新加载QDialog,QApplication等(在DLL中调用)之后,代码在第二次使用同一图像时会一直失败!?!

让我想知道析构函数是否干净地终止,或者我是否需要以不同方式重新初始化QApplication。

建议,好吗?这是我的代码......

    PBITMAPINFOHEADER pDIBInfoHeader = (PBITMAPINFOHEADER)m_pImage;
    QGraphicsScene *pgs = new QGraphicsScene();
    pgs->setSceneRect(0.0, 0.0, 70.0, 80.0);
    QSize qs(70, 80);

    int width = pDIBInfoHeader->biWidth;
    int height = pDIBInfoHeader->biHeight;

    uchar *pBits = (uchar *)m_pImage + sizeof(BITMAPINFOHEADER);
    QImage *pqi = new QImage((uchar *)pBits, width, height, QImage::Format_Grayscale8);
    QImage qiFlip = pqi->mirrored(false, true);         //flip image vertically
    delete pqi;

    QPixmap *ppm = new QPixmap;
    if (!ppm->convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion))
        cdbg << "ppm->convertFromImage false" << endl;

    // DOES QGRAPHICSPIXMAPITEM TAKE OWNERSHIP OF QPIXMAP?
    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(*ppm, 0);    

    delete ppm;

    pgs->addItem(item);  // <<< SIGSEGV
    ui->grXray->setScene(pgs);

注意:pgs是场景中唯一的项目。场景未激活。

我使用Windows MSVC 2015的调试选项重建了QT,并且可以看到很多细节,但C ++模板,QVariant和QMetaType的复杂性让我感到震惊。我应该在哪里寻找腐败?

这是SIGSEGV的调用堆栈:

QMetaType::construct(void * where, const void * copy) Line 2153 C++
`anonymous namespace'::customConstruct(QVariant::Private * d, const void * copy) Line 1020 C++
QVariant::QVariant(const QVariant & p) Line 1372 C++
QGraphicsItem::itemChange(QGraphicsItem::GraphicsI temChange change, const QVariant & value) Line 7447 C++
QGraphicsScene::addItem(QGraphicsItem * item) Line 2496 C++

QT代码段:

inline void *QMetaType::construct(void *where, const void *copy) const
{
if (Q_UNLIKELY(isExtended(ConstructEx)))
return constructExtended(where, copy);
return m_constructor(where, copy);                 //<<<<<<<<
}


QVariant::QVariant(const QVariant &p)
: d(p.d)
{
if (d.is_shared) {
d.data.shared->ref.ref();
} else if (p.d.type > Char) {
handlerManager[d.type]->construct(&d, p.constData());   //<<<<<<
d.is_null = p.d.is_null;
}
}


void QGraphicsScene::addItem(QGraphicsItem *item)
...
// Notify the item that its scene is changing, and allow the item to
// react.
const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
QVariant::fromValue<QGraphicsScene *>(this)));  // <<<<<<<<<

1 个答案:

答案 0 :(得分:0)

不需要在堆上构建public class MyObject : INotifyPropertyChanged { private int id; public int Id { get { return id; } private set { id = value; OnPropertyChanged("Id"); } } private string name; public string Name { get { return name; } set { if (value == name) return; name = value; OnPropertyChanged("Name"); CheckIfModified(); } } public bool IsModified { get; private set; } public bool IsPersistable { get; private set; } public MyObject OriginalState { get; private set; } public MyObject(int id, string name, bool saveOriginalState = false) { Id = id; Name = name; if (saveOriginalState) OriginalState = new MyObject(id, name); } ///... More BI code (determine if modified/persistable etc...) } pqi你还在使用ppm时摧毁它。

您的代码的清洁版本将是:

ppm

代码甚至可以缩短,但开始时可读性会降低。