Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] Drag and dropping widgets in a grid at runtime
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Drag and dropping widgets in a grid at runtime

Scheduled Pinned Locked Moved General and Desktop
drag and dropruntimewidgetpyqt
11 Posts 2 Posters 8.3k Views 2 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.
  • S Offline
    S Offline
    SGaist
    Lifetime Qt Champion
    wrote on 17 Apr 2015, 21:46 last edited by
    #2

    Hi,

    What about creating a QStyledItemDelegate that will show the information the way you want them ? Doing so you'll have the drag & drop feature for free without reimplementing QTableView/Widget.

    Hope it helps

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

    1 Reply Last reply
    1
    • W Offline
      W Offline
      wlof
      wrote on 18 Apr 2015, 10:14 last edited by
      #3

      Hi,

      Thanks for the suggestion, it seems very promising! I've tried a few things and I think I'm much closer to my goal.

      I'm wondering how best to "link" my custom widget to the delegate. I found this Stack Overflow thread, but creating the widget inside the paint() method is not a usable solution in practice. I need to create each widget only once and have the delegate somehow be aware of them so it can render them.

      In this other Stack Overflow thread, someone commented "AFAIK, you can't use custom widgets for viewing items in a List/Table/Tree-View-delegates. You can use them for editing, but if the view-mode requires anything other than just a redraw, you're pretty stumped."

      Any further ideas?

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 18 Apr 2015, 23:19 last edited by
        #4

        Do you really need to render a widget to show your data ?

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

        1 Reply Last reply
        0
        • W Offline
          W Offline
          wlof
          wrote on 19 Apr 2015, 14:07 last edited by
          #5

          Sadly, yes. Data is pulled from a backend, the widget needs to be registered in another class so the data gets refreshed. This is an existing (badly designed) system, and the widget is just too tightly coupled with so many other things.

          I guess I'm SOL... Obviously the proper way to use widgets in a QTableWidget is through the setCellWidget() method, which doesn't support my "reorganizing at runtime" usecase. I'll take a look at the QTableWidget's source code and see if it's feasible to adapt the drag and drop logic to widgets.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 19 Apr 2015, 20:22 last edited by
            #6

            Don't be sad so early. What would you like to have ? Something like a vertical list of your widgets ? e.g. like a QScrollArea containing a widget with a QVBoxLayout filled with your special widget ?

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

            1 Reply Last reply
            0
            • W Offline
              W Offline
              wlof
              wrote on 19 Apr 2015, 21:11 last edited by
              #7

              Something like that, yes. Check out the mini-project I included in the first post if you can, it should illustrate what I want.

              My first prototype was actually a QScrollArea with a QVBoxLayout. I figured if I could make the drag and drop work, then turning the vertical list into a 2D grid wouldn't be too difficult, but I couldn't make the drag and drop work in the first place, and thus was hoping for some other Qt goodness that would do what I want out of the box...

              1 Reply Last reply
              0
              • S Offline
                S Offline
                SGaist
                Lifetime Qt Champion
                wrote on 19 Apr 2015, 21:46 last edited by
                #8

                Since you depend on that widget (are you sure you can't reimplement it to be cleaner ?) Then you should add the drag handling to it (putting e.g. a pointer to the widget in the QDrag mime data) and have the widget in the QScrollArea handle the drop.

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

                1 Reply Last reply
                0
                • W Offline
                  W Offline
                  wlof
                  wrote on 19 Apr 2015, 22:52 last edited by
                  #9

                  Actually, I think I managed to do what I want by deriving QTableWidget and reimplementing the dropEvent() method.

                  Due to the way QAbstractListView manages the list of widgets attached to indexes, I can't just move the existing widget around. Doing the following:

                  widget = self.cellWidget(orig_row, orig_column)
                  self.setCellWidget(dest_row, dest_column)
                  

                  won't work because internally, QAbstractListView::setIndexWidget() will delete the "old" widget first. Except in this case, the "old" and "new" widget are one and the same, so I'll have to add a clone() method to my widget. I'll have to see how it works in practice, but I think this will work.

                  In case anyone is interested, here is an updated version of the project in the first post, with my solution: https://gist.github.com/anonymous/6bd244c8ca30fee10918

                  Thanks a lot for your help and suggestions, SGaist!

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 20 Apr 2015, 22:12 last edited by
                    #10

                    One thing you have to also take into account: how many of these widgets will you have at the same time ?

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

                    1 Reply Last reply
                    0
                    • W Offline
                      W Offline
                      wlof
                      wrote on 24 Apr 2015, 17:42 last edited by wlof
                      #11

                      Inside the QTableWidget, I'm guessing I'll have ~100 of my custom widgets at most.

                      In other use cases (i.e. not in the QTableWidget, but in static layouts), I've had up to 4000 of these widgets, with a few hundred being active (i.e. actively refreshing their data from the backend) at the same time, without any serious performance issues, so I know it scales relatively well.

                      Also, to elaborate on the solution I offered above: cloning the custom widget proved difficult, because it has a lot of properties (I simplified the problem, the "custom widget" is actually a family of different widgets to fit different data), and because copying Qt objects is not trivial (see http://doc.qt.io/qt-5/object.html#identity-vs-value).

                      What I ended up doing was write a ContainerWidget to go along the GridWidget. The ContainerWidget has a layout with no margins and is used to display another widget through a setContainedWidget() method. I also added a cloneAndPassContainedWidget() method that does what you'd expect: it returns a new ContainerWidget and gives it ownership of the contained widget. Obviously, after calling the method the original ContainerWidget becomes useless, but the method is called precisely because the original ContainerWidget is set to be destroyed, so that's not a problem. I can now use my GridWidget to display any kind of widgets, it's pretty neat! (I wrote "widget" too many times!)

                      I realize the "proper" way would have been to write a model, views, and delegates, but that would have required a lot more work.

                      EDIT: Here's my updated solution: https://gist.github.com/anonymous/a3b2d7e61c6b3e11742c

                      1 Reply Last reply
                      0
                      • P Pl45m4 referenced this topic on 18 Apr 2024, 15:14

                      11/11

                      24 Apr 2015, 17:42

                      • Login

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