I need to display a set of points(nearly 200) on my custom plot. Thereafter when I click on a specific point ,it should display its coordinates using mouse event. The mouse event should be able to display only those points coordinates where I click and not the remaining empty region. I have tried using event->pos().x() to a pixeltocoord. But no use. I need a help in mouse event.
Your question its a little vague, 'but not use' meaning what ? Did you received the event and the information is not useful ? or you never got an event ? Or the value is wrong for some perspective ? Is it your custom plot a QWidget ?
Well, I try anyway ...
If your custom plot is a QWidget:
First you need to enable Mouse tracking in your widget
CustomPlotWidget->setMouseTracking(true);
Then you should store the coordinates in the mouse press event, you do that by overriding the event handler
CustomPlotWidget::mousePressEvent(QMouseEvent *event)
{
save_coords=event->pos;
}
Then when you paint the widget you use that coordinates to display some text there, or you can pop a QToolTip in that location (that is what I do, and it looks really nice)
According to your comment if you went with the solution of drawing yourself the coordinates you just need to redraw the section where you previously draw them. You can store the rectangular area when you draw before, then you redraw everything under that area but the coordinates.
CustomPlotWidget::mousePressEvent(QMouseEvent *event)
{
...
save_coords=event->pos;
update(areaWhereYouPreviouslyDrawCoordinates);
update(areaWhereYouWantToDrawNewCoordinates);
}
CustomPlotWidget::paintEvent(QPaintEvent *event)
{
...
if (event->rect().insersect(areaWhereYouWantToDrawNewCoordinates))
{
drawCoordinates();
areaWhereYouPreviouslyDrawCoordinates=areaWhereYouWantToDrawNewCoordinates;
}
...
}
If you go with the solution using QToolTip:
CustomPlotWidget::mousePressEvent(QMouseEvent *event)
{
...
if (needToDrawCoordinates)
QToolTip::showText(Where,Coordinates);
else
QToolTip::hideText();
}
Related
I have a Qt application with objects derived from QGraphicsObjcet that need to be movable in a scene. I know that I can use the flags for movement to achieve this.
myObject->setFlag(QGraphicsItem::ItemIsMovable);
myObject->setFlag(QGraphicsItem::ItemIsSelectable);
myObject->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
but I am having an issue with the objects popping out of position when i use it. The only time when the objects move into an incorrect position is when an object I've moved is deleted and removed from the scene, the next time I try to move another object in the scene, its position relative to mouse Cursor is distorted until I release it and press it again. I realise that my problem could be occuring somewhere completely elsewhere in my code but from my own debugging I would at least want to try and implement the move functionality myself to solve this issue.
So my question is: How can you implement movable objects (derived from QGraphicsObject) that act as if the flags above are active?
I've been trying to use mouseMoveEvent but can't figure out how I get the objects to move with the cursor. Maybe I should look into DragMoveEvent instead? If possible, I would however really appreciate to see what the code for mouseMoveEvent below would look:
void myObject::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// How do I get myObject to follow
// the event pos in the scene from here?
QGraphicsObject::mouseMoveEvent(event);
update();
}
I think something like this should do the trick (not tested):
void myObject::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// Set the item position as the mouse position.
this->setPos(event->scenePos());
// If your object (this) has no parent, then setPos() place it using scene coordinates, which is what you need here.
QGraphicsObject::mouseMoveEvent(event);
update();
}
With the code above, your object is going to follow the mouse untill the end of the world, so you probably want to combine it with a start/stop flag.
And if your item has a parent, you are probably going to need to translate the coordinates.
I am creating a node graph and I want to be able to click the empty space in a scene and middle-mouse-drag to navigate without deselecting the currently selected items in the scene. Any suggestions?
I can block the middle click in the view's mousePressEvent and get the right behavior but then I no longer have middle-mouse click events working on items in the scene. I don't mind a middle-click resulting in a single selection when clicking on an item in the scene, but if I middle-click the empty space in the scene I don't want the selection altered.
This didn't cover the more complex behavior I am looking for: PyQt. How to block clear selection on mouse right click?
I didn't try using an eventFilter as I assume the issue would be the same
I am using PyQt/PySide, FWIW.
Before I roll my own workaround I thought I'd post here for the correct way or at least other workaround ideas.
Some workaround ideas:
Block the mousePressEvent to the scene but iterate over child items to deliver it directly
Restore selection while still in the mousePressEvent in the scene. Probably bad for performance at scale but simple I suppose.
Any feedback would be great!
[Edit:]
Here is my python version of the answer. Code tested. In my QGraphicsScene derived class:
def mousePressEvent(self, event):
# Prevent the QGraphicsScene default behavior to deselect-all when clicking on
# empty space by blocking the event in this circumstance.
item_under_the_mouse = self.itemAt(event.scenePos())
if event.button() == QtCore.Qt.MidButton and not item_under_the_mouse:
event.accept()
else:
super(GraphScene, self).mousePressEvent(event)
In your QGraphicsScene::mousePressEvent derived implementation, if it's a middle mouse click, check for items under the mouse click. If there aren't any, then accept the event and don't call the base class implementation. If something is under the click, then just call the base implementation; you don't have to try to reimplement that yourself. I think this is the general idea:
void MyScene::mousePressEvent (QGraphicsSceneMouseEvent *evt)
{
if ((evt->buttons () & Qt::MidButton) && items (evt->scenePos ().count ())
{
QGraphicsScene::mousePressEvent (evt);
}
else
{
evt->accept ();
}
}
I'm not sure if the accept is required in this case or not. I haven't compiled or tested this, but hopefully, it's helpful to get you going in the right direction.
I need to save and restore position of QToolbars in my application.
When toolbars are docked to different area, i am able to save the area and assign it in function QMainWindow::addToolBar. But when several toolbars are docked to the same area, i don't know in what order they are currently on the screen.
I tried
QList<QToolBar*> toolbars = findChildren<QToolBar*>();
But this seems to return toolbars in order of creation and not how there are currently arranges on the screen (user can move them).
There is an easy and straightforward way of doing what you want in Qt. QMainWindow has a method saveState() that
saves the current state of this mainwindow's toolbars and dockwidgets.
and a method restoreState() that does the opposite.
Further information can be found here.
To save and restore the QMainWindow's geometry itself you can still use QWidget::saveGeometry() and QWidget::restoreGeometry().
An example of both combined that can also be found in saveState()'s documentation:
To save the geometry when the window closes, you can implement a close
event like this:
void MyMainWindow::closeEvent(QCloseEvent *event)
{
QSettings settings("MyCompany", "MyApp");
settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState());
QMainWindow::closeEvent(event);
}
I have a simple QGraphicsWidget, MyGraphicsWidget. Here's my mouseMoveEvent(), which seems to work fine :
void MyGraphicsWidget::mouseMoveEvent (QGraphicsSceneMouseEvent *event)
{
QPointF p = event->scenePos() - m_StartPos;
if(p.manhattanLength() < 20)
return;
//omitted drawing a rounded rect on the drag
QDrag *drag = new QDrag(event->widget());
drag->start(Qt::MoveAction);
}
The scene's dropEvent() just moves this widget to its new position, and I don't have a press/move event for the scene itself, so those should get passed on correctly to the widgets within.
However, once the drag completes, the next mouse press will be on this widget. So if I try to click and drag another widget, I'll be stuck dragging this one on accident, despite the fact that my cursor is not on this widget. I've printed out the event->pos() and event->scenePos(), and both reported that the cursor is where it appears to be (not on the widget at all). If I click once before trying to click and drag, everything works normally. Is there maybe something I need to implement within mouseReleaseEvent() or my mouseMoveEvent() ?
Thanks.
It's working now. I'm pretty sure this was the issue:
MyGraphicsWidget had another custom GraphicsWidget sitting on top of it, and in its mousePressEvent, I was calling QGraphicsWidget::mousePressEvent(event); at the start of the event. The rest of the event was never getting triggered, which was messing it all up. I moved that line to the end of the method, and everything seems okay now.
I'm developing a custom widget with QGraphicsScene/View and I have no prior experience with it.
The custom widget is an image viewer that needs to track mouse movement and send signal(s) to it's parent dialog / window. The signal(s) will be the position of the pixel under the mouse cursor and it's color (in RGB). A status bar will use that information.
I use a QGraphicsPixmapItem to display the image I load from a file in the scene.
Thanks.
First of all you have to implement the mouseMoveEvent in your custom item. In this function you can easily get the mouse position calling the pos function. You can get the rgb value if you transform the item's pixmap into image and call the pixel function. You should consider storing the QImage as member variable in order to avoid multiple transformations. Finally you have to emit a custom signal. Sample code follows:
void MyPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
QPointF mousePosition = event->pos();
QRgb rgbValue = pixmap().toImage().pixel(mousePosition.x(), mousePostion.y());
emit currentPositionRgbChanged(mousePosition, rgbValue);
}
Notice that QGraphicsItems do not inherit from QObject so by default signals/slots are not supported. You should inherit from QObject as well. This is what QGraphicsObject does. Last but not least I would advise you to enable mouse tracking on your QGraphicsView
I found the mouseMoveEvent approach to not work at all, at least not with Qt5.5. However, enabling hover events with setAcceptHoverEvents(true) on the item and reimplementing hoverMoveEvent(QGraphicsSceneHoverEvent * event) worked like a charm.
The Qt docs on mouseMoveEvent() provide the clue:
"If you do receive this event, you can be certain that this item also received a mouse press event"
http://doc.qt.io/qt-5.5/qgraphicsitem.html#mouseMoveEvent