1

I am trying to achieve rubber band rectangle zoom in. But here I need to zoom in only the part which comes under rubber band rectangle. I do not want to zoom in the whole view. For that I was told to create rubber band rectangle whose point I will know. And then use

    void QGraphicsView::ensureVisible(qreal x, qreal y, qreal w, qreal h, int xmargin = 50, int ymargin = 50)     
or       
    void QGraphicsView::centerOn(qreal x, qreal y) 
      

So just to understand, what this ensureVisible() does, I called it with some points which are present in my design. But just a pop up windows appeared but nothing was there to display. So I left that task and concentrated on, how to get rubber band rectagle points. So I tried to add some mouse events in my existing sample project but I got following error.

schematicdesign.cpp:75:47: error: non-static member 'mapToScene' found in multiple base-class subobjects of type 'QGraphicsItem': class SchematicDesign -> class QGraphicsRectItem -> class QAbstractGraphicsShapeItem -> class QGraphicsItem class SchematicDesign -> class QGraphicsPathItem -> class QAbstractGraphicsShapeItem -> class QGraphicsItem qgraphicsitem.h:360:13: note: member found by ambiguous name lookup

Such error is not only for mapToScene() but also for scene() and transform().

What I understood from the error is :

I have inherited schematicDesign class from multiple classes ( QGraphicsRectItem and QGraphicsPathItem ) so when it tries to find the definition of mapToScene() or scene() or transform(), it finds in multiple classes so gets confused in which one to pick. ( please correct if I am wrong )

Here is my code:
Widget.h

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QGraphicsView
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget(); 
private slots:
  void on_schematicButoon_clicked();     
private:
    Ui::Widget *ui;
    QGraphicsScene* scene;
    QGraphicsView* view;
};

 

Widget.cpp

    Widget::Widget(QWidget *parent)
        : QGraphicsView(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        scene = new QGraphicsScene(this);
    
        view = new QGraphicsView(this);
        view->setScene(scene);
        ui->verticalLayout_2->addWidget(view);
    }      
           
void Widget::on_schematicButoon_clicked()
{
    SchematicDesign* sd1 = new SchematicDesign();

    QGraphicsRectItem* clkPin = sd1->createRect(20,160,20,20);
    scene->addItem(clkPin);   
    // some more createRect() method        
         
    QPen mPen;
    mPen.setWidth(3);
    mPen.setBrush(Qt::yellow);

    QPolygonF clknet;
    clknet<< QPointF (40,170) << QPointF (186,170);
    QGraphicsPathItem* clk = sd1->drawPolyline(clknet);
    scene->addItem(clk);      
    // some more drawPolyline() method.         
       
    QGraphicsPathItem* text = sd1->addText(i1Instance,275.0,138.0,"I1");
    scene->addItem(text);       
    // some more addText() method      
      
   }      

SchematicDesign.h

class SchematicDesign : public QGraphicsRectItem,QGraphicsPathItem
{
public:
    explicit SchematicDesign();
    explicit SchematicDesign(qreal x, qreal y, qreal width, qreal height,QGraphicsItem *parent = nullptr)
        : QGraphicsRectItem(x, y, width, height, parent)
        {}

    explicit SchematicDesign(QPainterPath pPath);
signals:

public:
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    QGraphicsRectItem* createRect(qreal x, qreal y, qreal width, qreal height);
    QGraphicsPathItem* drawPolyline(QPolygonF poly);
    QGraphicsPathItem* addText(QGraphicsRectItem *rect, double d1, double d2, QString s);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

private:
    QPointF selectTopLeft;
    bool drawingSelection;
    QGraphicsRectItem* lastRect;
public:
    QPoint rubberBandOrigin;
    bool rubberBandActive;
};

#endif // SCHEMATICDESIGN_H
  

