Results 1 to 4 of 4

Thread: QWidget::setMask: bug &/or help for workaround

  1. #1
    Join Date
    Mar 2008
    Posts
    5
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default QWidget::setMask: bug &/or help for workaround

    Hi,

    I'm working on a set of classes implementing various button shapes that can be re-oriented (rotated & translated) for various set of layout (eg table, circles etc..)
    In order to do this, the classes inherit from QPushButton and the paintButton method is reimplemented.

    Since only the shape of the button (ellipse, trapezoid etc..) should be active when the mouse goes over it etc... and since the button can be rotated on itself to arrange it on a layout, I'm making use of setMask function to make only the shape of the button visible.

    This approach works fine for rectangle, trapezoid shapes but for circle or ellipse shapes the application become extremely slow and the button have some hatched marks (see attached snapshots). The problem clearly come from setMask since when commented out the app. runs fine and the buttons look ok.

    I'm using Qt 4.3.0 and also tried with 4.4.0 in case it was a bug and got fixed, but the problem remain.

    Could anyone help me to determine if I'm doing something wrong (see attached code snippet)
    or if this is a Qt issue in which case any advice/suggestion on how to workaround this without loosing the functionality and a smooth running app. would be more than welcome.

    One possible workaround would be not to not use a mask but use a function that figure out if the mouse is within the button shape boundaries. Unfortunately, this would cause problem when the button are rotated and placed onto a layout due to the overlap in the QWidget rectangle. So it doesn't seem that this approach would workout.

    Thanks in advance for the help.
    Anyes





    Qt Code:
    1. //__________________________________________________________________________________________________
    2. void ShapedButtonEllipse::paintButton(QPaintEvent* )
    3. {
    4. updateButtonSize();
    5.  
    6. QPointF center = QPointF(width()/2., height()/2.);
    7.  
    8. QStylePainter painter(this);
    9. painter.setRenderHint(QPainter::Antialiasing);
    10.  
    11. painter.save();//save the painter state
    12. painter.translate(center); //translate coordinate system to center of shape
    13.  
    14. /*
    15.   Test for state changes
    16.   */
    17. QColor button_color;
    18. if(this->isEnabled())
    19. {
    20. m_hovered ? button_color = b_highlight : button_color = b_color;
    21. if(m_pressed)
    22. button_color = b_highlight.darker(250);
    23. }
    24. else
    25. button_color = QColor(50, 50, 50);
    26.  
    27. /*
    28.   Rotate painter wrt to button center if the button has been rotated
    29.   */
    30. if(rot_angle != 0)
    31. painter.rotate(-rot_angle);
    32.  
    33. /*
    34.   Draw the button
    35.   */
    36. painter.setPen(QPen(QBrush(Qt::black), bw, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); //button outline
    37. QLinearGradient gradient(0., 0., 0., height()); //button inside color gradient
    38. gradient.setColorAt(0., button_color);
    39. gradient.setSpread(QGradient::PadSpread);
    40. painter.setBrush(gradient);
    41.  
    42. QPainterPath outline;
    43. outline.addEllipse(-s_width/2, -s_height/2, s_width, s_height); //button outline shape
    44.  
    45. /*
    46.   Define visible/active region (add 2pixel extra all around)
    47.   */
    48. const qreal b = bw/2 + 4;
    49. QRegion maskedRegion((int)(-s_width/2 -b ), (int)(-s_height/2 -b ),
    50. (int)( s_width +b*2), (int)( s_height +b*2), QRegion::Ellipse);
    51. if (rot_angle != 0)
    52. {
    53. QMatrix matrix;
    54. matrix.rotate(-rot_angle);
    55. maskedRegion = maskedRegion * matrix;
    56. maskedRegion.translate(center.toPoint());
    57. }
    58. else
    59. {
    60. maskedRegion.translate((int)center.x(),(int)center.y());
    61. }
    62.  
    63. setMask(maskedRegion); //Funny looking after masking, very slow ????
    64. painter.drawPath(outline);
    65.  
    66. painter.restore();
    67.  
    68. /*
    69.   Add button text if any
    70.   */
    71. QString text = this->text();
    72. if(!text.isNull())
    73. {
    74. QFont font = this->font();
    75. painter.setFont(font);
    76. painter.setPen(t_color);
    77. painter.setOpacity(1.0);
    78. painter.drawText(0, 0, width(), height(), Qt::AlignCenter, text);
    79. }
    80.  
    81. }
    To copy to clipboard, switch view to plain text mode 
    Attached Images Attached Images
    Last edited by wysota; 22nd May 2008 at 11:12. Reason: Changed [quote] to [code]

  2. #2
    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: QWidget::setMask: bug &/or help for workaround

    What do you need the mask for here? Just paint the button and calculate the hit shape, should be very easy...

  3. #3
    Join Date
    Mar 2008
    Posts
    5
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: QWidget::setMask: bug &/or help for workaround

    Hi,

    Am I understanding correctly that what you are suggesting is to re-implement in whatever method tells the QWidget that the mouse is over it, the active/visible region to the given shape (which by default the QWidget::geometry(), ie rectangle containing the button shape)
    How would one do that (ie which method(s) would need to be re-written) ?

    What would happen in the case where a button (the part return by QWidget::geometry but not the active region) is on top of the active region of another button and the mouse is moved over the active region of the bottom button? Wouldn't it be the QWidget on top that would receive the click?

    Thanks
    -a

  4. #4
    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: QWidget::setMask: bug &/or help for workaround

    Quote Originally Posted by ataffard View Post
    How would one do that (ie which method(s) would need to be re-written) ?
    mouse{Press,Release}Event().

    Wouldn't it be the QWidget on top that would receive the click?
    Yes, it would. If it would ignore it, the click would be propagated to parent and not to the other widget. If you want to retain the "clickability" of the other button you have to do some event passing in the parent or use QGraphicsView instead of widgets, it might be a good choice in your situation.

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.