0

Here i develoed a custom widget to print some shape. But here my MouseRelease and MouseMove event are not working.wh t is the problem of my code. As well as some Asserts are executed. please help me to solve this.

This is my header file

//painter.h

#ifndef PAINTER_H
#define PAINTER_H

#include <QWidget>
#include <QGraphicsView>
#include <math.h>
#include <QVector>
#include <QMouseEvent>
#include <QPoint>


class painter : public QWidget
{
    Q_OBJECT
private:
    enum Shape{CIRCLE,RECTENGEL,TRIANGEL} shape;
    QGraphicsView *graphic;
    QGraphicsScene *Scene;
    QPoint *start;
    QPoint *end;
    QPen *pen;
    QBrush *brush;
    QVector<QGraphicsItem*> *items;

public:
    explicit painter(QWidget *parent = 0);

    void setSize(double width,double height);
    void setShape(Shape value);
    void addItem();
    void clear();
    void scale();

signals:

public slots:

protected:

   void mousePressEvent(QMouseEvent *event);
   void mouseMoveEvent(QMouseEvent *event);
   void mouseReleaseEvent(QMouseEvent *event);


};

#endif // PAINTER_H

and this is my CPP file

//painter.cpp

#include "painter.h"
#include <QDebug>
#include <QGraphicsView>
#include <iterator>

painter::painter(QWidget *parent) :
    QWidget(parent)
{
    graphic = new QGraphicsView(this);
    Scene = new QGraphicsScene(this);
    pen = new QPen;
    brush = new QBrush;
    start = new QPoint;
    end  = new QPoint;
    items = new QVector<QGraphicsItem*>();

    graphic->setScene(Scene);

  //Scene->addEllipse(10,10,50,50,*pen,*brush);//Scene->addLine(0,0,1,1);
  //  Scene->addRect(70,70,50,50,*pen,*brush);

graphic->setSceneRect(0,0,500,500);
Scene->addEllipse(20,20,20,20,*pen,*brush);





}

void painter::setSize(double width,double height)
{
    graphic->setSceneRect(0,0,width,height);
}


void painter::setShape(Shape value)
{

    if(value==CIRCLE)
        shape = CIRCLE;
    else if(value==RECTENGEL)
        shape = RECTENGEL;
    else if(value=TRIANGEL)
        shape=TRIANGEL;
    else
        throw("Invalid Shape");


}

void painter::addItem()
{
    QGraphicsItem *newItem;
    double length = sqrt(pow((double)(start->x()-end->x()),2)+ pow((double)(start->y()-end->y()),2));

    if(shape==TRIANGEL)
    {
//        QPolygonF triangel;
//        triangel.
//        Scene->addPolygon(,pen,brush);
    }
    else if(shape==RECTENGEL)
       newItem = (QGraphicsItem*)Scene->addRect(end->x()-length,end->y()-length,2*length,2*length,*pen,*brush);

    else
       newItem =  (QGraphicsItem*)Scene->addEllipse(end->x()-length,end->y()-length,2*length,2*length,*pen,*brush);

    items->push_back(newItem);
}

void painter::clear()
{
    for(int i=0;i<items->size();i++)
       Scene->removeItem(items->at(i));

}

void painter::scale()
{
}


void painter::mousePressEvent(QMouseEvent *event)
{
    end->setX(50);
   end->setY(50);


    start->setX(event->x());
    start->setY(event->y());
shape = RECTENGEL;
    addItem();



}

void painter::mouseMoveEvent(QMouseEvent *event)
{
    qDebug("move");

}

void painter::mouseReleaseEvent(QMouseEvent *event)
{
    end->setX(event->x());
    end->setY(event->y());
    addItem();

}

3 Answers3

2

Use QGraphicsSceneMouseEvent.

brooNo
  • 506
  • 4
  • 8
1

You're not telling us at all what is it that you're trying to do. The Qt's graphics scene / view system is powerful enough to support dragging of items without you having to write any code to handle low-level mouse events. If that's what you're after, that is.

Your mouse move event is not called because your mouse press doesn't happen in your widget, but in the child QGraphicsScene. Mouse presses that happen in children will not trigger mouse tracking within your widget.

