We've all written our own small toolkits, and the like in the past, and today I revisited my glory days: I made a button.

Actually, it was a bit more involved.

Some of you might have heard of a nifty thing called a QGraphicsScene (and friends), a fairly useful tool to allow for complex rendering/manipulating of 2D objects, animations, all the rest of the bling. It's been used for a lot of things over time, and recently I've been getting to know it in my copious "free time" over this weekend.

I decided to see how difficult it would be to create my own button inside a QGraphicsScene (yes, I know QGraphicsProxyWidget exists, but it is fairly slow, so using it isn't the best for many situations), so while I was at it, I decided to make it blend in with the rest of the widgets on my desktop too.

This is more a proof of concept than anything, but in case anyone else ever wants to write their own widgets and render them in a QGraphicsScene, here's a bit of a pointer in the right direction. ;)

#include <QApplication>
#include <QGraphicsWidget>
#include <QPainter>
#include <QStyleOptionGraphicsItem>

class AButton : public QGraphicsWidget
{
public:
AButton()
: QGraphicsWidget(),
m_isPressed(false)
{
}
QRectF boundingRect() const
{
// TODO: fetch QRectF from text() + icon() and cache
return QRectF(0, 0, 40, 40);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
{
QStyleOptionButton opt;
// TODO: QStyleOption::initFrom overload for QStyleOptionGraphicsItem would be nice
//opt.initFrom(this);

opt.state = (m_isPressed ? QStyle::State_Sunken : QStyle::State_Raised) | QStyle::State_Enabled;
opt.text = text();
opt.icon = icon();
opt.rect = option->rect;
opt.palette = option->palette;

QApplication::style()->drawControl(QStyle::CE_PushButton, &opt, painter);
}

QString text() const
{
return "hi";
}

QPixmap icon() const
{
return QPixmap();
}

void mousePressEvent(QGraphicsSceneMouseEvent *event)
{
m_isPressed = true;
update();
}

void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
m_isPressed = false;
update();
}

private:
bool m_isPressed;
};

#include <QApplication>
#include <QGraphicsView>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

// set up scene
QGraphicsScene scene;
AButton button;
scene.addItem(&button);

// add a view
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.resize(200, 100);
view.setBackgroundBrush(QApplication::palette().background());
view.show();

return a.exec();
}