2016-01-27 5 views
0

У меня есть окно, содержимое которого я хочу экспортировать в .png-файл. Я использую это делают функцию, чтобы сделать его на QImage:QWidget :: render() on QImage

QLOG("Image export mode"); 
const QString refpath = seq_->item(0)->path(0); 
QImage refimg(refpath); 
const QSize imgsize = refimg.size(); 
QLOG("image size: " << imgsize); 
Q_ASSERT(mapwin_); 
mapwin_->resize(imgsize); 
// the window doesn't seem to fit the image well the first time around, so do it 
// once and disregard the result - no idea why this happens. 
mapwin_->showImage(refimg); 
QImage winimage(mapwin_->size(), QImage::Format_ARGB32); 
emit mapFit(); 
QPainter painter(&winimage); 
emit renderWindow(&painter); 

emit message("Exporting images"); 
emit startProgress(itemIndices_.size()); 

// iterate over indices of selected images in sequence 
for (int i = 0; i < itemIndices_.size(); ++i) 
{ 
    const int itemidx = itemIndices_.at(i); 
    Q_ASSERT(itemidx >= 0); 
    const SeqItem *item = seq_->item(itemidx); 
    Q_ASSERT(item->mapExists()); 
    QLOG("Item " << i << " (" << itemidx << "): '" << item->filename(0) << "'"); 
    QLOGINC; 

    // iterate over selected displacement components 
    for (int ci = 0; ci < cci::VAL_COUNT; ++ci) 
    { 
     const cci::ValueID id = cci::VAL_ID[ci]; 
     if (!dcomp_.active(id)) continue; 
     const QString label = ValueIDWrapper(id).shortName(); 
     QLOG("Active value: " << label); 

     mapwin_->setValueID(id); 
     emit mapIndexUpdate(itemidx); 
     emit mapFit(); 
     emit renderWindow(&painter); 

     const QString exportpath = dirPath_ + "/" + item->filename(0).remove(".bmp", Qt::CaseSensitive) + "_" + label + ".png"; 
     winimage.save(exportpath); 
    } 

    emit makeProgress(); 
    QLOGDEC; 
} 

я сделал с помощью непосредственно излучающих сигнал графического интерфейса нити (Испустите RenderWindow) Который только делает следующее:

void MapWindow::renderOn(QPainter *image) 
{ 
    render(image, QPoint(), QRegion(), QWidget::DrawChildren); 
} 

К сожалению, когда я запускаю это код i получает QT ASSERT: [окно ошибки] [1] после извлечения сигнала. Есть ли что-то, что может пойти не так, когда я пытаюсь привлечь QWidget к QImage?

Весь CallStack на ASSERT (С этой информацией я сделал вывод, что это проблема с методом renderOn, так как это последний перед исключением):

