2016-11-27 1 views
1

ich ohne GUI Blockierung ein QWidget auf einem QPrinter Gerät render versuchen:Printing QWidget (machen), die außerhalb des GUI-Thread

Mein Druckverfahren wie folgt aussieht:

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(); 
} 

Mit dieser Funktion i haben ca. 1-2 sec Blockzustand so will ich QThread für dieses Problem verwenden, aber Qt Doc sagt:

Obwohl QObject ist reentran t, die GUI-Klassen, insbesondere QWidget und alle Unterklassen, sind nicht reentrant. Sie können nur aus dem Haupt-Thread verwendet werden. Wie bereits erwähnt, muss QCoreApplication :: exec() auch von diesem Thread aufgerufen werden.

Und auch:

In der Praxis ist die Unmöglichkeit, in anderen Threads GUI-Klassen als der Haupt-Thread leicht umgingen, indem sie zeitaufwändige Operationen in einem separaten Arbeitsthread werden kann und die Ergebnisse auf dem Bildschirm im Hauptthread anzuzeigen, wenn der Arbeiter-Thread

fertig ist habe ich geändert Mandelbrot Example aber t Hier ist nichts auf meinem Bildschirm zu sehen. mein Widget sollte gerendert werden (zeitraubende Operation) und an den Drucker gesendet werden, das ist alles.

Haben Sie also etwas für meine Situation im Kopf?

+3

1) Wo blockiert es genau? 2) Sie können ein QWidget niemals aus einem Nicht-GUI-Thread heraus berühren. – peppe

+0

@ peppe.1.Von dem Punkt, wo wir drücken QPrintDialog print button, bis es an den Drucker gesendet wird.auf einem Netzwerkdrucker dauert es etwa 1 Sekunde und auch MyWidget ist nicht so komplex – IMAN4K

+2

Eine Möglichkeit ist, die '_widget' so zu ändern dass es nicht direkt, sondern in ein 'QImage' zeichnet und dann dieses Bild anzeigt. Sie können dann das Bild von diesem Steckplatz abrufen und eine Kopie an einen Thread senden, der das Bild dann druckt. Eine weitere Möglichkeit ist, den Zeichnungscode des Widgets in eine Klasse zu verschieben, die einen 'QPainter' verwendet. Dann kann der Druck-Thread ein neues Objekt dieser Klasse instanziieren und es genau wie das Widget verwenden. –

Antwort

1

Wenn das Widget paintEvent nicht viel Berechnungen ausführt, dann wird es sehr schnell das Widget auf QPicture rendern. A QPicture ist nur eine Aufzeichnung aller Maleranrufe. Sie können sie dann auf einem Drucker in einem gleichzeitigen Job wiedergeben.

Alternativ können Sie sicherstellen, dass das Widget nicht aus dem Hauptthread verwendet wird (indem Sie unsichtbar bleiben und kein Elternteil haben), und dann ist es in Ordnung, render aus einem beliebigen Thread aufzurufen.

+0

Sorry für zu spät antworten. Hier ist Ihr Vorschlag basierend auf 'QPicture': http://pastebin.com/xGrj4Ykd, aber das Druckergebnis ist klein und überladen :(so wie die Erstellung' QPrinter' Objekt ist das Hauptproblem und blockiert meine GUI gibt es andere Workaround? – IMAN4K

+0

Sie haben die volle Kontrolle über die Skalierung des Ergebnisses, skalieren Sie es nach Ihren Wünschen :) –