PDA

View Full Version : passing a QPainter object to widgets



vratojr
11th January 2006, 10:52
Hello,
I'm writing a program that acts this way:
- I have a principal QWidget over which I create a QPainter,
- I draw on the widget,
- I pass the Painter to other widgets so I can use those widgets to draw on the principal one,
- Finally,in the principal widget,I call end() on the painter.

The program works properly but ends with a segmentation fault. I runned gdb and it sais that the problem was that it doesn't found qlist.h (quite strange I think).

However the output has no apparent problem:I can display the result of my painting on video and I can eventually draw it on a file. The problem arises when I try to convert the .ps image created with my program to a .pdf,in fact I obtain this error using dvipdf ( in fact I use the .ps file I create as an image in a latex text):

/usr/bin/dvipdf: line 40: 20896 Broken pipe exec dvips -q -f "$infile"
20897 Segmentation fault | gs $OPTIONS -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$outfile" $OPTIONS -c .setpdfwrite -

I'm sure it's not a problem of the latex file or of my dvipdf because if I do the same things but without passing the QPainter to other widgets,I have no problem.

What can I do?

thanks!

mcosta
11th January 2006, 11:17
Hi,

You can try to do something like



// Principal widget
void ChildWidget::myFunc(QPainter* painter)
{
painter->begin(parentWidget());
// Drawing
painter->end();
}


PS. If you use Qt 4.1 you can print to a PDF file directly using



printer.setPrinterMode(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);


PPS. Sorry for my very bad English.

PPPS. For vratojr: I'm italian like you. If you like you can write me in private post in Italian

jacek
11th January 2006, 13:09
- I draw on the widget,
- I pass the Painter to other widgets so I can use those widgets to draw on the principal one,
QCanvas does similar thing, so there shouldn't be any problems with this approach.

How do those widget draw themselves?


The program works properly but ends with a segmentation fault. I runned gdb and it sais that the problem was that it doesn't found qlist.h (quite strange I think).
Make sure you compile your application in debug mode (you should have "CONFIG += debug" in .pro file). Then run your application from gdb. When is crashes issue "bt" command to print the backtrace and post it here.

vratojr
11th January 2006, 14:28
How do those widget draw themselves?

Here is a brief description:


//Inside the Main widget's paintEvent:
QPainter painter;
painter.begin( graficoPaintDevice );
//drawing
assex = new AsseNumerico (/*options*/,painter,this);
assex.draw();
painter.end();

//stucture of the second widget
class AsseNumerico,public QWidget{
public:
AsseNumerico(....);
void draw(QPainter &painter);
private:
QPainter p;
};

AsseNumerico::AsseNumerico(/*options*/,QPainter &painter,QWidget *parent):QWidget(parent),p(painter){};

void AsseNumerico::draw(Qpainter &painter){
p.drawSomething();
}



Make sure you compile your application in debug mode (you should have "CONFIG += debug" in .pro file). Then run your application from gdb. When is crashes issue "bt" command to print the backtrace and post it here.

Well, first. I will explain better and briefly how the program works. I do some calculation to draw an istogram on screen and afterward I give the opportunity to print it.
If I display the istogram on screen WITHOUT trying to print it I got the the error:

*** glibc detected *** double free or corruption (!prev): 0x0825f648 ***

And, if i use the file in the .ps and then use dvipdf I got the error:
/usr/bin/dvipdf: line 40: 28347 Broken pipe exec dvips -q -f "$infile"
28348 Segmentation fault | gs $OPTIONS -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$outfile" $OPTIONS -c .setpdfwrite -
Segmentation fault

And this is the ouput from gdb:

*** glibc detected *** double free or corruption (!prev): 0x08252e38 ***

Program received signal SIGABRT, Aborted.
[Switching to Thread -1221314880 (LWP 31932)]
0xffffe410 in ?? ()
(gdb) bt
#0 0xffffe410 in ?? ()
#1 0xbfffed94 in ?? ()
#2 0x00000006 in ?? ()
#3 0x00007cbc in ?? ()
#4 0xb738c6e5 in raise () from /lib/tls/libc.so.6
#5 0xb738e049 in abort () from /lib/tls/libc.so.6
#6 0xb73c07ba in __fsetlocking () from /lib/tls/libc.so.6
#7 0xb73c6d9c in malloc_trim () from /lib/tls/libc.so.6
#8 0xb73c737a in free () from /lib/tls/libc.so.6
#9 0xb756a6f1 in operator delete () from /usr/lib/libstdc++.so.6
#10 0xb7bca5d7 in ~QPainterPrivate (this=0x82644b0) at qpainter_p.h:120
#11 0xb7bbe78a in ~QPainter (this=0x819629c) at painting/qpainter.cpp:635
#12 0x08081a4b in ~AsseRiferimento (this=0x8196238) at .moc/moc_assenumerico.cpp:77

jacek
11th January 2006, 15:24
*** glibc detected *** double free or corruption (!prev): 0x08252e38 ***

Program received signal SIGABRT, Aborted.
[...]
#12 0x08081a4b in ~AsseRiferimento (this=0x8196238) at .moc/moc_assenumerico.cpp:77
It seems that you delete memory twice. What happens in that AsseRiferimento destructor?

mcosta
11th January 2006, 15:25
Here is a brief description:


//Inside the Main widget's paintEvent:
QPainter painter;
painter.begin( graficoPaintDevice );
//drawing
assex = new AsseNumerico (/*options*/,painter,this);
assex.draw();
painter.end();

//stucture of the second widget
class AsseNumerico,public QWidget{
public:
AsseNumerico(....);
void draw(QPainter &painter);
private:
QPainter p;
};

AsseNumerico::AsseNumerico(/*options*/,QPainter &painter,QWidget *parent):QWidget(parent),p(painter){};

void AsseNumerico::draw(Qpainter &painter){
p.drawSomething();
}



Try to use QPainter pointer as function parameter instead o reference



AsseNumerico::AsseNumerico(/*options*/,QPainter* painter,QWidget *parent):QWidget(parent),p(painter){};


Using copy constructor you force the creation of a copy object and destruction of it. Passing pointer you don't.

vratojr
11th January 2006, 15:45
It seems that you delete memory twice. What happens in that AsseRiferimento destructor?

Nothing.
I didn't wrote code for the destructor.
should I?

jacek
11th January 2006, 15:56
Nothing.
I didn't wrote code for the destructor.
should I?
No, you don't have to write it. So the problem is probably because you create a copy that QPainter. Try what mcosta suggests.

mcosta
11th January 2006, 16:04
So the problem is probably because you create a copy that QPainter.

Qt Official Documentation says


QPainter::QPainter ( QPaintDevice * pd )
Constructs a painter that begins painting the paint device pd immediately.
This constructor is convenient for short-lived painters, e.g. in a paint event and should be used only once.

The constructor calls begin() for you and the QPainter destructor automatically calls end().


So, you must use QPainter pointer.

vratojr
11th January 2006, 16:27
You were right, I resolved doing that way.

Thank you very much boys!