Results 1 to 9 of 9

Thread: QPainter.fillRect not filling what I tell it to

  1. #1
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Exclamation QPainter.fillRect not filling what I tell it to

    I'm trying to do the simplest of painting using a QPainter but I'm running into one hell of an oddity. Here's some example PyQt code which demonstrates the problem

    When the line edit has focus, the background should be red. when it doesnt have focus the background should be blue. Very simple... but it doesnt work. You can toss print statements in there, and you'll see that fillRect is being called every time focus changes.

    Here's the kicker, if you resize it, it repaints using the correct color

    Qt Code:
    1. from PyQt4 import QtGui
    2. from PyQt4.QtCore import Qt
    3.  
    4. class MyWidget(QtGui.QWidget):
    5. def __init__(self, parent=None):
    6. QtGui.QWidget.__init__(self, parent)
    7. self.lineedit = QtGui.QLineEdit(self)
    8. self.button = QtGui.QPushButton(self)
    9. layout = QtGui.QVBoxLayout(self)
    10. layout.addWidget(self.lineedit)
    11. layout.addWidget(self.button)
    12. def paintEvent(self, event):
    13. painter = QtGui.QPainter(self)
    14. if self.lineedit.hasFocus():
    15. painter.fillRect(self.rect(), Qt.red)
    16. else:
    17. painter.fillRect(self.rect(), Qt.blue)
    18.  
    19. w = MyWidget()
    20. w.show()
    To copy to clipboard, switch view to plain text mode 

    Any idea?

  2. #2
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: QPainter.fillRect not filling what I tell it to

    The following code works in C++:
    Qt Code:
    1. void Widget::paintEvent ( QPaintEvent * event ) {
    2. QPainter painter;
    3. painter.begin(this);
    4. if(lineEdit->hasFocus()) painter.fillRect(rect(), QBrush(Qt::red));
    5. else painter.fillRect(rect(), QBrush(Qt::blue));
    6. painter.end();
    7. update();
    8. }
    To copy to clipboard, switch view to plain text mode 
    I got the same results as you in C++ without painter.begin(), painter.end() and update(). When I tried plugging them into your program it didn't change anything, but I don't know much about Python.

  3. The following user says thank you to norobro for this useful post:

    chezifresh (14th January 2011)

  4. #3
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QPainter.fillRect not filling what I tell it to

    It does repaint correctly in Python too, however, it dramatically slows things down because calling update() from the paintEvent() is nearly a recursive call.
    I'm sure I can find a way to only call update() one time after focus changes. Too bad an update call in focusOutEvent doesnt do it.

    here's what I added

    Qt Code:
    1. void Widget::paintEvent ( QPaintEvent * event ) {
    2. QPainter painter;
    3. painter.begin(this);
    4. if(lineEdit->hasFocus()) painter.fillRect(rect(), QBrush(Qt::red));
    5. else painter.fillRect(rect(), QBrush(Qt::blue));
    6. painter.end();
    7.  
    8. // New Code Here
    9. if(lineEdit->hasFocus() != _lineEditHadFocus) {
    10. _lineEditHadFocus = lineEdit->hasFocus();
    11. update();
    12. }
    13. }
    To copy to clipboard, switch view to plain text mode 

  5. #4
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: QPainter.fillRect not filling what I tell it to

    Also since paintEvent() gets called so often, you could put any tests & update() in a slot:
    Qt Code:
    1. Widget::Widget(QWidget *parent) :
    2. QWidget(parent), _brush(Qt::red)
    3. {
    4. ...
    5. connect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(changedFocus(QWidget*,QWidget*)));
    6. }
    7.  
    8. void Widget::changedFocus(QWidget *old,QWidget *now){
    9. Q_UNUSED(old);
    10. if(QString(now->metaObject()->className())=="QLineEdit") _brush.setColor(Qt::red);
    11. else _brush.setColor(Qt::blue);
    12. update();
    13. }
    14.  
    15. void Widget::paintEvent ( QPaintEvent * event ) {
    16. Q_UNUSED(event);
    17. QPainter painter;
    18. painter.begin(this);
    19. painter.fillRect(rect(), _brush);
    20. painter.end();
    21. }
    To copy to clipboard, switch view to plain text mode 

  6. #5
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QPainter.fillRect not filling what I tell it to

    I'm not sure if this is better or not but here's what I ended up with:

    Qt Code:
    1. Widget::Widget(QWidget *parent) :
    2. QWidget(parent), _brush(Qt::red)
    3. {
    4. ...
    5. _lineEdit->installEventFilter(this);
    6. }
    7.  
    8. void Widget::eventFilter(QObject *obj, QEvent * event){
    9. if(obj == _lineEdit && (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut))
    10. update();
    11. return False;
    12. }
    To copy to clipboard, switch view to plain text mode 

    I also ended up changing the widget around a bit, now its a scroll area with a custom viewport which has line edit inside of it, so I'm not sure if this works with my original setup, either way, these all appear to work for various problems

  7. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QPainter.fillRect not filling what I tell it to

    A cleaner approach would be to raise/clear a flag in the event filter so that the widget doesn't have to query its child during the paint event. Still it's not clear for me why you want to paint this widget's background in this situation. I could understand painting the line edit's background but not what you do now. And if you just want to add a button to the line edit, you can do it easier - subclass the line edit, set a margin for its contents and place a button in the area of the margin. Then you end up with QLineEdit being your main widget (and keeping its whole API) and you can colour just the line edit.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #7
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QPainter.fillRect not filling what I tell it to

    So I'm trying to implement a tag entry widget. You can check out this post for more details: http://www.qtcentre.org/threads/3752...ng-a-line-edit

    What I have is a scroll area, a custom viewport, a bunch of custom 'tag' widgets, and a line edit with no frame, the line edit also acts as a focus proxy for the scroll area. The trick is I want the whole widget to look like a normal line edit and for the most part act like a normal line edit. The problem I ran into was the focus frame. When the line edit receives focus, or loses focus the scroll area's focus rect isnt repainted. So if you tab from my tag line edit to another line edit, the focus rectangle will be on both the tag line edit and the currently focused line edit. Bottom line, the focus frame wasn't behaving correctly on the scroll area.

    When I started the post I wasn't using a scroll area I was drawing the entire widget myself by using QStyle::drawPrimitive, which still exhibits the same problem as above. When the focus proxy gets/loses focus, the parent widget gets a paintEvent and I'm able to modify my QStyleOptionFrame to paint the frame with or without focus but its almost as if the paint method (or drawPrimitive method in this case) was ignored. The first example I posted was just a dead simple way to show what was happening. If you throw some print statements in the paintEvent when choosing bg colors you'll see what I mean.

    Anyway, I have a functioning tag widget, I like it, but I've implemented a workaround, not necessarily a solution. That is unless there is a good, documented reason why my fillRect in the first example doesnt work. Otherwise, this seems like a bug to me. I'd love to understand why the example in my original post didnt work, it was a huge time sink, but I have a workaround.

    In case others aren't PyQt4 users here's the same example in C++

    Qt Code:
    1. #include <QtGui>
    2. #include <iostream>
    3.  
    4. class Widget : public QWidget
    5. {
    6. Q_OBJECT
    7. public:
    8. Widget(QWidget * parent);
    9. private:
    10. void paintEvent(QPaintEvent * event);
    11. QLineEdit * _lineEdit;
    12. QPushButton * _button;
    13. QVBoxLayout * _layout;
    14. };
    15.  
    16. Widget::Widget(QWidget * parent) : QWidget(parent)
    17. {
    18. _lineEdit = new QLineEdit(this);
    19. _button = new QPushButton(this);
    20. _layout = new QVBoxLayout(this);
    21. _layout->addWidget(_lineEdit);
    22. _layout->addWidget(_button);
    23. }
    24.  
    25. void Widget::paintEvent ( QPaintEvent * event ) {
    26. QPainter painter;
    27. painter.begin(this);
    28. if(_lineEdit->hasFocus()) {
    29. painter.fillRect(rect(), QBrush(Qt::red));
    30. std::cerr<<"Line edit has focus, bg should be red"<<std::endl;
    31. }
    32. else {
    33. painter.fillRect(rect(), QBrush(Qt::blue));
    34. std::cerr<<"Line edit does NOT have focus, bg should be blue"<<std::endl;
    35. }
    36. painter.end();
    37. }
    To copy to clipboard, switch view to plain text mode 

  9. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QPainter.fillRect not filling what I tell it to

    To be honest your "tag widget" is an obvious candidate for a QAbstractItemView subclass or even for a QListView subclass. If you just use QListView then all you need is a custom delegate for drawing your tags and editing the tag.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. The following user says thank you to wysota for this useful post:

    chezifresh (20th January 2011)

  11. #9
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QPainter.fillRect not filling what I tell it to

    Had I thought of that when I started I probably would have gone that route I ended up implementing the QFlowLayout and using that in a scroll area. I guess the QListView already does that when you put it in icon mode. Good call.

Similar Threads

  1. FillRect with text
    By paolom in forum Qt Programming
    Replies: 4
    Last Post: 10th December 2010, 08:32
  2. fillRect does not display anything?
    By Ishmael in forum Newbie
    Replies: 5
    Last Post: 30th September 2009, 20:03
  3. problem in painter fillRect
    By wagmare in forum Qt Programming
    Replies: 1
    Last Post: 27th May 2009, 13:43
  4. Fading effect on QPainter fillrect()
    By smarinr in forum Qt Programming
    Replies: 7
    Last Post: 29th April 2008, 21:57
  5. how to show fillRect() using mouseEvents??
    By thomasjoy in forum Qt Programming
    Replies: 9
    Last Post: 31st August 2007, 14:30

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.