Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Ideal way to show markable text in QGraphicsScene



  • My question is related to this question (https://forum.qt.io/topic/120114/how-to-select-only-part-of-a-text-of-qgraphictextitem) but more general now.

    My setup:
    Python 3.7.3
    PySide2 5.15.1
    OS: Debian

    (I am quite a novice to Qt and GUI programming in general, just to provide some background)

    I am showing text on a QGraphicsScene via using QGraphicsTextItem.

    Everything works well so far. But I am really struggling with comming up with a solution in order to mark only parts of the text via mouse (click-drag-relase) like I would do in a webbrowser or in a word doc.

    EDIT: The marked text then also needs to be copyable.

    I was able to make the text selectable via setTextInteractionFlags(QtGui.Qt.TextSelectableByMouse) but this way I can only select the entire text of the QGraphicsTextItem.

    So my questions:

    • Is QGraphicsTextItem the right type of widget for this? Is there anything better suited?
    • If it is the right type of widget: Can anyone hint me the right direction? Do I have to inherit QGraphicsTextItem and to catch the mouse events and do something on my own? Can I do this in PySide2? Or is there an already implemented way to do this?

    So thankful for a hint!
    Michael


  • Lifetime Qt Champion

    Hi,

    Can you provide a minimal runnable script that allows to test your issue ?



  • Oh, while trying to set up a minimal example I discovered that QGraphicsTextIteam actually by default DOES what I want.

    The problem is that I defined a new class deriving QGraphicsTextIteam and there I seem to have messed up!

    I will make a minimal example with this new class and post it as soon as I am done.



  • @SGaist

    Now I have a working example. The problem was that I did not propagate the event (super().mousePressEvent(event)).

    But now I have another problem. The application crahes with a segfault as soon as I do a right click. Probably this is my fault as well but I do not see what could cause it...

    Here the minimal example:

    from PySide2 import QtWidgets, QtCore, QtGui
    
    class TextItem(QtWidgets.QGraphicsTextItem):
    	
    	def __init__(self):
    		QtWidgets.QGraphicsTextItem.__init__(self)
    
    	def mousePressEvent(self, event):
    
    		if(event.button() == QtCore.Qt.MouseButton.LeftButton):		
    			print("left button")
    
    		if(event.button() == QtCore.Qt.MouseButton.RightButton):		
    			print("right button")
    
    		super().mousePressEvent(event)
    
    
    class MainWindow(QtWidgets.QMainWindow):
    
    	def __init__(self):
    
    		super().__init__()
    
    		self.setWindowTitle("Window title")
    
    		self.scene = QtWidgets.QGraphicsScene()
    		self.view = QtWidgets.QGraphicsView(self.scene)
    
    		self.layout = QtWidgets.QHBoxLayout()
    		self.layout.addWidget(self.view)
    		self.setLayout(self.layout)
    
    		self.setCentralWidget(self.view)
    
    
    app = QtWidgets.QApplication([])
    
    window = MainWindow()
    window.resize(400, 100)
    window.show()
    
    text = TextItem()
    text.setTextInteractionFlags(QtGui.Qt.TextSelectableByMouse)
    text.setHtml("This is a test text text text text text text text text ...")
    window.scene.addItem(text)
    
    app.exec_()
    


  • If I add this I do not get a segfault anymore:

    def contextMenuEvent(self, event):
    	event.ignore()
    

    Is this a bug or a problem on my side?



  • @MS_GX said in Ideal way to show markable text in QGraphicsScene:

    The application crahes with a segfault as soon as I do a right click.

    So do you run it from inside debugger and get the stack trace to see the cause? That's how we debug programs.



  • @JonB

    Thanks much!

    I did some debugging and got the following (without capturing the contextMenuEvent for right button obviously):

    (gdb) file python
    Reading symbols from python...(no debugging symbols found)...done.
    (gdb) run /home/user/SW/minimal_example/example.py
    Starting program: /home/user/SW/venv/bin/python /home/user/SW/minimal_example/example.py
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    [New Thread 0x7ffff4299700 (LWP 11120)]
    [New Thread 0x7ffff1a98700 (LWP 11121)]
    [New Thread 0x7fffef297700 (LWP 11122)]
    Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
    [New Thread 0x7fffe1efa700 (LWP 11123)]
    [New Thread 0x7fffdb76d700 (LWP 11124)]
    [New Thread 0x7fffdaf4b700 (LWP 11125)]
    [New Thread 0x7fffda71e700 (LWP 11126)]
    [New Thread 0x7fffd9f0c700 (LWP 11127)]
    [New Thread 0x7fffcb5ba700 (LWP 11128)]
    [New Thread 0x7fffcadb9700 (LWP 11129)]
    right button
    
    Thread 1 "python" received signal SIGSEGV, Segmentation fault.
    0x00007fffe91d3b58 in QWidget::window() const ()
       from /home/user/Software/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    
    


  • @MS_GX
    When the seg fault happens you need to look at the stack trace. That is a window if your are debugging inside Qt Creator, or the bt command if you are running gdb manually.

    Having said. I'm not sure I appreciated you are running Python. I'm not certain gdb stack trace will be useful there, I don't know whether if you run inside a Python debugger you will have more joy.

    Having said that: I just pasted your code and tried here on my Ubuntu 20.04/GNOME, and right-click was fine, it brought up the internal "Copy" menu.



  • @JonB Thanks for the hints! Are you running Wayland or X11? Because I am running Wayland and I get this wayland warning there. Do you think that this might cause the problem?

    Anyway, I will try to debug as you said. Many thanks!



  • @MS_GX
    Yup, I wouldn't know what "Wayland" was if it smacked me upside the head ;-) I am X11, vanilla Ubuntu 20.04 inside a vanilla Windows (7) PC with a vanilla gfx card/monitor. All drivers up-to-date.



  • @JonB

    Here the stacktrace for now. Not sure if helpful since I am not able to judge this to be honest.

    (gdb) bt
    #0  0x00007fffe91d3b58 in QWidget::window() const ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #1  0x00007fffe9389156 in QWidgetTextControlPrivate::contextMenuEvent(QPoint const&, QPointF const&, QWidget*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #2  0x00007fffe9389a9c in QWidgetTextControl::processEvent(QEvent*, QTransform const&, QWidget*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #3  0x00007fffe938065b in QWidgetTextControl::processEvent(QEvent*, QPointF const&, QWidget*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #4  0x00007fffe9472ecc in QGraphicsTextItem::dropEvent(QGraphicsSceneDragDropEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #5  0x00007fffe9e2ec2f in QGraphicsTextItemWrapper::contextMenuEvent(QGraphicsSceneContextMenuEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #6  0x00007fffe947f7e1 in QGraphicsItem::sceneEvent(QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #7  0x00007fffe947f985 in QGraphicsTextItem::sceneEvent(QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #8  0x00007fffe9e33c1d in QGraphicsTextItemWrapper::sceneEvent(QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #9  0x00007fffe94a02ed in QGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #10 0x00007fffe9e165b7 in QGraphicsSceneWrapper::contextMenuEvent(QGraphicsSceneContextMenuEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #11 0x00007fffe94b0bd5 in QGraphicsScene::event(QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #12 0x00007fffe9e1802d in QGraphicsSceneWrapper::event(QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #13 0x00007fffe91ad3cc in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #14 0x00007fffe91b3eb0 in QApplication::notify(QObject*, QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #15 0x00007fffe9c835a5 in QApplicationWrapper::notify(QObject*, QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #16 0x00007fffe81bf0e8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
       from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    --Type <RET> for more, q to quit, c to continue without paging--c
    #17 0x00007fffe94ce8a2 in QGraphicsView::contextMenuEvent(QContextMenuEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #18 0x00007fffe9e40d67 in QGraphicsViewWrapper::contextMenuEvent(QContextMenuEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #19 0x00007fffe91ec398 in QWidget::event(QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #20 0x00007fffe929400e in QFrame::event(QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #21 0x00007fffe94ce2ab in QGraphicsView::viewportEvent(QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #22 0x00007fffe9e48d9d in QGraphicsViewWrapper::viewportEvent(QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #23 0x00007fffe81bee80 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #24 0x00007fffe91ad3a2 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #25 0x00007fffe91b5504 in QApplication::notify(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #26 0x00007fffe9c835a5 in QApplicationWrapper::notify(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #27 0x00007fffe81bf0e8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #28 0x00007fffe92050ca in QWidgetWindow::handleMouseEvent(QMouseEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #29 0x00007fffe9207c83 in QWidgetWindow::event(QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #30 0x00007fffe91ad3cc in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #31 0x00007fffe91b3eb0 in QApplication::notify(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
    #32 0x00007fffe9c835a5 in QApplicationWrapper::notify(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #33 0x00007fffe81bf0e8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #34 0x00007fffe88886d6 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
    #35 0x00007fffe8889ae5 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
    #36 0x00007fffe88658cb in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
    #37 0x00007fffe2e4157a in xcbSourceDispatch(_GSource*, int (*)(void*), void*) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/plugins/platforms/../../lib/libQt5XcbQpa.so.5
    #38 0x00007fffe5134f2e in g_main_context_dispatch () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #39 0x00007fffe51351c8 in ?? () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #40 0x00007fffe513525c in g_main_context_iteration () from /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #41 0x00007fffe821aaac in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #42 0x00007fffe81bdafa in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #43 0x00007fffe81c6ab3 in QCoreApplication::exec() () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/Qt/lib/libQt5Core.so.5
    #44 0x00007fffe9c81038 in Sbk_QApplicationFunc_exec_ () from /home/user/SW/venv/lib/python3.7/site-packages/PySide2/QtWidgets.abi3.so
    #45 0x00000000005d7061 in _PyMethodDef_RawFastCallKeywords ()
    #46 0x000000000054aac0 in ?? ()
    #47 0x0000000000551bf9 in _PyEval_EvalFrameDefault ()
    #48 0x000000000054b452 in _PyEval_EvalCodeWithName ()
    #49 0x000000000054d7f3 in PyEval_EvalCode ()
    #50 0x0000000000630152 in ?? ()
    #51 0x0000000000630207 in PyRun_FileExFlags ()
    #52 0x0000000000630e6f in PyRun_SimpleFileExFlags ()
    #53 0x0000000000653eae in ?? ()
    #54 0x000000000065420e in _Py_UnixMain ()
    #55 0x00007ffff79c109b in __libc_start_main (main=0x4bc8d0 <main>, argc=2, argv=0x7fffffffd748, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd738) at ../csu/libc-start.c:308
    #56 0x00000000005df66a in _start ()
    

Log in to reply