Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 6

Qt-interest Archive, July 2007
Repainting without erasure


Message 1 in thread

Hello,
I am very new to Qt. What I'm trying to do is simple: make a window with
methods for drawing and erasing lines and rectangles. Since speed is key,
and to do away with flickering, I need to be able to draw and redraw
specific rectangles or lines without repainting the entire widget. The
window class' member functions should be callable by client programs.

What I'm doing currently is, I have functions that change global 
line/rectangle dimension varialbles and then call repaint(const QRect &r),
repaint ( int x, int y, int w, int h ) or repaint ( const QRegion & rgn ).

The paintEvent function then does stuff according to whether certain 
global variables evaluate to true or false. The problem is that, even if I 
call repaint ( const QRegion & rgn ), it erases the entire window. For 
example, if I write these simple functions and call them for another 
program:

/*_________________________________________
      begin example snippet */

//a line is a actually a rectangle (for my own purposes)

void window::drawline(int x1,int y1,int x2,int y2,int r,int g,int b)
{
toDo = 1; //paintEvent checks this variable and draws a line if toDo == 2
xx1 = x1;
xx2 = x2;
yy1 = y1;
yy2 = y2;
color = QColor(r,g,b);
repaint(QRegion(xx1,yy1,xx2,yy2));
}


void window::drawrect(int x1,int y1,int x2,int y2,int r,int g,int b)
{
   toDo = 2;  //similarly, paintEvent draws a rect if toDo is == 3
   xx1 = x1;
   xx2 = x2;
   yy1 = y1;
   yy2 = y2;
   color = QColor(r,g,b);
   repaint(QRegion(xx1,yy1,xx2,yy2));
}

