Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Drag and drop widgets onto a MS word-like a4 page
Forum Updated to NodeBB v4.3 + New Features

Drag and drop widgets onto a MS word-like a4 page

Scheduled Pinned Locked Moved Solved Qt for Python
12 Posts 2 Posters 800 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MightyDigits
    wrote on last edited by
    #1

    Hi,

    I'm developing a plotting app, and for reporting purposes, I would like to have the functionality to drag chart types onto a page that looks like an MS Word-like page.

    I would not want the page to be a text edit widget, but rather some sort of grid so that the drops snap in place at some given resolution. Any text should come from a draggable text edit widget added to the page.

    I know how to implement drag/drop part, the widgets, the rendering, and all.
    But I have no clue about how to make an MS Word-like page with A4 proportions, and how to drop widgets at snapping points. I think all the other rearrangement logic etc. will fall into place once I have the page set up.

    I tried some experiments with a QGridLayout, but obviously, that's the wrong choice because I don't think it's wise to predefine sizes of layouts if it's even possible. I think something with a graphics scene maybe?

    Here's some code to at least get a gist of the way I would like to drag widgets in another field:

    from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea
    from PyQt6 import QtGui, QtCore
    from PyQt6.QtCore import Qt, QMimeData
    from PyQt6.QtGui import QDrag, QPixmap
    
    
    class DragButton(QPushButton):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
        def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
            # Not sure if the conditional here is needed (yet)
            if event.buttons() == QtCore.Qt.MouseButton.LeftButton:    
                drag = QDrag(self)
    
                mime_data = QMimeData()
                drag.setMimeData(mime_data)
                drag.setHotSpot(event.pos())
    
                # Code to show what is being dragged
                pixmap = QPixmap(self.size())
                self.render(pixmap)
                drag.setPixmap(pixmap)
    
                drag.exec(Qt.DropAction.MoveAction)     
    
    
    class Window(QWidget):
    
        def __init__(self):
            super().__init__()
            self.setAcceptDrops(True)
    
            self.main_layout = QVBoxLayout()
            self.button_layout = QHBoxLayout()
    
            # We want something like a ScrollArea??
            self.scrollArea = QScrollArea(self)
            self.scrollArea.setWidgetResizable(True)
            self.scrollAreaWidgetContents = QWidget()
    
            self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
            self.scrollArea.setWidget(self.scrollAreaWidgetContents)
    
            for button in ["A", "B", "C", "D"]:
                _button = DragButton(button)
                self.button_layout.addWidget(_button)
    
            self.main_layout.addLayout(self.button_layout)
            self.main_layout.addWidget(self.scrollArea)
            self.setLayout(self.main_layout)
    
            # Test
            self.column = 3
            self.row = 3
    
        def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
            event.accept()
    
        def dropEvent(self, event: QtGui.QDropEvent) -> None:
            widget = event.source()    # Know which widget is triggering
            print(f"Widget:\t{widget}")
    
            event.setDropAction(Qt.DropAction.MoveAction)
    
            button = QPushButton("xyz")
    
            self.gridLayout.addWidget(button, self.column, self.row)
            self.column += 1
            # self.row += 1
    
            event.accept()
    
    
    app = QApplication([])
    w = Window()
    w.show()
    
    app.exec()
    

    Can anyone help me along? Just dropping clues would be welcome as well, the Qt Framework is a bit overwhelming to me.

    Regards,

    Roddy

    M 1 Reply Last reply
    0
    • M MightyDigits

      Hi,

      I'm developing a plotting app, and for reporting purposes, I would like to have the functionality to drag chart types onto a page that looks like an MS Word-like page.

      I would not want the page to be a text edit widget, but rather some sort of grid so that the drops snap in place at some given resolution. Any text should come from a draggable text edit widget added to the page.

      I know how to implement drag/drop part, the widgets, the rendering, and all.
      But I have no clue about how to make an MS Word-like page with A4 proportions, and how to drop widgets at snapping points. I think all the other rearrangement logic etc. will fall into place once I have the page set up.

      I tried some experiments with a QGridLayout, but obviously, that's the wrong choice because I don't think it's wise to predefine sizes of layouts if it's even possible. I think something with a graphics scene maybe?

      Here's some code to at least get a gist of the way I would like to drag widgets in another field:

      from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea
      from PyQt6 import QtGui, QtCore
      from PyQt6.QtCore import Qt, QMimeData
      from PyQt6.QtGui import QDrag, QPixmap
      
      
      class DragButton(QPushButton):
      
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
      
          def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
              # Not sure if the conditional here is needed (yet)
              if event.buttons() == QtCore.Qt.MouseButton.LeftButton:    
                  drag = QDrag(self)
      
                  mime_data = QMimeData()
                  drag.setMimeData(mime_data)
                  drag.setHotSpot(event.pos())
      
                  # Code to show what is being dragged
                  pixmap = QPixmap(self.size())
                  self.render(pixmap)
                  drag.setPixmap(pixmap)
      
                  drag.exec(Qt.DropAction.MoveAction)     
      
      
      class Window(QWidget):
      
          def __init__(self):
              super().__init__()
              self.setAcceptDrops(True)
      
              self.main_layout = QVBoxLayout()
              self.button_layout = QHBoxLayout()
      
              # We want something like a ScrollArea??
              self.scrollArea = QScrollArea(self)
              self.scrollArea.setWidgetResizable(True)
              self.scrollAreaWidgetContents = QWidget()
      
              self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
              self.scrollArea.setWidget(self.scrollAreaWidgetContents)
      
              for button in ["A", "B", "C", "D"]:
                  _button = DragButton(button)
                  self.button_layout.addWidget(_button)
      
              self.main_layout.addLayout(self.button_layout)
              self.main_layout.addWidget(self.scrollArea)
              self.setLayout(self.main_layout)
      
              # Test
              self.column = 3
              self.row = 3
      
          def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
              event.accept()
      
          def dropEvent(self, event: QtGui.QDropEvent) -> None:
              widget = event.source()    # Know which widget is triggering
              print(f"Widget:\t{widget}")
      
              event.setDropAction(Qt.DropAction.MoveAction)
      
              button = QPushButton("xyz")
      
              self.gridLayout.addWidget(button, self.column, self.row)
              self.column += 1
              # self.row += 1
      
              event.accept()
      
      
      app = QApplication([])
      w = Window()
      w.show()
      
      app.exec()
      

      Can anyone help me along? Just dropping clues would be welcome as well, the Qt Framework is a bit overwhelming to me.

      Regards,

      Roddy

      M Offline
      M Offline
      MightyDigits
      wrote on last edited by
      #2

      An update. So I have a graphicsview and graphicsscene.

      The peculiar part is that I cannot drop into the scene, only outside of it in the view. It does get added to the scene when dropping.

      How to resolve this issue, and basically inverse this behavior (not droppable outside of scene, droppable inside it).?

      Code below:

      import math
      
      from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea, QGraphicsGridLayout, QGraphicsView, QGraphicsScene
      from PyQt6 import QtGui, QtCore
      from PyQt6.QtCore import Qt, QMimeData
      from PyQt6.QtGui import QDrag, QPixmap
      
      
      class CustomGraphicsScene(QGraphicsScene):
          def __init__(self, parent=None):
              super(QGraphicsScene, self).__init__(parent)
      
          # def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
          #     event.accept()
          #
          # def dropEvent(self, event: QtGui.QDropEvent) -> None:
          #     widget = event.source()    # Know which widget is triggering
          #     print(f"Widget:\t{widget}")
          #
          #     event.setDropAction(Qt.DropAction.MoveAction)
          #
          #     button = QPushButton("xyz")
          #
          #     # widget.setParent(self.graphics_view)
          #
          #     self.addWidget(button)
          #     event.accept()
      
      
      class DragButton(QPushButton):
      
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
      
          def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
              # Not sure if the conditional here is needed (yet)
              if event.buttons() == QtCore.Qt.MouseButton.LeftButton:    # Must use buttons(), not button()
                  drag = QDrag(self)
      
                  mime_data = QMimeData()
                  drag.setMimeData(mime_data)
                  drag.setHotSpot(event.pos())
      
                  # Code to show what is being dragged
                  pixmap = QPixmap(self.size())
                  self.render(pixmap)
                  drag.setPixmap(pixmap)
      
                  drag.exec(Qt.DropAction.MoveAction)     # Event loop blocking the main loop until complete
      
      
      class Window(QWidget):
      
          def __init__(self):
              super().__init__()
              self.setAcceptDrops(True)
      
              self.main_layout = QVBoxLayout()
              self.button_layout = QHBoxLayout()
      
              self.graphics_scene = CustomGraphicsScene(parent=self)
      
              # Make a graphics view and add it to the main_layout as the 2nd widget
              self.graphics_view = QGraphicsView()
              self.graphics_view.setScene(self.graphics_scene)
              self.graphics_view.setAcceptDrops(True)
              page_size = 300
              self.graphics_view.setFixedSize(page_size, int(page_size*(math.sqrt(2))))
      
              # We want something like a ScrollArea??
              self.scrollArea = QScrollArea(self)
              self.scrollArea.setWidgetResizable(True)
      
              self.scrollArea.setWidget(self.graphics_view)
      
              for button in ["A", "B", "C", "D"]:
                  _button = DragButton(button)
                  self.button_layout.addWidget(_button)
      
              self.main_layout.addLayout(self.button_layout)
              self.main_layout.addWidget(self.scrollArea)
              self.setLayout(self.main_layout)
      
              # Test
              self.column = 3
              self.row = 3
      
          def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
              event.accept()
      
          def dropEvent(self, event: QtGui.QDropEvent) -> None:
              widget = event.source()    # Know which widget is triggering
              print(f"Widget:\t{widget}")
              position = event.position()
      
              event.setDropAction(Qt.DropAction.MoveAction)
      
              button = QPushButton("xyz")
      
              self.graphics_scene.addWidget(button)
      
              event.accept()
      
      
      app = QApplication([])
      w = Window()
      w.show()
      
      app.exec()
      
      SGaistS 1 Reply Last reply
      0
      • M MightyDigits

        An update. So I have a graphicsview and graphicsscene.

        The peculiar part is that I cannot drop into the scene, only outside of it in the view. It does get added to the scene when dropping.

        How to resolve this issue, and basically inverse this behavior (not droppable outside of scene, droppable inside it).?

        Code below:

        import math
        
        from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea, QGraphicsGridLayout, QGraphicsView, QGraphicsScene
        from PyQt6 import QtGui, QtCore
        from PyQt6.QtCore import Qt, QMimeData
        from PyQt6.QtGui import QDrag, QPixmap
        
        
        class CustomGraphicsScene(QGraphicsScene):
            def __init__(self, parent=None):
                super(QGraphicsScene, self).__init__(parent)
        
            # def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
            #     event.accept()
            #
            # def dropEvent(self, event: QtGui.QDropEvent) -> None:
            #     widget = event.source()    # Know which widget is triggering
            #     print(f"Widget:\t{widget}")
            #
            #     event.setDropAction(Qt.DropAction.MoveAction)
            #
            #     button = QPushButton("xyz")
            #
            #     # widget.setParent(self.graphics_view)
            #
            #     self.addWidget(button)
            #     event.accept()
        
        
        class DragButton(QPushButton):
        
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
        
            def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
                # Not sure if the conditional here is needed (yet)
                if event.buttons() == QtCore.Qt.MouseButton.LeftButton:    # Must use buttons(), not button()
                    drag = QDrag(self)
        
                    mime_data = QMimeData()
                    drag.setMimeData(mime_data)
                    drag.setHotSpot(event.pos())
        
                    # Code to show what is being dragged
                    pixmap = QPixmap(self.size())
                    self.render(pixmap)
                    drag.setPixmap(pixmap)
        
                    drag.exec(Qt.DropAction.MoveAction)     # Event loop blocking the main loop until complete
        
        
        class Window(QWidget):
        
            def __init__(self):
                super().__init__()
                self.setAcceptDrops(True)
        
                self.main_layout = QVBoxLayout()
                self.button_layout = QHBoxLayout()
        
                self.graphics_scene = CustomGraphicsScene(parent=self)
        
                # Make a graphics view and add it to the main_layout as the 2nd widget
                self.graphics_view = QGraphicsView()
                self.graphics_view.setScene(self.graphics_scene)
                self.graphics_view.setAcceptDrops(True)
                page_size = 300
                self.graphics_view.setFixedSize(page_size, int(page_size*(math.sqrt(2))))
        
                # We want something like a ScrollArea??
                self.scrollArea = QScrollArea(self)
                self.scrollArea.setWidgetResizable(True)
        
                self.scrollArea.setWidget(self.graphics_view)
        
                for button in ["A", "B", "C", "D"]:
                    _button = DragButton(button)
                    self.button_layout.addWidget(_button)
        
                self.main_layout.addLayout(self.button_layout)
                self.main_layout.addWidget(self.scrollArea)
                self.setLayout(self.main_layout)
        
                # Test
                self.column = 3
                self.row = 3
        
            def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None:
                event.accept()
        
            def dropEvent(self, event: QtGui.QDropEvent) -> None:
                widget = event.source()    # Know which widget is triggering
                print(f"Widget:\t{widget}")
                position = event.position()
        
                event.setDropAction(Qt.DropAction.MoveAction)
        
                button = QPushButton("xyz")
        
                self.graphics_scene.addWidget(button)
        
                event.accept()
        
        
        app = QApplication([])
        w = Window()
        w.show()
        
        app.exec()
        
        SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by SGaist
        #3

        Hi and welcome to devnet,

        You need to implement the dragMoveEvent as well.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        M 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi and welcome to devnet,

          You need to implement the dragMoveEvent as well.

          M Offline
          M Offline
          MightyDigits
          wrote on last edited by
          #4

          @SGaist To me it seems like it's because the scene cannot accept drops.

          How would the dragMoveEvent suddenly make me be able to drop into the scene, when without it I can drop anywhere but the scene, so long as I set setAcceptDrops to True?

          SGaistS 1 Reply Last reply
          0
          • M MightyDigits

            @SGaist To me it seems like it's because the scene cannot accept drops.

            How would the dragMoveEvent suddenly make me be able to drop into the scene, when without it I can drop anywhere but the scene, so long as I set setAcceptDrops to True?

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            If you want custom drag and drop you must do it at the view level. The scene handles scene related drag and drop.

            dragEnterEvent enables the handling of DnD, dragMoveEvent, handles where it should happen and then dropEvent for the actual drop.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            M 1 Reply Last reply
            2
            • SGaistS SGaist

              If you want custom drag and drop you must do it at the view level. The scene handles scene related drag and drop.

              dragEnterEvent enables the handling of DnD, dragMoveEvent, handles where it should happen and then dropEvent for the actual drop.

              M Offline
              M Offline
              MightyDigits
              wrote on last edited by
              #6

              @SGaist Got it to work. Thanks a lot!

              SGaistS 1 Reply Last reply
              0
              • M MightyDigits

                @SGaist Got it to work. Thanks a lot!

                SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @MightyDigits you're welcome !

                Since you have it working now, please mark the thread as solved using the "Topic Tools" button or the three doted menu beside the answer you deem correct so other forum members may know a solution has been found :-)

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                M 1 Reply Last reply
                0
                • M MightyDigits has marked this topic as solved on
                • SGaistS SGaist

                  @MightyDigits you're welcome !

                  Since you have it working now, please mark the thread as solved using the "Topic Tools" button or the three doted menu beside the answer you deem correct so other forum members may know a solution has been found :-)

                  M Offline
                  M Offline
                  MightyDigits
                  wrote on last edited by
                  #8

                  @SGaist Share the code as well?

                  SGaistS 1 Reply Last reply
                  0
                  • M MightyDigits

                    @SGaist Share the code as well?

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @MightyDigits that would be nice as well ! It might help other people having the same issue :-)

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    M 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      @MightyDigits that would be nice as well ! It might help other people having the same issue :-)

                      M Offline
                      M Offline
                      MightyDigits
                      wrote on last edited by
                      #10

                      @SGaist

                      Sure, below is the code.

                      Still having trouble with dropping the buttons at the right place. I have experience mapping ROI's from pyqtgraph into views, but PyQt is different. Tried all mapping options and followed some examples, but nothing is giving me what I want. Some of these little functionalities takes hours and hours without success...

                      The coordinates of the view/scene and buttons do not align, so how to achieve that?

                      import math
                      
                      from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea, QGraphicsGridLayout, QGraphicsView, QGraphicsScene
                      from PyQt6 import QtGui, QtCore
                      from PyQt6.QtCore import Qt, QMimeData
                      from PyQt6.QtGui import QDrag, QPixmap
                      
                      
                      class CustomGraphicsView(QGraphicsView):
                          def __init__(self, parent=None):
                              super(QGraphicsView, self).__init__(parent)
                              self.setAcceptDrops(True)
                      
                          def dragMoveEvent(self, event: QtGui.QDragMoveEvent) -> None:
                              if event.mimeData().hasImage():
                                  event.acceptProposedAction()
                      
                          def dropEvent(self, event):
                              print("In dropEvent of VIEW")
                              if self.scene():
                                  event.accept()
                      
                                  button = DragButton("XYZ")
                                  point = button.mapFromGlobal(event.position())
                      
                                  try:
                                      button.move(point)
                                      self.scene().addWidget(button)
                                      print("Button moved")
                                  except Exception as e:
                                      print(e)
                              event.acceptProposedAction()
                      
                      
                      class CustomGraphicsScene(QGraphicsScene):
                          def __init__(self, parent=None):
                              super(QGraphicsScene, self).__init__(parent)
                      
                      
                      class DragButton(QPushButton):
                      
                          def __init__(self, *args, **kwargs):
                              super().__init__(*args, **kwargs)
                              
                          def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
                              print("In mousemovevent of dragbutton")
                              drag = QDrag(self)
                              
                              mime_data = QMimeData()
                              mime_data.setText(f"{event.pos().x()}, {event.pos().y()}")
                      
                              drag.setMimeData(mime_data)
                              drag.setHotSpot(event.pos())
                      
                              pixmap = QPixmap(self.size())
                              self.render(pixmap)
                              drag.setPixmap(pixmap)
                      
                              drag.exec(Qt.DropAction.MoveAction)     # Event loop blocking the main loop until complete
                      
                          
                      class Window(QWidget):
                      
                          def __init__(self):
                              super().__init__()
                              self.setFixedSize(960, 540)
                      
                              self.main_layout = QVBoxLayout()
                              self.button_layout = QHBoxLayout()
                      
                              self.graphics_scene = CustomGraphicsScene(parent=self)
                      
                              self.graphics_view = CustomGraphicsView(self)
                              self.graphics_view.setScene(self.graphics_scene)
                              page_size = 300
                              self.graphics_view.setFixedSize(page_size, int(page_size*(math.sqrt(2))))
                      
                              self.scrollArea = QScrollArea(self)
                              self.scrollArea.setAcceptDrops(True)
                              self.scrollArea.setWidgetResizable(True)
                      
                              self.scrollArea.setWidget(self.graphics_view)
                      
                              for button in ["A", "B", "C", "D"]:
                                  _button = DragButton(button)
                                  self.button_layout.addWidget(_button)
                      
                              self.main_layout.addLayout(self.button_layout)
                              self.main_layout.addWidget(self.scrollArea)
                              self.setLayout(self.main_layout)
                      
                      
                      app = QApplication([])
                      w = Window()
                      w.show()
                      
                      app.exec()
                      
                      SGaistS 1 Reply Last reply
                      0
                      • M MightyDigits

                        @SGaist

                        Sure, below is the code.

                        Still having trouble with dropping the buttons at the right place. I have experience mapping ROI's from pyqtgraph into views, but PyQt is different. Tried all mapping options and followed some examples, but nothing is giving me what I want. Some of these little functionalities takes hours and hours without success...

                        The coordinates of the view/scene and buttons do not align, so how to achieve that?

                        import math
                        
                        from PyQt6.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget, QPushButton, QGridLayout, QScrollArea, QGraphicsGridLayout, QGraphicsView, QGraphicsScene
                        from PyQt6 import QtGui, QtCore
                        from PyQt6.QtCore import Qt, QMimeData
                        from PyQt6.QtGui import QDrag, QPixmap
                        
                        
                        class CustomGraphicsView(QGraphicsView):
                            def __init__(self, parent=None):
                                super(QGraphicsView, self).__init__(parent)
                                self.setAcceptDrops(True)
                        
                            def dragMoveEvent(self, event: QtGui.QDragMoveEvent) -> None:
                                if event.mimeData().hasImage():
                                    event.acceptProposedAction()
                        
                            def dropEvent(self, event):
                                print("In dropEvent of VIEW")
                                if self.scene():
                                    event.accept()
                        
                                    button = DragButton("XYZ")
                                    point = button.mapFromGlobal(event.position())
                        
                                    try:
                                        button.move(point)
                                        self.scene().addWidget(button)
                                        print("Button moved")
                                    except Exception as e:
                                        print(e)
                                event.acceptProposedAction()
                        
                        
                        class CustomGraphicsScene(QGraphicsScene):
                            def __init__(self, parent=None):
                                super(QGraphicsScene, self).__init__(parent)
                        
                        
                        class DragButton(QPushButton):
                        
                            def __init__(self, *args, **kwargs):
                                super().__init__(*args, **kwargs)
                                
                            def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
                                print("In mousemovevent of dragbutton")
                                drag = QDrag(self)
                                
                                mime_data = QMimeData()
                                mime_data.setText(f"{event.pos().x()}, {event.pos().y()}")
                        
                                drag.setMimeData(mime_data)
                                drag.setHotSpot(event.pos())
                        
                                pixmap = QPixmap(self.size())
                                self.render(pixmap)
                                drag.setPixmap(pixmap)
                        
                                drag.exec(Qt.DropAction.MoveAction)     # Event loop blocking the main loop until complete
                        
                            
                        class Window(QWidget):
                        
                            def __init__(self):
                                super().__init__()
                                self.setFixedSize(960, 540)
                        
                                self.main_layout = QVBoxLayout()
                                self.button_layout = QHBoxLayout()
                        
                                self.graphics_scene = CustomGraphicsScene(parent=self)
                        
                                self.graphics_view = CustomGraphicsView(self)
                                self.graphics_view.setScene(self.graphics_scene)
                                page_size = 300
                                self.graphics_view.setFixedSize(page_size, int(page_size*(math.sqrt(2))))
                        
                                self.scrollArea = QScrollArea(self)
                                self.scrollArea.setAcceptDrops(True)
                                self.scrollArea.setWidgetResizable(True)
                        
                                self.scrollArea.setWidget(self.graphics_view)
                        
                                for button in ["A", "B", "C", "D"]:
                                    _button = DragButton(button)
                                    self.button_layout.addWidget(_button)
                        
                                self.main_layout.addLayout(self.button_layout)
                                self.main_layout.addWidget(self.scrollArea)
                                self.setLayout(self.main_layout)
                        
                        
                        app = QApplication([])
                        w = Window()
                        w.show()
                        
                        app.exec()
                        
                        SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        From the looks of it, you did not mapToScene.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        M 1 Reply Last reply
                        1
                        • SGaistS SGaist

                          From the looks of it, you did not mapToScene.

                          M Offline
                          M Offline
                          MightyDigits
                          wrote on last edited by
                          #12

                          @SGaist First thing I tried was mapToScene(), but that didn't work.

                          What worked, is defining the sceneRect for the scene. Without it, there apparently are no native coordinates and they get set on the fly with each button drop, with the first drop being dead center in the scene.

                          All I had to do is add the following line:

                          self.graphics_scene = CustomGraphicsScene(parent=self)
                          # ADDED THE FOLLOWING LINE:
                          self.graphics_scene.setSceneRect(0, 0, page_size, int(page_size*math.sqrt(2)))
                          
                          self.graphics_view = CustomGraphicsView(self)
                          

                          There's still some polishing like scrollarea showing the scrollbars, basically just not slightly showing the full rect. If I increase the size of the scrollarea, it doesn't solve it. But that stuff is for worries later on.

                          Thanks anyway, you're a great help!

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved