Results 1 to 19 of 19

Thread: How to create a custom Button?

  1. #1
    Join Date
    Oct 2006
    Posts
    18
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default How to create a custom Button?

    Hello,

    I am trying to create a custom Button of my own in Qt4. What I want it to do is to display an open switch and a closed switch respectively, depending on whether it has been pressed by the user. Like a QCheckBox, but with different graphics. Two possible solutions come to mind:

    1.) Create a subclass of QAbstractButton.

    I have tried to do this and have achieved some success, however I still have problems. For instance, I can display my own Button within another QWidget, but I cannot add it to any kind of layout (QGridLayout and the like). It is not visible then. I thought this could be a problem with the class I've written not being a subclass of QWidget but of QAbstractButton. But since QAbstractButton is a subclass of QWidget itself, I don't know what I am doing wrong here.
    Here is the source code of my own Button class:

    File: MyButton.h
    Qt Code:
    1. #ifndef _MYBUTTON
    2. #define _MYBUTTON
    3. #include <QAbstractButton>
    4.  
    5. class MyButton : public QAbstractButton
    6. {
    7. Q_OBJECT
    8.  
    9. public:
    10. MyButton(QWidget *parent = 0);
    11. void paintEvent(QPaintEvent*);
    12.  
    13. signals:
    14. void valueChanged(int newValue);
    15. };
    16.  
    17. #endif
    To copy to clipboard, switch view to plain text mode 

    File: MyButton.cpp
    Qt Code:
    1. #include "MyButton.h"
    2. #include <QtGui>
    3.  
    4. MyButton::MyButton(QWidget *parent)
    5. : QAbstractButton(parent)
    6. {
    7. setCheckable(true);
    8. setChecked(false);
    9. }
    10.  
    11. void MyButton::paintEvent(QPaintEvent*)
    12. {
    13. QPainter painter(this);
    14. QPen myPen;
    15. myPen.setWidth(2);
    16.  
    17. if(isChecked())
    18. {
    19. myPen.setColor(Qt::black);
    20. painter.setPen(myPen);
    21. painter.drawLine(20,29,50,20);
    22. int a = 1;
    23. emit valueChanged(a);
    24. }
    25. else
    26. {
    27. myPen.setColor(Qt::darkGray);
    28. painter.setPen(myPen);
    29. painter.drawLine(20,29,30,0);
    30. int b = 0;
    31. emit valueChanged(b);
    32. }
    33. painter.drawLine(0,30,20,30);
    34. painter.drawLine(50,30,70,30);
    35. painter.drawLine(50,30,50,20);
    36. }
    To copy to clipboard, switch view to plain text mode 

    2.) Another possibility would be to use the QCheckBox class and just change its graphical appearance by using QIcons. I tried that just a few minutes ago but somehow I can't seem to get it to display another pixmap. Here is a small example that does compile and run but obviously is not enough to change the QCheckBox's graphical appearance:

    Qt Code:
    1. #include <QtGui>
    2.  
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication app(argc, argv);
    6.  
    7. QCheckBox *button = new QCheckBox;
    8. button->setIcon(QIcon("CustomIcon.png"));
    9. button->show();
    10.  
    11. return app.exec();
    12. }
    To copy to clipboard, switch view to plain text mode 

    Any help on this matter is highly welcome. :-)

  2. #2
    Join Date
    Feb 2006
    Location
    Boulder, Colorado, USA
    Posts
    63
    Thanked 8 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to create a custom Button?

    Combine 1 & 2, just subclass QCheckBox

  3. #3
    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: How to create a custom Button?

    How about subclassing QPushButton and providing your own paintEvent? You have the checkbox functionality already there.

  4. #4
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: How to create a custom Button?

    You would have to provide a proper implementation for QWidget::sizeHint to get it "working" in a layout.. QAbstractButton doesn't provide any implementation for sizeHint() and the default implementation in QWidget returns an invalid size.
    J-P Nurmi

  5. The following user says thank you to jpn for this useful post:

    Mister_Crac (20th October 2006)

  6. #5
    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: How to create a custom Button?

    I suggested subclassing a push button, not the abstract one. Of course subclassing the check box is as good as subclassing the push button. My previous post was a direct response to the original question, not your response, jpn

  7. #6
    Join Date
    Oct 2006
    Posts
    18
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by jpn View Post
    You would have to provide a proper implementation for QWidget::sizeHint to get it "working" in a layout.. QAbstractButton doesn't provide any implementation for sizeHint() and the default implementation in QWidget returns an invalid size.
    Yay, it works - for the layout. Thank you.
    However there is still one problem left: When I move the mouse over my Button Widget (without clicking), it emits the signal that it should only emit when the mouse button is pressed. So I'm doing something wrong with Signals & Slots here? I will post my source code once I've packed it into a single file so you can try out for yourself and see what it does.
    cul8r

  8. #7
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: How to create a custom Button?

    Quote Originally Posted by wysota View Post
    I suggested subclassing a push button, not the abstract one. Of course subclassing the check box is as good as subclassing the push button. My previous post was a direct response to the original question, not your response, jpn
    Yup, got it.. Just wanted to explain why his approach didn't work like he expected.

    Quote Originally Posted by Mister_Crac View Post
    When I move the mouse over my Button Widget (without clicking), it emits the signal that it should only emit when the mouse button is pressed. So I'm doing something wrong with Signals & Slots here?
    Well, have you overridden QWidget::enterEvent()? Do you emit any signals from there?
    J-P Nurmi

  9. #8
    Join Date
    Oct 2006
    Posts
    18
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by jpn View Post
    Well, have you overridden QWidget::enterEvent()?
    No, I haven't. Do I need to do this?

    Do you emit any signals from there?
    The only place so far where I use emit is in paintEvent():
    Qt Code:
    1. if(isChecked())
    2. {
    3. myPen.setColor(Qt::black);
    4. painter.setPen(myPen);
    5. painter.drawLine(20,29,50,20);
    6. int a = 1;
    7. emit valueChanged(a);
    8. }
    9. else
    10. {
    11. myPen.setColor(Qt::darkGray);
    12. painter.setPen(myPen);
    13. painter.drawLine(20,29,30,0);
    14. int b = 0;
    15. emit valueChanged(b);
    16. }
    To copy to clipboard, switch view to plain text mode 

    I just realised that it makes no sense to put all of my code into one single file, I'm getting moc Linker errors like crazy ("undefinde reference to vtable").
    If you need more of my source code posted, I will do so if you ask.

  10. #9
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: How to create a custom Button?

    You should only inform about the state/value change when the change actually occurs. There's no sense in emitting the changed value during each and every paint event. The button gets repainted every once in a while when needed (like if it's geometry is changed by the layout, or after it has been temporarily overlapped by some other window and so on).

    Quote Originally Posted by Mister_Crac View Post
    I just realised that it makes no sense to put all of my code into one single file, I'm getting moc Linker errors like crazy ("undefinde reference to vtable").
    If you need more of my source code posted, I will do so if you ask.
    Add line:
    Qt Code:
    1. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 

    at the end of your main.cpp.

    You will have to include the moc file by hand in case you don't have separate class header files. This is for example when embedding everything as an example to a single main.cpp.
    J-P Nurmi

  11. #10
    Join Date
    Oct 2006
    Posts
    18
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by jpn View Post
    You should only inform about the state/value change when the change actually occurs.
    That's what I thought I was doing with the
    Qt Code:
    1. if(isChecked())
    To copy to clipboard, switch view to plain text mode 

    statement. But obviously that is wrong.
    Now, if I put // comment in front of my second "emit" statement, it works alright 50% of the time.
    So what am I supposed to do exactly, I need to react to a certain event (the user clicks the left mouse button while the mouse pointer is over the MyButton switch).
    Do I need a MouseEvent() and a PaintEvent(), and the PaintEvent() only gets called from the MouseEvent() when the state of the Button changes?
    Where do I put the emit() then?

  12. #11
    Join Date
    Oct 2006
    Posts
    18
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to create a custom Button?

    It seems I found a solution. I added another if statement. Like this:

    Qt Code:
    1. if(isChecked())
    2. {
    3. myPen.setColor(Qt::black);
    4. painter.setPen(myPen);
    5. painter.drawLine(20,29,50,20);
    6.  
    7. if(isDown())
    8. emit valueChanged(1);
    9. }
    10. else
    11. {
    12. myPen.setColor(Qt::darkGray);
    13. painter.setPen(myPen);
    14. painter.drawLine(20,29,30,0);
    15.  
    16. if(isDown())
    17. emit valueChanged(0);
    18. }
    To copy to clipboard, switch view to plain text mode 

  13. #12
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: How to create a custom Button?

    The value does not change in the paint event. The value changes when user interacts with the button, eg. when receiving certain mouse and key events or when the value is changed from code. A paint event occurs whenever appropriate, but the value has not necessarily changed still if a paint event is received. QAbstractButton already provides you a bunch of signals of button state changes:

    wouldn't these suffice for you?
    J-P Nurmi

  14. #13
    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: How to create a custom Button?

    Why don't you just subclass one of existing implementations of QAbstractButton like QCheckBox, QToolButton or QPushButton? You'd only need to reimplement the paint event... I guess even something like this would be enough:

    Qt Code:
    1. class SwitchButton : public QCheckBox {
    2. public:
    3. SwitchButton(QWidget *p=0) : QCheckBox(p){}
    4. QSize sizeHint() const{
    5. QString c = checkState()==Qt::Checked ? ":/mypixmap_checked.png" : ":/mypixmap_unchecked.png";
    6. return QPixmap(c).size();
    7. }
    8. protected:
    9. void paintEvent(QPaintEvent *){
    10. QPainter p(this);
    11. QString c = checkState()==Qt::Checked ? ":/mypixmap_checked.png" : ":/mypixmap_unchecked.png";
    12. p.drawPixmap( QPixmap(c));
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 

  15. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by wysota View Post
    QString c = checkState()==Qt::Checked ? ":/mypixmap_checked.png" : ":/mypixmap_unchecked.png";
    return QPixmap(c).size();
    IMO it would be better to use QPixmapCache instead of loading those pixmaps every time they are needed.

  16. #15
    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: How to create a custom Button?

    Quote Originally Posted by jacek View Post
    IMO it would be better to use QPixmapCache instead of loading those pixmaps every time they are needed.
    That's only an example, I wanted to make it as simple as can be. It would be enough to have two static QPixmap members in the class that would hold those pixmaps, I don't see a benefit from the cache here.

  17. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by wysota View Post
    That's only an example, I wanted to make it as simple as can be.
    But still, it's an improper example. You've just made it too simple.

    Quote Originally Posted by wysota View Post
    It would be enough to have two static QPixmap members in the class that would hold those pixmaps, I don't see a benefit from the cache here.
    How do you want to initialize static QPixmaps? QApplication instance must be created first.

  18. #17
    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: How to create a custom Button?

    Quote Originally Posted by jacek View Post
    But still, it's an improper example. You've just made it too simple.


    How do you want to initialize static QPixmaps? QApplication instance must be created first.
    Somehow I knew you would ask that question

    Qt Code:
    1. class x{
    2. static QPimxap *p1;
    3. static QPixmap *p2;
    4. public x(){
    5. if(!p1){
    6. p1 = new QPixmap(...);
    7. p2 = new QPixmap(...);
    8. }
    9. }
    10. };
    11.  
    12. QPixmap *x::p1 = 0;
    13. QPixmap *x::p2 = 0;
    To copy to clipboard, switch view to plain text mode 
    Of course this causes a slight memory leak if you don't count instances of your class. An alternative is to have those pixmaps directly in the class as regular members, only that it will have a bigger memory footprint.

    BTW. It's not an improper example - you simply don't like it.

  19. #18
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to create a custom Button?

    Quote Originally Posted by wysota View Post
    It's not an improper example - you simply don't like it.
    It's just unnecessarily inefficient.

  20. #19
    Join Date
    Feb 2006
    Location
    Boulder, Colorado, USA
    Posts
    63
    Thanked 8 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to create a custom Button?

    I've been playing around with the new stylesheet thing and it makes everything much simpler. (The below is a stylesheet, not c++)
    Qt Code:
    1. QCheckBox::indicator:unchecked {
    2. image: url(:/images/checkbox_unchecked.png);
    3. }
    4.  
    5. QCheckBox::indicator:checked {
    6. image: url(:/images/checkbox_checked.png);
    7. }
    To copy to clipboard, switch view to plain text mode 

    This is implemented with qApp->setStyleSheet() globally or with myCheckbox->setStyleSheet() for a particular checkbox. Also, check out the Style Sheet Example

Similar Threads

  1. Create a new button
    By avis_phoenix in forum Qt Programming
    Replies: 7
    Last Post: 3rd September 2006, 18:56
  2. How to create an Insert/Submit button for a form.
    By fnmblot in forum Qt Programming
    Replies: 5
    Last Post: 4th August 2006, 16:18
  3. Example HowTo create custom view
    By dexjam in forum Newbie
    Replies: 6
    Last Post: 12th July 2006, 11:06
  4. custom maximize button---
    By Naveen in forum Qt Programming
    Replies: 1
    Last Post: 24th February 2006, 13:11
  5. How to create custom slot in Qt Designer 4.1?
    By jamadagni in forum Qt Tools
    Replies: 31
    Last Post: 18th January 2006, 20:46

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.