Results 1 to 19 of 19

Thread: Creating Custom Ellipse Button

  1. #1
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Creating Custom Ellipse Button

    I tried this code then did QEllipseButton b; b.setText("woot"); b.show(); in a simple window of Qt, and it will not show the area. I tried r3, and r1, update,setting a background... but it wont make me a button with a different size.

    Like I would like to make an egg shaped button that works just like a pushbutton, but has a nice background image on it.

    Qt Code:
    1. class QEllipseButton : public QPushButton {
    2. public:
    3. QEllipseButton(QWidget * parent = 0): QPushButton(parent){
    4. }
    5. protected:
    6. void paintEvent ( QPaintEvent * event ){
    7. QRegion r1(QRect(200, 50, 500, 400), // r1: elliptic region
    8. QRegion::Ellipse);
    9. QRegion r2(QRect(200, 70, 90, 30)); // r2: rectangular region
    10. QRegion r3 = r1.intersected(r2); // r3: intersection
    11.  
    12. QPainter painter(this);
    13. painter.setClipping(true);
    14. painter.setClipRegion(r1);
    15. //QBrush brush(QColor(255,0,0,255));
    16. //painter.setBackground(brush);
    17. //update();
    18. }
    19. };
    To copy to clipboard, switch view to plain text mode 

    thx for help.

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Why don't you try QWidget::setMask( const QRegion& ).
    Using a painter to achieve this will probably not work, because the background of the widget is not (yet) transparent. You could first fill the widget rect with a transparent pixmap but it is better and easier to use QWidget::setMask.

    Regards

  3. #3
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Oh, and even if you subclass QPushButton, overriding paintEvent will not keep the push button behavior. If you like, you could call QPushButton:aintEvent in the paint event of your class( at the beginning ). But this could mess up things even more...

    In my opinnion, the best solution is to subclass QAbstractButton and custom draw your button in all the states ( pressed, normal, hovered, disabled, etc...). This allows more freedom in defining the look of your widget.

    Regards

  4. #4
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    Could you show any code examples of this?

  5. #5
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Unfortunately I do not have any examples, nor the time to create one . But it should be pretty straightforwards.

    You define an enum in your QAbstractButton subclass.
    Qt Code:
    1. typedef enum States
    2. {
    3. eStateNormal,
    4. eStatePressed,
    5. eStateHovered,
    6. eStateDisabled
    7. } States;
    To copy to clipboard, switch view to plain text mode 
    Then , add a State member in your class.
    The state switching depends on the user actions.
    Initially you start with eStateNormal.
    In mousePressEvent, if the button is Qt::LeftButton, the state is eStatePressed.
    In mouseMoveEvent, if no btns are pressed, the state is eStateHovered.
    In mouseReleaseEvent, if the previous state was eStatePressed, then switch to eStateNormal.

    After this, everything happens in paintEvent:
    Qt Code:
    1. void MyBtn::paintEvent( QPaintEvent* )
    2. {
    3. switch( mButtonState )
    4. {
    5. case eStateNormal:
    6. //Paint in this state
    7. break;
    8. case eStatePressed:
    9. //Paint in this state
    10. break;
    11. case eStateHovered:
    12. //Paint in this state
    13. break;
    14. case eStateDisabled:
    15. //Paint in this state
    16. break;
    17. }
    18. }
    To copy to clipboard, switch view to plain text mode 

    Actually, you should make pixmaps for all the states ( either external or you build them here ). It will make drawing faster.

    Regards

  6. #6
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    Yeah I don't think this is working:
    Qt Code:
    1. class QEllipseButton : public QAbstractButton {
    2. public:
    3. typedef enum States
    4. {
    5. eStateNormal,
    6. eStatePressed,
    7. eStateHovered,
    8. eStateDisabled
    9. } States;
    10. States m_ButtonState;
    11. QEllipseButton(QWidget * parent = 0): QAbstractButton(parent){
    12. m_ButtonState = eStateNormal;
    13. }
    14. protected:
    15. void mousePressEvent(QMouseEvent *event){
    16. if (event->button() == Qt::LeftButton) {
    17. m_ButtonState = eStatePressed;
    18. }
    19. }
    20. void mouseMoveEvent(QMouseEvent *event){
    21. if(event->buttons() & Qt::LeftButton) {
    22. m_ButtonState = eStateHovered;
    23. }
    24. }
    25. void mouseReleaseEvent(QMouseEvent *event){
    26. if(event->buttons() && m_ButtonState == eStatePressed){
    27. m_ButtonState = eStateNormal;
    28. }
    29. }
    30. void paintEvent ( QPaintEvent * event ){
    31. QRegion r1(QRect(200, 50, 500, 400), // r1: elliptic region
    32. QRegion::Ellipse);
    33. QRegion r2(QRect(200, 70, 90, 30)); // r2: rectangular region
    34. QRegion r3 = r1.intersected(r2); // r3: intersection
    35.  
    36. QPainter painter(this);
    37. QPixmap qpx;
    38. switch( m_ButtonState ){
    39. case eStateNormal:
    40. qpx.load(QString("JoinNormal.jpg"));
    41. break;
    42. case eStatePressed:
    43. qpx.load(QString("JoinPressed.jpg"));
    44. break;
    45. case eStateHovered:
    46. qpx.load(QString("JoinHover.jpg"));
    47. break;
    48. case eStateDisabled:
    49. qpx.load(QString("JoinNormal.jpg"));
    50. break;
    51. }
    52. QRectF target(10.0, 20.0, 80.0, 60.0);
    53. QRectF source(0.0, 0.0, 70.0, 40.0);
    54. painter.drawPixmap(target, qpx, source);
    55. painter.setClipping(true);
    56. painter.setClipRegion(r1);
    57. //QBrush brush(QColor(255,0,0,255));
    58. //painter.setBackground(brush);
    59. //update();
    60. }
    61. };
    To copy to clipboard, switch view to plain text mode 


    class QEllipseButton : public QAbstractButton {
    public:
    typedef enum States
    {
    eStateNormal,
    eStatePressed,
    eStateHovered,
    eStateDisabled
    } States;
    States m_ButtonState;
    QEllipseButton(QWidget * parent = 0): QAbstractButton(parent){
    m_ButtonState = eStateNormal;
    }
    protected:
    void mousePressEvent(QMouseEvent *event){
    if (event->button() == Qt::LeftButton) {
    m_ButtonState = eStatePressed;
    }
    }
    void mouseMoveEvent(QMouseEvent *event){
    if(event->buttons() & Qt::LeftButton) {
    m_ButtonState = eStateHovered;
    }
    }
    void mouseReleaseEvent(QMouseEvent *event){
    if(event->buttons() && m_ButtonState == eStatePressed){
    m_ButtonState = eStateNormal;
    }
    }
    void paintEvent ( QPaintEvent * event ){
    QRegion r1(QRect(200, 50, 500, 400), // r1: elliptic region
    QRegion::Ellipse);
    QRegion r2(QRect(200, 70, 90, 30)); // r2: rectangular region
    QRegion r3 = r1.intersected(r2); // r3: intersection

    QPainter painter(this);
    QPixmap qpx;
    switch( m_ButtonState ){
    case eStateNormal:
    qpx.load(QString("JoinNormal.jpg"));
    break;
    case eStatePressed:
    qpx.load(QString("JoinPressed.jpg"));
    break;
    case eStateHovered:
    qpx.load(QString("JoinHover.jpg"));
    break;
    case eStateDisabled:
    qpx.load(QString("JoinNormal.jpg"));
    break;
    }
    QRectF target(10.0, 20.0, 80.0, 60.0);
    QRectF source(0.0, 0.0, 70.0, 40.0);
    painter.drawPixmap(target, qpx, source);
    painter.setClipping(true);
    painter.setClipRegion(r1);
    //QBrush brush(QColor(255,0,0,255));
    //painter.setBackground(brush);
    //update();
    }
    };


    I posted twice, so you can copy one, since someone not so smart decided to use number lines with Geshi knowing that no one can COPY the code because of damn number lines.

  7. #7
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Creating Custom Ellipse Button

    You have to trigger repainting after updating your state (call update()).
    Just setting your internal state variable will not cause your button to repaint itself in this state.

    HTH
    Christoph

  8. #8
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Yes.
    I forgot that, but you must call an update() to schedule a paintEvent each time you switch the states.

    Other than this, the code looks good.

    Regards

  9. #9
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    No the code still does not work:

    #include <QtGui>
    #include "flowlayout.h"
    class QEllipseButton : public QAbstractButton {
    public:
    typedef enum States
    {
    eStateNormal,
    eStatePressed,
    eStateHovered,
    eStateDisabled
    } States;
    States m_ButtonState;
    QEllipseButton(QWidget * parent = 0): QAbstractButton(parent){
    m_ButtonState = eStateNormal;
    }
    protected:
    void mousePressEvent(QMouseEvent *event){
    if (event->button() == Qt::LeftButton) {
    m_ButtonState = eStatePressed;
    update();
    }
    }
    void mouseMoveEvent(QMouseEvent *event){
    if(event->buttons() & Qt::LeftButton) {
    m_ButtonState = eStateHovered;
    update();
    }
    }
    void mouseReleaseEvent(QMouseEvent *event){
    if(event->buttons() && m_ButtonState == eStatePressed){
    m_ButtonState = eStateNormal;
    update();
    }
    }
    void paintEvent ( QPaintEvent * event ){
    QRegion r1(QRect(200, 50, 500, 400), // r1: elliptic region
    QRegion::Ellipse);
    QRegion r2(QRect(200, 70, 90, 30)); // r2: rectangular region
    QRegion r3 = r1.intersected(r2); // r3: intersection

    QPainter painter(this);
    QPixmap qpx;
    switch( m_ButtonState ){
    case eStateNormal:
    qpx.load(QString("Normal.jpg"));
    break;
    case eStatePressed:
    qpx.load(QString("Pressed.jpg"));
    break;
    case eStateHovered:
    qpx.load(QString("Hover.jpg"));
    break;
    case eStateDisabled:
    qpx.load(QString("Normal.jpg"));
    break;
    }
    QRectF target(100.0, 100.0, 100.0, 100.0);
    QRectF source(100.0, 100.0, 100.0, 100.0);
    painter.drawPixmap(target, qpx, source);
    painter.setClipping(true);
    painter.setClipRegion(r1);
    //QBrush brush(QColor(255,0,0,255));
    //painter.setBackground(brush);
    //update();
    }
    };

    ----------------- hOW i run it: -------
    QEllipseButton b;
    b.setText("hoot");
    b.show();

  10. #10
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Qt Code:
    1. QRectF target(100.0, 100.0, 100.0, 100.0);
    2. QRectF source(100.0, 100.0, 100.0, 100.0);
    To copy to clipboard, switch view to plain text mode 
    Is the problem, by any chance, that you don't see any pixmap?
    Try drawing everything relative to (0,0), not (100, 100).
    Also, overwrite QAbstractButton::sizeHint() and return your size hint( which probably is the size of one of the pixmaps ).

    Regards

  11. #11
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    I used 0, and I finally saw the picture. However, the clip stuff never works. Also putting everything inside a QHBoxLayout and settingLayout with a widget, makes it dissappear.

    Also Hover absolutely does not work.

  12. #12
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Regarding hover:
    Hover means you just move your mouse over the widget. You switch to hover if the left button is pressed, in mouseMoveEvent, which is not correct.
    To detect hover, there are less processor stressing methods, like QWidget::enterEvent and QWidget::leaveEvent.

    Regarding adding your custom btn to layouts:
    When I said drawing everything relative to (0,0) I meant to the origin of what rect() returns: rect().topLeft().
    Adding to layouts did not worked because everything was drawn in the topleft corner of the layout .

    Hope it works now.

    Regards

  13. #13
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    Well how do I add automaticlaly to wherever it needs to draw it...? Is there a way?
    Any code examples?

  14. #14
    Join Date
    Oct 2006
    Posts
    279
    Thanks
    6
    Thanked 40 Times in 39 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Wouldn't it be easier to do this with style sheets?
    i.e.
    Qt Code:
    1. int main(int argc, char **argv)
    2. {
    3. QApplication app(argc, argv);
    4. QPushButton btn("quit");
    5. btn.setStyleSheet
    6. (
    7. "QPushButton {"
    8. " border-image: url(normal.png) 17% 17% 17% 17% stretch stretch; "
    9. " border-width: 8px;"
    10. "}"
    11. "QPushButton:hover {"
    12. " border-image: url(hover.png) 17% 17% 17% 17% stretch stretch; "
    13. " border-width: 8px;"
    14. "}"
    15. "QPushButton:pressed {"
    16. " border-image: url(pressed.png) 17% 17% 17% 17% stretch stretch; "
    17. " border-width: 8px;"
    18. "}"
    19. );
    20. QObject::connect(&btn, SIGNAL(clicked()), &app, SLOT(quit()));
    21. btn.show();
    22. app.exec();
    23. }
    To copy to clipboard, switch view to plain text mode 
    You obviously have to adjust the percentage and border values to fit your bitmap and you won't be able to get a true ellipse since some part of the image must be stretched or repeated depending on the text length, but it seems a lot easier.

  15. The following user says thank you to spud for this useful post:

    WinchellChung (26th June 2007)

  16. #15
    Join Date
    Jan 2007
    Posts
    209
    Thanks
    34
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Creating Custom Ellipse Button

    I realize that, I won't be able to get it perfectly. I won't be able to cut the square black background into a transparent one or turn the Square feature of pushbutton into an ELLIPSE feature.

    the Stretch stuff by the way didn't change anything except when the image size is different than the button size.

  17. #16
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Hey man, it works just fine if you do it as I've shown you.

    It will work anyway if you use "ready-made" png images for the states. I mean you draw an ellipse in a png and leave everything else transparent. Then just fill the widget with these pixmaps.

    If you use transp pixmaps the you don't need setting any clipping masks.

    Regards

  18. #17
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    If you use transp pixmaps the you don't need setting any clipping masks.
    Are you sure about that?
    Is this from experience?
    Some time back I implemented a styled button, which can take any shape, and as I remember, I had to use masks in addition to the png (which had transparent areas).
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  19. #18
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Creating Custom Ellipse Button

    Yes, I have already tried it some time ago.
    Also, I might have filled the widget with a transparent pixmap first, then applied the actual png... Can't remember exactly, but it can be done.

    Regards

  20. #19
    Join Date
    Oct 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Smile Re: Creating Custom Ellipse Button

    Qt Code:
    1. ui->pushButton->setFixedSize(150,100);
    2.  
    3. ui->pushButton->setStyleSheet("QPushButton {"
    4. "background-color: red;"
    5. "border-style: solid;"
    6. "border-width: 3px;"
    7. "border-radius: 75px 50px;"
    8. "border-color: blue;"
    9. "font: bold 14px;"
    10. "padding: 6px;}"
    11. "QPushButton:pressed {"
    12. "background-color: rgb(224, 0, 0);}");
    To copy to clipboard, switch view to plain text mode 

    That's what i have implemented ... (For someone looking for a way to go)

    Please note : setFixedSize(150,100); and "border-radius: 75px 50px;"

    Regards.

Similar Threads

  1. Connect Button to a custom slot
    By Majestade in forum Qt Programming
    Replies: 2
    Last Post: 28th March 2007, 17:17
  2. custom maximize button---
    By Naveen in forum Qt Programming
    Replies: 1
    Last Post: 24th February 2006, 13:11

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.