Had you added a layout to manage the child widgets in your Painter class, you'd notice that your mouse move events are handled if you click in the margin outside of the QGraphicsView. The code below shows how to do set a layout on a widget containing a scene view.

The code below is a complete and hopefully correct example of creating randomly sized, moveable and focuseable circles. It demonstrates as well:

  • How to properly map coordinates from the parent widget to scene itself.
  • That clearing the scene does not require manually keeping track of items.
  • How to derive from a predefined item to add simple functionality.
  • How to operate on an item that has focus.
  • That the scene is notified when its children are removed, thus simply deleting a child item is perfectly safe thing to do.
  • That delete safely ignores null pointers, such as potentially returned by QGraphicsScene::focusItem().
  • How to use object names to automatically attach slots named on_name_signal.
  • How to have Q_OBJECT classes within .cpp files by including the .moc file at the end.
  • How to keep members by value, relegating memory management to the compiler.

The example is self contained and consists of just one .pro and .cpp file each. It works under both Qt 4 and Qt 5, and leverages C++11.

screnshot from running the example code

// https://github.com/KubaO/stackoverflown/tree/master/questions/scene-movable-circles-11188261
// main.cpp
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
#include <cmath>

class Circle : public QGraphicsEllipseItem {
   QBrush m_inBrush{Qt::red}, m_outBrush{Qt::lightGray};
public:
   Circle(const QPointF & c) {
      const qreal r = 10.0 + (50.0*qrand())/RAND_MAX;
      setRect({c.x()-r, c.y()-r, 2.0*r, 2.0*r});
      setFlag(QGraphicsItem::ItemIsMovable);
      setFlag(QGraphicsItem::ItemIsFocusable);
      setPen({Qt::red});
      setBrush(m_outBrush);
   }
   void focusInEvent(QFocusEvent *) override { setBrush(m_inBrush); }
   void focusOutEvent(QFocusEvent *) override { setBrush(m_outBrush); }
};

class Painter : public QWidget {
   Q_OBJECT
   QGridLayout m_layout{this};
   QGraphicsView m_view;
   QPushButton m_clear{"Clear"};
   QPushButton m_remove{"Remove"};
   QGraphicsScene m_scene;
public:
   explicit Painter(QWidget *parent = nullptr);
protected:
   Q_SLOT void on_remove_clicked();
   void mousePressEvent(QMouseEvent *event) override;
};

Painter::Painter(QWidget *parent) : QWidget(parent) {
   m_layout.addWidget(&m_view, 0, 0, 1, 2);
   m_layout.addWidget(&m_clear, 1, 0);
   m_layout.addWidget(&m_remove, 1, 1);
   m_remove.setObjectName("remove");
   QMetaObject::connectSlotsByName(this);
   connect(&m_clear, SIGNAL(clicked()), &m_scene, SLOT(clear()));

   m_view.setRenderHint(QPainter::Antialiasing);
   m_view.setScene(&m_scene);
   m_view.setSceneRect(0,0,500,500);
}

void Painter::mousePressEvent(QMouseEvent *event) {
   auto center = m_view.mapToScene(m_view.mapFromParent(event->pos()));
   m_scene.addItem(new Circle(center));
}

void Painter::on_remove_clicked() {
   delete m_scene.focusItem();
}

int main(int argc, char ** argv)
{
   QApplication app{argc, argv};
   Painter p;
   p.show();
   return app.exec();
}

#include "main.moc"
# scene-movable-circles-11188261.pro
greaterThan(QT_MAJOR_VERSION, 4) {
    QT = widgets 
    CONFIG += c++11
} else {
    QT = gui 
    unix:QMAKE_CXXFLAGS += -std=c++11
    macx {
        QMAKE_CXXFLAGS += -stdlib=libc++
        QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
        QMAKE_CXXFLAGS_WARN_ON += -Wno-inconsistent-missing-override
    }
}
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050800
TARGET = scene-movable-circles-11188261
TEMPLATE = app
SOURCES += main.cpp
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
0

In QWidget mouse tracking (when no mouse button is pressed) is not enable by default. To enable it add the following code :

painter->setMouseTracking(true);
KazukiCP
  • 127
  • 2