Qt5Cored.dll!qt_message_fatal(QtMsgType __formal, const QMessageLogContext & context, const QString & message) Line 1571 C++ 
Qt5Cored.dll!QMessageLogger::fatal(const char * msg, ...) Line 781 C++ 
Qt5Cored.dll!qt_assert(const char * assertion, const char * file, int line) Line 2967 C++ 
Qt5Widgetsd.dll!QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QRectF & rect, Qt::SortOrder order, bool onlyTopLevelItems) Line 379 C++ 
Qt5Widgetsd.dll!QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const QRectF & rect, Qt::SortOrder order) Line 535 C++ 
Qt5Widgetsd.dll!QGraphicsScenePrivate::drawItems(QPainter * painter, const QTransform * const viewTransform, QRegion * exposedRegion, QWidget * widget) Line 4689 C++ 
Qt5Widgetsd.dll!QGraphicsView::paintEvent(QPaintEvent * event) Line 3540 C++ 
Qt5Widgetsd.dll!QWidget::event(QEvent * event) Line 8831 C++ 
Qt5Widgetsd.dll!QFrame::event(QEvent * e) Line 540 C++ 
Qt5Widgetsd.dll!QAbstractScrollArea::viewportEvent(QEvent * e) Line 1200 C++ 
Qt5Widgetsd.dll!QGraphicsView::viewportEvent(QEvent * event) Line 2963 C++ 
Qt5Widgetsd.dll!QAbstractScrollAreaPrivate::viewportEvent(QEvent * event) Line 102 C++ 
Qt5Widgetsd.dll!QAbstractScrollAreaFilter::eventFilter(QObject * o, QEvent * e) Line 118 C++ 
Qt5Cored.dll!QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject * receiver, QEvent * event) Line 1072 C++ 
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3712 C++ 
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3681 C++ 
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 965 C++ 
>Qt5Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 227 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::sendPaintEvent(const QRegion & toBePainted) Line 5628 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5569 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5761 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5619 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5761 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5748 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5748 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5748 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5619 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecursive(QPaintDevice * pdev, const QList<QObject *> & siblings, int index, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5761 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev, const QRegion & rgn, const QPoint & offset, int flags, QPainter * sharedPainter, QWidgetBackingStore * backingStore) Line 5619 C++ 
Qt5Widgetsd.dll!QWidgetPrivate::render(QPaintDevice * target, const QPoint & targetOffset, const QRegion & sourceRegion, QFlags<enum QWidget::RenderFlag> renderFlags) Line 5705 C++ 
Qt5Widgetsd.dll!QWidget::render(QPainter * painter, const QPoint & targetOffset, const QRegion & sourceRegion, QFlags<enum QWidget::RenderFlag> renderFlags) Line 5145 C++ 
Qt5Widgetsd.dll!QWidget::render(QPaintDevice * target, const QPoint & targetOffset, const QRegion & sourceRegion, QFlags<enum QWidget::RenderFlag> renderFlags) Line 5068 C++ 
ccigui.exe!MapWindow::renderOn(QImage * image) Line 453 C++ 
ccigui.exe!MapWindow::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 475 C++ 
Qt5Cored.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 487 C++ 
Qt5Cored.dll!QObject::event(QEvent * e) Line 1239 C++ 
Qt5Widgetsd.dll!QWidget::event(QEvent * event) Line 9105 C++ 
Qt5Widgetsd.dll!QMdiSubWindow::event(QEvent * event) Line 2917 C++ 
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3716 C++ 
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3681 C++ 
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 965 C++ 
Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 224 C++ 
Qt5Cored.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1593 C++ 
Qt5Cored.dll!QEventDispatcherWin32::sendPostedEvents() Line 1242 C++ 
qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 84 C++ 
Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned __int64 wp, __int64 lp) Line 416 C++ 
[External Code] 
Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 818 C++ 
qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 74 C++ 
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 129 C++ 
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 204 C++ 
Qt5Widgetsd.dll!QDialog::exec() Line 542 C++ 
ccigui.exe!Corr2DProject::handle_exportShow(int type, int seqidx) Line 387 C++ 
ccigui.exe!CCIGui::slot_anal_exportClicked() Line 1324 C++ 
ccigui.exe!CCIGui::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 464 C++ 
Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Line 3715 C++ 
Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3579 C++ 
Qt5Widgetsd.dll!QAbstractButton::clicked(bool _t1) Line 304 C++ 
Qt5Widgetsd.dll!QAbstractButtonPrivate::emitClicked() Line 536 C++ 
Qt5Widgetsd.dll!QAbstractButtonPrivate::click() Line 528 C++ 
Qt5Widgetsd.dll!QAbstractButton::mouseReleaseEvent(QMouseEvent * e) Line 1133 C++ 
Qt5Widgetsd.dll!QWidget::event(QEvent * event) Line 8679 C++ 
Qt5Widgetsd.dll!QAbstractButton::event(QEvent * e) Line 1090 C++ 
Qt5Widgetsd.dll!QPushButton::event(QEvent * e) Line 674 C++ 
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3716 C++ 
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3276 C++ 
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 965 C++ 
Qt5Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 227 C++ 
Qt5Widgetsd.dll!QApplicationPrivate::sendMouseEvent(QWidget * receiver, QMouseEvent * event, QWidget * alienWidget, QWidget * nativeWidget, QWidget * * buttonDown, QPointer<QWidget> & lastMouseReceiver, bool spontaneous) Line 2770 C++ 
Qt5Widgetsd.dll!QWidgetWindow::handleMouseEvent(QMouseEvent * event) Line 556 C++ 
Qt5Widgetsd.dll!QWidgetWindow::event(QEvent * event) Line 211 C++ 
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3716 C++ 
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3160 C++ 
Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 965 C++ 
Qt5Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 227 C++ 
Qt5Guid.dll!QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent * e) Line 1792 C++ 
Qt5Guid.dll!QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e) Line 1582 C++ 
Qt5Guid.dll!QWindowSystemInterface::sendWindowSystemEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 626 C++ 
qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 85 C++ 
Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned __int64 wp, __int64 lp) Line 416 C++ 
[External Code] 
Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 818 C++ 
qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 74 C++ 
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 129 C++ 
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 204 C++ 
Qt5Cored.dll!QCoreApplication::exec() Line 1229 C++ 
Qt5Guid.dll!QGuiApplication::exec() Line 1528 C++ 
Qt5Widgetsd.dll!QApplication::exec() Line 2977 C++ 
ccigui.exe!main(int argc, char * * argv) Line 41 C++ 
ccigui.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 113 C++ 
[External Code] 
+0

Используйте отладчик и проверить, где делает ASSERT пришел из –

+0

Добавлено стеком вызовов с моим комментарием – Dario3d

ответ

0

Есть что-нибудь, что может пойти не так, когда Я пытаюсь привлечь QWidget к QImage?

Да, есть. documentation для визуализации перегрузки, принимающей художника, четко указывает, что художник должен быть активным, что означает, что его следует использовать только во время события рисования.

Рассмотрите возможность использования другой перегрузки, которая принимает QPaintDevice.

+0

Ранее я использовал QImage непосредственно, который вытекает из QPaintDevice, но получил тот же самый эффект – Dario3d

+0

Ваш код и трассировку стека, кажется, не идут рука об руку , В коде используется 'renderWindow (& painter)', но трассировка стека имеет 'renderOn (QImage * image)' – Thomas

+0

Вы находитесь в 'sendPostedEvents', вы инициировали рендеринг в другом потоке? Если это так, то это будет проблемой, особенно. поскольку сигнал содержит QObject. – Thomas