Using platform rendering for widgets in a graphics scene
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(); }
<< Home