void DrawingWindow::paintEvent(QPaintEvent *)
{
   QPainter painter(this);
   switch (toDo)
     {case 3: //draw rect
       painter.setPen(Qt::NoPen);
       painter.setBrush(color);
       painter.drawRect(QRect(xx1,yy1,xx2,yy2));
       break;
      case 4: //eraseRect
       painter.eraseRect(QRectF(xx1,yy1,xx2,yy2));
       break;

    //......................

/* end example snippet 
_____________________________________________ */


If I call drawline() first then drawrect(), the line is erased and I can 
only see the rectangle. I don't want to erase anything unless the client 
program calls window.eraserect(). Is there a way to do this?

Thanks,
Ernest

--
 [ signature omitted ] 

Message 2 in thread

tried QWidget::setAttribute(Qt::WA_OpaquePaintEvent) ?
but you'll really have to paint the whole widget then (care about background 
etc.)

MIGHT be QGraphicsView has improved support for this functionality .. (but i 
really don't know)

If you only on X11, you can also abuse Qt::WA_PaintOutsidePaintEvent
(you can then write your own myRepaint() that operates without using 
paintevents, open a painter on the widget and paint it witout any erasure - 
but that's hackish ;)

if nothing else helps, you could try keeping an offscreen buffer (QPixmap) and 
map that onto the widget on paintevents (that's similar to the above 
solution, but works everywhere)

Thomas

Am Samstag, 28. Juli 2007 01:09 schrieb Ernest G Ngaruiya:
> Hello,
> I am very new to Qt. What I'm trying to do is simple: make a window with
> methods for drawing and erasing lines and rectangles. Since speed is key,
> and to do away with flickering, I need to be able to draw and redraw
> specific rectangles or lines without repainting the entire widget. The
> window class' member functions should be callable by client programs.
>
> What I'm doing currently is, I have functions that change global
> line/rectangle dimension varialbles and then call repaint(const QRect &r),
> repaint ( int x, int y, int w, int h ) or repaint ( const QRegion & rgn ).
>
> The paintEvent function then does stuff according to whether certain
> global variables evaluate to true or false. The problem is that, even if I
> call repaint ( const QRegion & rgn ), it erases the entire window. For
> example, if I write these simple functions and call them for another
> program:
>
> /*_________________________________________
>       begin example snippet */
>
> //a line is a actually a rectangle (for my own purposes)
>
> void window::drawline(int x1,int y1,int x2,int y2,int r,int g,int b)
> {
> toDo = 1; //paintEvent checks this variable and draws a line if toDo == 2
> xx1 = x1;
> xx2 = x2;
> yy1 = y1;
> yy2 = y2;
> color = QColor(r,g,b);
> repaint(QRegion(xx1,yy1,xx2,yy2));
> }
>
>
> void window::drawrect(int x1,int y1,int x2,int y2,int r,int g,int b)
> {
>    toDo = 2;  //similarly, paintEvent draws a rect if toDo is == 3
>    xx1 = x1;
>    xx2 = x2;
>    yy1 = y1;
>    yy2 = y2;
>    color = QColor(r,g,b);
>    repaint(QRegion(xx1,yy1,xx2,yy2));
> }
>
> void DrawingWindow::paintEvent(QPaintEvent *)
> {
>    QPainter painter(this);
>    switch (toDo)
>      {case 3: //draw rect
>        painter.setPen(Qt::NoPen);
>        painter.setBrush(color);
>        painter.drawRect(QRect(xx1,yy1,xx2,yy2));
>        break;
>       case 4: //eraseRect
>        painter.eraseRect(QRectF(xx1,yy1,xx2,yy2));
>        break;
>
>     //......................
>
> /* end example snippet
> _____________________________________________ */
>
>
> If I call drawline() first then drawrect(), the line is erased and I can
> only see the rectangle. I don't want to erase anything unless the client
> program calls window.eraserect(). Is there a way to do this?
>
> Thanks,
> Ernest
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/

-- 
 [ signature omitted ] 

Message 3 in thread

For some reason (I'm on X11), nothing is painted on the widget when I set
Qt::WA_PaintOutsidePaintEvent. I will try your last idea (QPixmap) and see 
if works.

Regards,
Ernest
On Sat, 28 Jul 2007, Thomas Lübking wrote:

> tried QWidget::setAttribute(Qt::WA_OpaquePaintEvent) ?
> but you'll really have to paint the whole widget then (care about background
> etc.)
>
> MIGHT be QGraphicsView has improved support for this functionality .. (but i
> really don't know)
>
> If you only on X11, you can also abuse Qt::WA_PaintOutsidePaintEvent
> (you can then write your own myRepaint() that operates without using
> paintevents, open a painter on the widget and paint it witout any erasure -
> but that's hackish ;)
>
> if nothing else helps, you could try keeping an offscreen buffer (QPixmap) and
> map that onto the widget on paintevents (that's similar to the above
> solution, but works everywhere)
>
> Thomas
>
> Am Samstag, 28. Juli 2007 01:09 schrieb Ernest G Ngaruiya:
>> Hello,
>> I am very new to Qt. What I'm trying to do is simple: make a window with
>> methods for drawing and erasing lines and rectangles. Since speed is key,
>> and to do away with flickering, I need to be able to draw and redraw
>> specific rectangles or lines without repainting the entire widget. The
>> window class' member functions should be callable by client programs.
>>
>> What I'm doing currently is, I have functions that change global
>> line/rectangle dimension varialbles and then call repaint(const QRect &r),
>> repaint ( int x, int y, int w, int h ) or repaint ( const QRegion & rgn ).
>>
>> The paintEvent function then does stuff according to whether certain
>> global variables evaluate to true or false. The problem is that, even if I
>> call repaint ( const QRegion & rgn ), it erases the entire window. For
>> example, if I write these simple functions and call them for another
>> program:
>>
>> /*_________________________________________
>>       begin example snippet */
>>
>> //a line is a actually a rectangle (for my own purposes)
>>
>> void window::drawline(int x1,int y1,int x2,int y2,int r,int g,int b)
>> {
>> toDo = 1; //paintEvent checks this variable and draws a line if toDo == 2
>> xx1 = x1;
>> xx2 = x2;
>> yy1 = y1;
>> yy2 = y2;
>> color = QColor(r,g,b);
>> repaint(QRegion(xx1,yy1,xx2,yy2));
>> }
>>
>>
>> void window::drawrect(int x1,int y1,int x2,int y2,int r,int g,int b)
>> {
>>    toDo = 2;  //similarly, paintEvent draws a rect if toDo is == 3
>>    xx1 = x1;
>>    xx2 = x2;
>>    yy1 = y1;
>>    yy2 = y2;
>>    color = QColor(r,g,b);
>>    repaint(QRegion(xx1,yy1,xx2,yy2));
>> }
>>
>> void DrawingWindow::paintEvent(QPaintEvent *)
>> {
>>    QPainter painter(this);
>>    switch (toDo)
>>      {case 3: //draw rect
>>        painter.setPen(Qt::NoPen);
>>        painter.setBrush(color);
>>        painter.drawRect(QRect(xx1,yy1,xx2,yy2));
>>        break;
>>       case 4: //eraseRect
>>        painter.eraseRect(QRectF(xx1,yy1,xx2,yy2));
>>        break;
>>
>>     //......................
>>
>> /* end example snippet
>> _____________________________________________ */
>>
>>
>> If I call drawline() first then drawrect(), the line is erased and I can
>> only see the rectangle. I don't want to erase anything unless the client
>> program calls window.eraserect(). Is there a way to do this?
>>
>> Thanks,
>> Ernest
>>
>> --
>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> "unsubscribe" in the subject or the body. List archive and information:
>> http://lists.trolltech.com/qt-interest/
>
> -- 
> Fear... Fear attracts the fearfull.
> The strong. The weak. The innocent. The corrupt.
> Fear... Fear is my ally!
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>

Message 4 in thread

upps, you ended up in spam suspect...

attached is a small app that paints accumulative using  
Qt::WA_PaintOutsidePaintEvent

Thomas

Am Sonntag, 29. Juli 2007 15:06 schrieb Ernest G Ngaruiya:
> For some reason (I'm on X11), nothing is painted on the widget when I set
> Qt::WA_PaintOutsidePaintEvent. I will try your last idea (QPixmap) and see
> if works.
>
> Regards,
> Ernest
>
> On Sat, 28 Jul 2007, Thomas Lübking wrote:
> > tried QWidget::setAttribute(Qt::WA_OpaquePaintEvent) ?
> > but you'll really have to paint the whole widget then (care about
> > background etc.)
> >
> > MIGHT be QGraphicsView has improved support for this functionality ..
> > (but i really don't know)
> >
> > If you only on X11, you can also abuse Qt::WA_PaintOutsidePaintEvent
> > (you can then write your own myRepaint() that operates without using
> > paintevents, open a painter on the widget and paint it witout any erasure
> > - but that's hackish ;)
> >
> > if nothing else helps, you could try keeping an offscreen buffer
> > (QPixmap) and map that onto the widget on paintevents (that's similar to
> > the above solution, but works everywhere)
> >
> > Thomas
> >
> > Am Samstag, 28. Juli 2007 01:09 schrieb Ernest G Ngaruiya:
> >> Hello,
> >> I am very new to Qt. What I'm trying to do is simple: make a window with
> >> methods for drawing and erasing lines and rectangles. Since speed is
> >> key, and to do away with flickering, I need to be able to draw and
> >> redraw specific rectangles or lines without repainting the entire
> >> widget. The window class' member functions should be callable by client
> >> programs.
> >>
> >> What I'm doing currently is, I have functions that change global
> >> line/rectangle dimension varialbles and then call repaint(const QRect
> >> &r), repaint ( int x, int y, int w, int h ) or repaint ( const QRegion &
> >> rgn ).
> >>
> >> The paintEvent function then does stuff according to whether certain
> >> global variables evaluate to true or false. The problem is that, even if
> >> I call repaint ( const QRegion & rgn ), it erases the entire window. For
> >> example, if I write these simple functions and call them for another
> >> program:
> >>
> >> /*_________________________________________
> >>       begin example snippet */
> >>
> >> //a line is a actually a rectangle (for my own purposes)
> >>
> >> void window::drawline(int x1,int y1,int x2,int y2,int r,int g,int b)
> >> {
> >> toDo = 1; //paintEvent checks this variable and draws a line if toDo ==
> >> 2 xx1 = x1;
> >> xx2 = x2;
> >> yy1 = y1;
> >> yy2 = y2;
> >> color = QColor(r,g,b);
> >> repaint(QRegion(xx1,yy1,xx2,yy2));
> >> }
> >>
> >>
> >> void window::drawrect(int x1,int y1,int x2,int y2,int r,int g,int b)
> >> {
> >>    toDo = 2;  //similarly, paintEvent draws a rect if toDo is == 3
> >>    xx1 = x1;
> >>    xx2 = x2;
> >>    yy1 = y1;
> >>    yy2 = y2;
> >>    color = QColor(r,g,b);
> >>    repaint(QRegion(xx1,yy1,xx2,yy2));
> >> }
> >>
> >> void DrawingWindow::paintEvent(QPaintEvent *)
> >> {
> >>    QPainter painter(this);
> >>    switch (toDo)
> >>      {case 3: //draw rect
> >>        painter.setPen(Qt::NoPen);
> >>        painter.setBrush(color);
> >>        painter.drawRect(QRect(xx1,yy1,xx2,yy2));
> >>        break;
> >>       case 4: //eraseRect
> >>        painter.eraseRect(QRectF(xx1,yy1,xx2,yy2));
> >>        break;
> >>
> >>     //......................
> >>
> >> /* end example snippet
> >> _____________________________________________ */
> >>
> >>
> >> If I call drawline() first then drawrect(), the line is erased and I can
> >> only see the rectangle. I don't want to erase anything unless the client
> >> program calls window.eraserect(). Is there a way to do this?
> >>
> >> Thanks,
> >> Ernest
> >>
> >> --
> >> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> >> "unsubscribe" in the subject or the body. List archive and information:
> >> http://lists.trolltech.com/qt-interest/
> >
> > --
> > Fear... Fear attracts the fearfull.
> > The strong. The weak. The innocent. The corrupt.
> > Fear... Fear is my ally!
> >
> > --
> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> > "unsubscribe" in the subject or the body. List archive and information:
> > http://lists.trolltech.com/qt-interest/

-- 
 [ signature omitted ] 

Attachment: painttest.tar.bz2
Description: application/tbz


Message 5 in thread

Hi Ernest,

> I am very new to Qt. What I'm trying to do is simple: make a window with
> methods for drawing and erasing lines and rectangles. Since speed is key,
> and to do away with flickering, I need to be able to draw and redraw
> specific rectangles or lines without repainting the entire widget. The
> window class' member functions should be callable by client programs.
> 
> What I'm doing currently is, I have functions that change global 
> line/rectangle dimension varialbles and then call repaint(const QRect &r),
> repaint ( int x, int y, int w, int h ) or repaint ( const QRegion & rgn ).
> 

You should not call repaint() if speed is important. Use update() with 
the same arguments instead.

> The paintEvent function then does stuff according to whether certain 
> global variables evaluate to true or false. The problem is that, even if I 
> call repaint ( const QRegion & rgn ), it erases the entire window. For 
> example, if I write these simple functions and call them for another 
> program:

Could you run the program with QT_FLUSH_PAINT=1 set in your environment 
and confirm that the entire window is repainted? Areas that are 
repainted will then be flushed with yellow.


-- 
 [ signature omitted ]