SchematicDesign.cpp

    SchematicDesign::SchematicDesign(){}
    
    SchematicDesign::SchematicDesign(QPainterPath pPath)
    {}        
    void SchematicDesign::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
       auto copied_option = *option;
    copied_option.state &= ~QStyle::State_Selected;
    auto selected = option->state & QStyle::State_Selected;
    QGraphicsRectItem::paint(painter, &copied_option, widget);
    QGraphicsPathItem::paint(painter, &copied_option, widget);

    if (selected)
    {
        painter->save();
        painter->setBrush(Qt::NoBrush);
        painter->setPen(QPen(option->palette.windowText(), 0, Qt::SolidLine));
        painter->drawPath(QGraphicsRectItem::shape());
        painter->drawPath(QGraphicsPathItem::shape());
        painter->restore();
    }
}     
    QGraphicsRectItem *SchematicDesign::createRect(qreal x, qreal y, qreal width, qreal height)
    {...... }     
    QGraphicsPathItem* SchematicDesign::drawPolyline(QPolygonF poly)
    {....}    
    QGraphicsPathItem* SchematicDesign::addText(QGraphicsRectItem *rect, double d1, double d2, QString s)
    {.....}     
    
    void SchematicDesign::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        QGraphicsItem * sceneItem = scene()->itemAt(mapToScene(event->pos()),transform()); //error
        if(!sceneItem){
            selectTopLeft = event->pos();
            event->pos();
            drawingSelection = true;
        }
    
        QGraphicsRectItem::mousePressEvent(event);
    }
    
    void SchematicDesign::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
        if(drawingSelection){
            QGraphicsItem * itemToRemove = lastRect;
            if(itemToRemove){
                fitInView(itemToRemove,Qt::KeepAspectRatio); //error at fitInView : Use of undeclared identifier
                scene()->removeItem(itemToRemove); //error at scene()
                delete itemToRemove;
                lastRect = nullptr;
            }
        }
    
        drawingSelection = false;
        QGraphicsRectItem::mouseReleaseEvent(event);
    }
    
    void SchematicDesign::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if(drawingSelection){
    
            //Selection region
            int x = selectTopLeft.rx();
            int y = selectTopLeft.ry();
            int h = event->pos().rx();
            int w = event->pos().ry();
    
            //QRect selectRegion = QRect(selectTopLeft,event->pos());
            QRect selectRegion = QRect(x,y,h,w);
    
            QPainterPath path;
            path.addRect(selectRegion);
    
            scene()->setSelectionArea(mapToScene(path)); //error at scene()
    
            //Draw visual feedback for the user
            QGraphicsItem * itemToRemove = lastRect;
    
            scene()->removeItem(itemToRemove); // error at scene()
    
            lastRect = scene()->addRect(QRectF(mapToScene(selectTopLeft), 
                                               mapToScene(event->pos())).normalized()); // error at scene() and mapToScene()
            lastRect->setBrush(QBrush(QColor(255, 0, 0, 50)));
    
            delete  itemToRemove;
        }
    
        QGraphicsRectItem::mouseMoveEvent(event);
    }       
  

How to tackle such type of error ? Should not I inherit my class from multiple classes ?

tushar
  • 313
  • 4
  • 10
  • 1
    Why do you try to derive from QGraphicsRectItem and QGraphicsPathItem? This is not possible (and not needed) - choose one. – chehrlic Feb 20 '22 at 13:49
  • @chehrlic In my view, I have multiple items like rectnagle, polyline, Text etc. And to select them I have overridden paint(). In that paint() I am using QGraphicsRectItem and QGraphicsPathItem both. That's why I have derived from multiple classes. Please look at my paint method. I have updated my code. – tushar Feb 20 '22 at 14:18
  • Please show the code that uses `SchematicDesign`. You seem to have a misunderstanding of inheritance versus composition -- or at least when to use one rather than the other. – G.M. Feb 20 '22 at 14:24
  • @G.M. On my screen, I just click on ScematicDesign button and then whole design gets loaded. I have updated my code accordingly. ( In that design I have used different items like rectangle, polyline and text ) – tushar Feb 20 '22 at 14:33
  • Your update demonstrates the problem. You create a `SchematicDesign` instance and then only use it as a factory object. There's no need for it to inherit from the various `QGraphics*Item` classes and the overridden virtual methods will never be called. Also note that the code shown has a memory leak as you never `delete sd1`. – G.M. Feb 20 '22 at 15:12
  • @G.M. If I did not inherit from varios QGraphics*Item , then in paint() method I get error. And I want paint() at any cost. QGraphicsRectItem::paint(painter, &copied_option, widget); QGraphicsPathItem::paint(painter, &copied_option, widget); I want these both lines in paint() – tushar Feb 20 '22 at 15:27
  • So when do you expect your `SchematicDesign::paint` override to be called? – G.M. Feb 20 '22 at 15:32
  • @G.M. Can you please explain, what should I do now ? How to overcome this problem ? I tried to write QGraphicsRectItem:: scene() or QGraphicsRectItem:: mapToScene() etc and errors gone but rubber band is not coming – tushar Feb 20 '22 at 15:33
  • @G.M. When I will click on rectangle or polyline or text in the design, then only SchematicDesign::paint should get call. – tushar Feb 20 '22 at 15:35
  • @G.M. If I am using rectangle, polyline, text in my design, then I have to inherit from QGraphicsRectItem , QGraphicsPathItem. Without inheriting them, how to write program ? – tushar Feb 20 '22 at 15:41
  • @G.M In my new post, I have removed multiple inheritance and tried to use composition in paint(). But only for rectangle , paint() gets called but not for polyline. Can you help me in that ? https://stackoverflow.com/questions/71203657/virtual-paint-method-is-not-getting-called-for-all-the-qgraphicsitem-present-o – tushar Feb 21 '22 at 09:19

0 Answers0