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 ar
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);
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:
delete
safely ignores null pointers, such as potentially returned by QGraphicsScene::focusItem()
.on_name_signal
.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.
// 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
Use QGraphicsSceneMouseEvent.