[SOLVED]A little help in my approach for QTGraphicsRectItem



  • Hello. I am working on a quite big program now and since I am in Qt for 2 months average, I need some pro advices to spend time and energy for the big thing to come. So. I have a custom rect item that is inherited from QtGraphicsRectItem here(Ive removed most methods that dont deserve attention like getters/setters because the post get too big):

    ActionRectItem.h
    @
    class MainWindow;
    class ActionRectItem:QGraphicsRectItem {
    friend class Callbacks;
    friend class MainWindow;
    private:
    Callbacks* functors;

    ActionRectItem(int x, int y, int w, int h,
                   QString name, int id, MainWindow* pw,
                   QGraphicsScene* sc,
                   Callbacks*);
    

    protected:
    /overriden/
    void advance(int phase);
    void mousePressEvent(QGraphicsSceneMouseEvent* event);
    public:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    };
    @
    And its implementation here (Ive removed some get/set because my post was 6000+) :
    @

    void ActionRectItem::advance(int phase)
    {
    functors->onAdvance(phase, this);
    }

    ActionRectItem::ActionRectItem(int x, int y, int w, int h,
    QString name, int id, MainWindow* pw,
    QGraphicsScene* sc,
    Callbacks* cbs)
    :parent(pw), __name(name), __privateId(id),
    speed(5), scene(sc), xcoord(x), ycoord(y), width(w), height(h),
    functors(cbs) /*great success :D */

    {
    angle = qrand() % 360;
    setRotation(angle);
    setRect(x, y, w, h);
    timer = new QTimer(scene);
    setPos(xcoord, ycoord);
    }

    void ActionRectItem::mousePressEvent(QGraphicsSceneMouseEvent event) {
    functors->onMouse((QGraphicsSceneMouseEvent
    ) event, this);

    }

    void ActionRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {

    functors->onPaint(painter, option, widget, this);
    

    }

    ...
    @

    As you see there is nothing strange beside 3 functions I want to look at. paint(), advance(), onMousePress(). So lets say I have 5 instances from ActionRectItem like this: @ ActionRectItem a1,a2,a3,a4,a5; //called with the big constructor just saved typing @ I need all of these to have different bodies of paint(), advance() and noMousePress(). What I came up is the Callbacks pointer inside ActionRectItem, which Ive implemented as dpointer or opaque in the h file. So lets show you how do I use that approach. I have a big class with these 5 objects that do different things: Somewhere in the big class that composites the whole picture...(Ill post just 2 imagine there can be 5 or 10 or whatever )
    @

    ActionRectItem* art = new ActionRectItem(100,200, 300,200, "Screen", 1, this, myScene,
    new Callbacks(customOnAdvance,
    customOnMouse2,
    customOnPaint2,
    doer));
    ActionRectItem* art2 = new ActionRectItem(400,300, 300,200, "Screen", 1, this, myScene,
    new Callbacks(customOnAdvance2,
    customOnMouse,
    customOnPaint2,
    doer));
    @
    Look at the new Callbacks. Each object takes different callbacks in it`s construction so you can have combination of different behaviour by just setting the callbacks to different functions or exchange the behavior. Here is custom function
    @
    static inline void customOnMouse(QGraphicsSceneMouseEvent* me,
    ActionRectItem* ari) {
    ((QGraphicsRectItem*)ari)->setBrush(QBrush(QColor(255,0,0,100)));
    QPixmap pix(100, 50);

    QPainter painter(&pix);
    painter.setPen(Qt::black);
    painter.setBrush(Qt::blue);
    QFont font = painter.font();
    font.setPointSize(12);
    painter.setFont(font);
    
    QGraphicsTextItem* text = ari->getScene()->addText("TEST DISPLAY", font);
    text->setPos(QPointF(ari->getX()+10, ari->getY()+ 10));
    

    }

    static inline void customOnMouse2(QGraphicsSceneMouseEvent* me,
    ActionRectItem* ari) {
    qDebug() << "CALLED CUSTOM ON MOUSE\n";
    ((QGraphicsRectItem*)ari)->setBrush(QBrush(QColor(255,0,0,100)));
    QPixmap pix(100, 100);

    QPainter painter(&pix);
    painter.setPen(Qt::black);
    painter.setBrush(Qt::blue);
    QFont font = painter.font();
    font.setPointSize(22);
    painter.setFont(font);
    
    QGraphicsTextItem* text = ari->getScene()->addText("BLAAAAAA", font);
    text->setPos(QPointF(ari->getX()+500, ari->getY()+ 600));
    

    }

    static inline void customOnPaint(QPainter* qp,
    const QStyleOptionGraphicsItem* qsi,
    QWidget* wd, ActionRectItem* ari) {
    static int calltimes = 0;
    qDebug() << "paint() calls:" << calltimes++ << "\n";
    static QRectF rec = ari->boundingRect();
    static QBrush Brush(Qt::gray);

    if ( ari->getScene()->collidingItems(
             (QGraphicsItem*) ari).isEmpty()) {
        Brush.setColor(Qt::green);
    } else {
        Brush.setColor(Qt::red);
        ari->doCollision();
    }
    qp->fillRect(rec, Brush);
    qp->drawRect(rec);
    

    }

    @
    So you can mode paint() versions or mouse or remove, exchange per object or jsut do nothing. You can add more logic by adding functors to Callbacks class and implement with static inlines on the fly. Ive tested it and it made the concrete class easy to work with. But I want your opinion on my idea/approach. And be honest. [EDIT] I kind of read that I need Visitor design pattern, but the callbacks method Ive used did a good job. You may look here:
    https://www.flickr.com/photos/heatblazer/15834622069/
    https://www.flickr.com/photos/heatblazer/16018713711/



  • Nobody replied to this. Some people told me the approach was not good. Ive decided to test with Visitor. Its OK.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.