PDA

View Full Version : QPrintPreviewDialog doesn't update preview during execution



HappyCoder
22nd September 2015, 16:51
Hi,

i wrote a class PrintPreview to show a preview of of our data.
It could be a Plot or a Report (with more data and the plot).

I modified the QPrintPreviewDialog and add two QCheckBoxes

11387

The QCheckboxes are autoexclusive and with



checkPlot.setChecked( false or true );
checkReport.setChecked( true or false );

i can set the initial render style and everthing works fine.
I can see on first exec() either the "Plot" or the "Report".

When i switch between "Plot" and "Report" style using the
QCheckboxes inside the QToolBar during the QPrintPreviewDialog
is executed, it doesn't work.

If i click on "Report" my debug shows:


void PrintPreview::render(QPrinter*)
void PrintPreview::renderReport(QPrinter*)


If i click on "Plot" my debug shows:


void PrintPreview::render(QPrinter*)
void PrintPreview::renderPlot(QPrinter*)


Both rendering slots are called, but the preview itself is not updated.



// connection paintReqnested
connect( pPreview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(render(QPrinter*)));

void PrintPreview::render(QPrinter *printer)
{
qDebug() << Q_FUNC_INFO;
if( checkPlot.isChecked() )
renderPlot( printer );

if( checkReport.isChecked() )
renderReport( printer );
}


Can anybody help why QPrintPreviewDialog doesn't update preview?
Thx

d_stranz
23rd September 2015, 01:00
If you are invoking your print preview dialog as modal (eg. using QDialog::exec()), then it is running its own local event loop. The main app event loop processing is suspended while a modal dialog is active, so any signals sent via the main event loop will not be received until after the dialog is closed and control returns to the main event loop.

HappyCoder
23rd September 2015, 08:24
The interessting thing is:

1.) I have a rendered "Plot", i can see the "Plot" in preview window
2.) Now i click on the "Report", the "Report" will be rendered but not shown
3). The orientation is landscape, when i now switch to portrait or click again on landscape i can see the updated preview, my "Report"

Could this be a workaround to trigger the action?



QList<QToolBar *> qlPreviewToolbars = pPreview->findChildren<QToolBar *>();
QToolBar *previewToolbar = qlPreviewToolbars.at(0);
previewActions = previewToolbar->actions();




void PrintPreview::render(QPrinter *printer)
{
qDebug() << Q_FUNC_INFO;
if( checkPlot.isChecked() )
renderPlot( printer );

if( checkReport.isChecked() )
renderReport( printer );

// action for
previewActions.at(7)->trigger(); // now my app crashes at this point?
}


Added after 23 minutes:

I found workaround for this:



// constructor
connect( pPreview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(render(QPrinter*)));
connect( &checkPlot, SIGNAL(released()), this, SLOT(render()));
connect( &checkReport, SIGNAL(released()), this, SLOT(render()));
d_data->styleChanged = false;


void PrintPreview::render()
{
d_data->styleChanged = true;
emit pPreview->paintRequested( printer );
}

void PrintPreview::render(QPrinter *printer)
{
if(!d_data->styleChanged)
{
if( checkPlot.isChecked() )
renderPlot( printer );

if( checkReport.isChecked() )
renderReport( printer );
}
else
{
d_data->styleChanged = false;

// Workaround
// when orientation is landscape, trigger again landscape (this updates preview)
// when orientation is portait, trigger again portrait (this updates preview)
if(printer->orientation() == QPrinter::Landscape )
previewActions.at(8)->trigger(); // if landscape, trigger action landscape again and this emits later a paintRequest
else
previewActions.at(7)->trigger(); // if portrait, trigger action portrait again and this emits later a paintRequest
}
}

anda_skoa
23rd September 2015, 10:58
If you are invoking your print preview dialog as modal (eg. using QDialog::exec()), then it is running its own local event loop. The main app event loop processing is suspended while a modal dialog is active, so any signals sent via the main event loop will not be received until after the dialog is closed and control returns to the main event loop.
I don't think that is true, that would make most applications unusable.

The nested event loop used by QDialog::exec() just filters certain user event intended for the dialog's parent or the whole application (depending on the used modality setting).

Easily testable by having a timer update a label in the dialog's parent.
Not only will the timer event be processed, the label will also receive its paint event.

Cheers,
_

d_stranz
23rd September 2015, 17:58
I don't think that is true, that would make most applications unusable.

The nested event loop used by QDialog::exec() just filters certain user event intended for the dialog's parent or the whole application (depending on the used modality setting).

Easily testable by having a timer update a label in the dialog's parent.
Not only will the timer event be processed, the label will also receive its paint event.

Hmm, I suppose that's correct. I was thinking mostly in terms of user interaction with the parent and not "background" event processing. I guess I have never programmed a case such as the one you describe.

That implies that a modal QDialog could send signals that would update a progress bar in the parent widget, right?

anda_skoa
24th September 2015, 10:49
That implies that a modal QDialog could send signals that would update a progress bar in the parent widget, right?
Yes.
The signal doesn't used events in that case, but the paint event caused by the value change will be processed normally.

Cheers,
_