How to integrate a cursor in a QtWidgets app
-
Hello
I am new to QtWidgets and trying to build an app in QtWidgets and Python (3.x).
the end goal of the app is to show images and a superposed cursor (to be exact, a "plus" sign of 2cm) that can be moved along the image reacting to mouse events. I want to start creating this plus sign first then integrate the images.i am not sure how to start. i read examples on the internet on how to do it in matplotlib. is it possible in my case to integrate matplotlib?
thanks
here is my desired output and the code of my app

import sys from PySide2 import QtWidgets from vispy import scene from PySide2.QtCore import QMetaObject from PySide2.QtWidgets import * class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.groupBox = QGroupBox(self.centralwidget) self.groupBox.setObjectName("groupBox") self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) QMetaObject.connectSlotsByName(MainWindow) class MainWindow(QtWidgets.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # OpenGL drawing surface self.canvas = scene.SceneCanvas(keys='interactive') self.canvas.create_native() self.canvas.native.setParent(self) self.view = self.canvas.central_widget.add_view() self.setWindowTitle('MyApp') def main(): import ctypes ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('my_gui') app = QtWidgets.QApplication([]) main_window = MainWindow() main_window.show() sys.exit(app.exec_()) if __name__ == '__main__': main() -
@jsulm
I believe you are mistaking the issue! :) The OP says this code works as-is. He puts this code in a class derived fromscene.SceneCanvas, which is some OpenGL class, not Qt. I believe the mouse events are being handled inside that, not Qt, so if that wants aon_mouse_press()method so be it.Correct me if I am wrong. Of course if that code does not actually work as the OP implies then it's a different matter!
-
Hi and welcome to devnet,
Do you want to move a cursor on your canevas or change the actual mouse cursor when hovering the canevas ?
As for matplotlib, it has a Qt backend so yes you can integrate it.
-
Hello. @SGaist yes I want to move the cursor (the red plus sign on the image) and this would move according to the mouse events (we need to click on it and drag it. when we don't click it should not move) and this would be suporposed on images i will display in the future
i thought of doing something like this (simpler than matplotilb). but i have trouble understanding how to integrate it in the code itself (SimpleItem would be something that I draw)
scene2 = QGraphicsScene() item = SimpleItem() scene2.addItem(item) -
In that case, don't complicate things: items can be made movable. See the GraphicsItemFlag.
-
@SGaist ok I read about it. but my problem is adding an item like this (example of a square) to my canvas
class SimpleItem(QtWidgets.QGraphicsItem): def __init__(self): QtWidgets.QGraphicsItem.__init__(self) self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True) def boundingRect(self): penWidth = 1.0 return QRectF(-10 - penWidth / 2, -10 - penWidth / 2, 20 + penWidth, 20 + penWidth) def paint(self, painter, option, widget): rect = self.boundingRect() painter.drawRect(rect)how can i include this to my canvas ?
scene2 = QGraphicsScene() item = SimpleItem() scene2.addItem(item) -
@SGaist ok I read about it. but my problem is adding an item like this (example of a square) to my canvas
class SimpleItem(QtWidgets.QGraphicsItem): def __init__(self): QtWidgets.QGraphicsItem.__init__(self) self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True) def boundingRect(self): penWidth = 1.0 return QRectF(-10 - penWidth / 2, -10 - penWidth / 2, 20 + penWidth, 20 + penWidth) def paint(self, painter, option, widget): rect = self.boundingRect() painter.drawRect(rect)how can i include this to my canvas ?
scene2 = QGraphicsScene() item = SimpleItem() scene2.addItem(item)@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
how can i include this to my canvas ?
More or less exactly as you show, using void QGraphicsScene::addItem(QGraphicsItem *item). (You will presumably want to set where you want the item and what size it is, maybe a pen too. If this is just supposed to be a rectangle, with perhaps your own
boundingrect(), why not start by deriving from QGraphicsRectItem?) What is the issue? -
@JonB my issue is i don t understand how to integrate it in my code. I am missing something on how to link it to the canvas
``` # OpenGL drawing surface self.canvas = scene.SceneCanvas(keys='interactive') self.canvas.create_native() self.canvas.native.setParent(self) self.view = self.canvas.central_widget.add_view() self.view.bgcolor = '#ffffff' # set the canva to a white background scene2 = QGraphicsScene() item = SimpleItem() scene2.addItem(item) -
@JonB my issue is i don t understand how to integrate it in my code. I am missing something on how to link it to the canvas
``` # OpenGL drawing surface self.canvas = scene.SceneCanvas(keys='interactive') self.canvas.create_native() self.canvas.native.setParent(self) self.view = self.canvas.central_widget.add_view() self.view.bgcolor = '#ffffff' # set the canva to a white background scene2 = QGraphicsScene() item = SimpleItem() scene2.addItem(item)@Pianissimo89
This seems to be something to do with OpenGL, about which I know nothing. So you will have to await someone else's response. -
@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
vispy
I didn't realize that you were using an external library.
I haven't used it yet but it seems that their Shape Draw example could be a good starting point for what you want.
-
@SGaist thank you for the tip. it seems easy to create any line plot for example
data = 500* np.random.normal(size=(2, 2)) plot = scene.Line(data, parent=self.view.scene, color="r")I just have to figure out now how to attach mouse events on it.
-
by adding these two methodes i don t get any prints. why is that?
def on_mouse_press(self, event): print(f"Press: {event.button}= | {event.buttons}=") def on_mouse_release(self, event): print(f"Release: {event.button}= | {event.buttons}=") -
by adding these two methodes i don t get any prints. why is that?
def on_mouse_press(self, event): print(f"Press: {event.button}= | {event.buttons}=") def on_mouse_release(self, event): print(f"Release: {event.button}= | {event.buttons}=")@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
why is that?
Because it's wrong.
Please check correct event handler names here: https://doc.qt.io/qt-6/qwidget.html -
@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
why is that?
Because it's wrong.
Please check correct event handler names here: https://doc.qt.io/qt-6/qwidget.html@jsulm thank you for your help. however i searched bit i am trying this snippet of code. it does not work
def mousePressEvent(self, event): if event.button() == self.fLeftButton: print("pressed left") if event.button() == self.fRightButton: print("pressed right") -
@jsulm thank you for your help. however i searched bit i am trying this snippet of code. it does not work
def mousePressEvent(self, event): if event.button() == self.fLeftButton: print("pressed left") if event.button() == self.fRightButton: print("pressed right")@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
it does not work
Does not print what you expect? Does not get called at all? What class is this method defined inside? Since we do not know what might be in your
self.fLeftButton/fRightButtonnobody can know whether your code is correct. Start by putting in an unconditionalprint()to see you are getting here, after that deal with the button code. -
@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
it does not work
Does not print what you expect? Does not get called at all? What class is this method defined inside? Since we do not know what might be in your
self.fLeftButton/fRightButtonnobody can know whether your code is correct. Start by putting in an unconditionalprint()to see you are getting here, after that deal with the button code.@JonB i put it in class MainWindow after the init (whole code is in the first message) unconditional print independent of buttons also does not print. so it does not detected
-
@JonB i put it in class MainWindow after the init (whole code is in the first message) unconditional print independent of buttons also does not print. so it does not detected
@Pianissimo89
And where are you pressing the mouse over? If I am not mistaken this will only work when directly over the main window, not a sub-widget. You might check it works in a standalone program with just aQMainWindow. -
@Pianissimo89
And where are you pressing the mouse over? If I am not mistaken this will only work when directly over the main window, not a sub-widget. You might check it works in a standalone program with just aQMainWindow.@JonB I see your point. i clicked outside the window we see when running the program (and making the window bigger so we can click outside of the square... he we get the print...)
but this is obviously not what I need. i have trouble understanding where i should put this event so i can get it even when i am on the canvas...
-
@JonB I see your point. i clicked outside the window we see when running the program (and making the window bigger so we can click outside of the square... he we get the print...)
but this is obviously not what I need. i have trouble understanding where i should put this event so i can get it even when i am on the canvas...
@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
when i am on the canvas...
You would need that when you click on the canvas then. But as I wrote at the start I know nothing about how that OpenGL canvas or whatever it is works with Qt. I am not sure whether you would get, or why you would even want, main window mouse click events if you are clicking on some other widget/canvas/outside the main window --- I would expect to handle mouse events there.
-
@Pianissimo89 said in How to integrate a cursor in a QtWidgets app:
when i am on the canvas...
You would need that when you click on the canvas then. But as I wrote at the start I know nothing about how that OpenGL canvas or whatever it is works with Qt. I am not sure whether you would get, or why you would even want, main window mouse click events if you are clicking on some other widget/canvas/outside the main window --- I would expect to handle mouse events there.
@JonB thanks again for the tips. i think i solved the problem by creating a dedicated class
class my_canvas(scene.SceneCanvas): def __init__(self): super().__init__(keys="interactive") def on_mouse_press(self, event): print("hello") -
@JonB thanks again for the tips. i think i solved the problem by creating a dedicated class
class my_canvas(scene.SceneCanvas): def __init__(self): super().__init__(keys="interactive") def on_mouse_press(self, event): print("hello")@Pianissimo89
So it looks like the mouse press you want to capture has nothing to do with Qt and its windows, it's just within the canvas. Which makes sense.