views:

104

answers:

2

What is the best way to render capsule-style toolbar controls (including the label text below the buttons) in a Qt application?

As far as rendering the buttons, I want to tap into what is provided by Mac OS as much as possible. (I'm not a Mac developer, so do not know if it has an API for this.) That is, I know I can draw them myself, use style sheets for border-image, guess on the font, and set it all up in a layout, but is there a better way that ensures consistent presentation when Mac updates her "look and feel?" I am using C++ in Qt.

I don't hate the idea of using Q_WS_MAC to get the platform-specific rendering, but does Qt already have anything for this? You know, a setCapsuleStyle(true) method somewhere? :)

Thanks for any suggestions.

+1  A: 

There is a segmented button example in the qt-labs repository that looks decent on KDE. It has a fair amount of #ifdef Q_WS_MAC code, but I don't know how well it renders on Mac. You can find it here.

If you are specifically targeting only Mac, you may use the QMacCocoaViewContainer to render native segmented buttons. Its learning curve is quite steep, so you may find this Qt Labs Blog post about Mac widget interesting: Mac widget style addons. The author provides three Mac-style widgets: QtCocoaPushButton, QtCocoaComboBox and QtCocoaSegmentedButton.

Giuseppe Cardone
+1  A: 

As Qt doesn't provide this type of widget by itself, the best way would be subclassing QPushButton and reimplementing paintEvent. You can then draw your capsule pixmap by simply painting a QPixmap that contains a screenshot of the capsule button. You can add click behaviour by reimplementing mousePressEvent and mouseReleaseEvent.

// CapsuleButton.h
class CapsuleButton : public QPushPutton {
   // ...
protected:
   void paintEvent(QPaintEvent*);
   void mousePressEvent(QMouseEvent*);
   void mouseReleaseEvent(QMouseEvent*);
   // ...
private:
   QPixmap pixmap_;
   QPixmap pressedPixmap_;
   bool pressed_;
};

// CapsuleButton.cpp
CapsuleButton::CapsuleButton(QObject* parent) : 
    QPushButton(parent),
    pixmap_(":/capsule-button-background.png"),
    pressedPixmap_(":/capsule-button-background-pressed.png"),
    pressed_(false)
{ /*...*/ }

void CapsuleButton::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(rect(), pressed_? pressedPixmap_ : pixmap_);
}

void CapsuleButton::mousePressEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton)
       pressed_ = true;
    update();
}

void CapsuleButton::mouseReleaseEvent(QMouseEvent*)
{
    pressed_ = false;
    update();
}

I have writte a short tutorial on how to create custom widgets: http://www.serenethinking.com/2010/08/how-to-create-custom-widgets-with-qt/

Maybe that helps.

Wolfgang Plaschg