2016-11-27 1 views
1

Я пытаюсь renderQWidget на QPrinter устройстве без блокировки GUI:Печать QWidget (визуализация) за пределами GUI поток

Моего метода печати выглядит следующим образом:

void MyClass::print() { 
    QPrinter *printer = new QPrinter(QPrinter::HighResolution); 
    printer->setPageSize(QPrinter::A5); 
    printer->setPageOrientation(QPageLayout::Portrait); 
    printer->setColorMode(QPrinter::Color); 
    QPrintDialog *dialog = new QPrintDialog(printer); 

    if (dialog->exec() == QDialog::Accepted) { 
     MyWidget *_widget = new MyWidget(/* args */); 

     QPainter *painter = new QPainter; 
     painter->begin(printer); 
     double xscale = printer->pageRect().width()/double(_widget ->width()); 
     double yscale = printer->pageRect().height()/double(_widget ->height()); 
     double scale = qMin(xscale, yscale); 
     _widget ->setMinimumWidth((printer->pageRect().width()/scale)); 
     _widget ->setMinimumHeight(printer->pageRect().height()/scale); 
     painter->translate(printer->paperRect().x() + printer->pageRect().width()/2, printer->paperRect().y() + printer->pageRect().height()/2); 
     painter->scale(scale, scale); 
     painter->translate(-_widget ->width()/2, -_widget ->height()/2); 
     _widget ->render(painter); 
     painter->end(); 
    } 
    emit done(); 
} 

С помощью этой функции I имеет около 1-2 сек состояния блока, так что я хочу использовать QThread для этого вопроса Но Qt Doc говорит:

Хотя QObject является reentran t, классы GUI, в частности QWidget и , все его подклассы не являются реентерабельными. Их можно использовать только с основной резьбы . Как отмечалось ранее, QCoreApplication :: exec() также должен быть вызван из этого потока.

А также:

На практике невозможно использовать классы GUI в других потоках , чем основной поток легко можно обойти, поставив трудоемких операций в отдельном потоке и отображение результатов на экране в главном потоке, когда рабочий поток закончил

Я изменил Mandelbrot Example но т здесь нечего показывать на экране в моем случае. мой виджет должен быть обработан (отнимает много времени) и отправляется на принтер, это все.

Итак, у вас есть что-то в виду для моей ситуации?

+3

1) Где он точно блокируется? 2) Вы не можете прикоснуться к QWidget из потока, отличного от GUI, когда-либо. – peppe

+0

@ peppe.1.С точки, где мы нажимаем кнопку печати QPrintDialog до тех пор, пока она не будет отправлена ​​на принтер. На сетевом принтере это займет около 1 секунды, а также MyWidget не является таким сложным – IMAN4K

+2

Один из вариантов - изменить '_widget' так что он не нарисован напрямую, а на «QImage», а затем отображает это изображение. Затем вы можете извлечь это изображение из этого слота' и отправить копию в поток, который затем распечатает изображение. Еще один вариант - переместить код рисования виджета в класс, который использует 'QPainter', тогда поток печати может создать экземпляр нового объекта этого класса и использовать его так же, как виджет. –

ответ

1

Если виджет paintEvent не делает много вычислений, то будет очень быстро отобразить виджет на QPicture. A QPicture - это всего лишь запись всех вызовов художника. Затем вы можете воспроизвести их на принтере одновременно.

В качестве альтернативы вы можете убедиться, что виджет не используется из основного потока (оставаясь невидимым и не имея родителя), и тогда нормально звонить render из любого потока.

+0

Так жаль слишком поздно ответить. вот ваше предложение, основанное на 'QPicture': http://pastebin.com/xGrj4Ykd, но результат печати небольшой и загроможденный :(так что создание объекта' QPrinter' является основной проблемой и блокирует мой GUI, есть ли другой способ обхода? – IMAN4K

+0

У вас есть полный контроль над масштабированием результата. Масштабируйте его так, как вы пожелаете :) –

Смежные вопросы