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. Custom QListWidget

Custom QListWidget

Scheduled Pinned Locked Moved General and Desktop
10 Posts 2 Posters 5.1k Views
  • 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
    maximus
    wrote on 10 Apr 2014, 14:42 last edited by
    #1

    Hi guys,

    I'm trying to create an interface like this :
    https://www.dropbox.com/s/owzgk3bq7k9ix3f/interface.png

    I previously tried with QListView and custom model, and failed hard (was complex to code and was not happy with the result), so i'm trying a new approach.

    I want to use QListWidget and QListWidgetItem. Each box would be a QListWidgetItem (a custom widget I create)
    I started up a basic example :
    https://www.dropbox.com/s/nei0gqjs889jp9y/current.png

    The "add" button call this slot, which is supposed to add my custom Widget in the QListWidget:

    @void WorkoutCreator::on_pushButton_addStep_clicked()
    {
    QListWidgetItem *newItem = new QListWidgetItem;
    newItem->setText("itemText");

    IntervalWidget *intervalWidget = new IntervalWidget();
    ui->listWidget->setItemWidget(newItem, intervalWidget);
    
    ui->listWidget->insertItem(0, newItem);
    

    }@

    However, the widget shown is a standard QListItem, anything i'm missing?
    Also i'm considering other option, maybe using a QVBoxLayout and adding Widget directly in it, but I suspect drag and drop functionality will be a pain to write..

    Thanks!


    Free Indoor Cycling Software - https://maximumtrainer.com

    1 Reply Last reply
    0
    • M Offline
      M Offline
      maximus
      wrote on 10 Apr 2014, 18:51 last edited by
      #2

      I think i'm going to go and try to replicate the Qt Creator designer (drag and drop widget, ..)

      I use a QVBoxLayout and add directly custom QWidget inside it
      https://www.dropbox.com/s/uzi8qrsf4esoawr/test1.png
      No need for model data, every time the Layout change, I will create my model data from the current ui
      Still much work to be done, drag and drop, etc, will post when it's done with working code

      @void WorkoutCreator::on_pushButton_addStep_clicked()
      {
      IntervalWidget *intervalWidget = new IntervalWidget();
      ui->verticalLayout_main->addWidget(intervalWidget);
      }@


      Free Indoor Cycling Software - https://maximumtrainer.com

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 10 Apr 2014, 19:43 last edited by
        #3

        Hi,

        Since you where using a QListWidget why not implement a QStyledItemDelegate and a custom editor ?

        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
        • M Offline
          M Offline
          maximus
          wrote on 11 Apr 2014, 13:38 last edited by
          #4

          The problem I had with the Model/QStyledItemDelegate architecture; I had to reimplement fake painting of the widget (because my widget is complex, not just a one line text edit... then detect when the widget is clicked so that the editor is drawn (actual widget) on top of the fake widget. All this needed 2-3 classes and lot of coding.

          On top of that, not every row in my QListView will be the same widget, I have 2 types of widget to insert, I think you can only have 1 delegateForRow per QListView?
          My structure is like this :
          #1- Simple Widget (orange box in picture **1)
          #2- Widget QGroupBox, containing one or multiple #1 (repeat box in picture **1)
          #3 - Parent Widget (QVBoxLayout) containing one or multiple #1, #2 (whole QVBoxLayout in **1)

          Here is a prototype of what I have so far :
          **1 - https://www.dropbox.com/s/8fi21mtodvqa2bo/interfaceNow1.png
          What I'm aiming at (similar):
          **2 - https://www.dropbox.com/s/jav6ouufa2ft2jl/workoutCreatorGarmin.png

          You think what i'm doing is possible? Adding custom widgets to a QVBoxLayout, then retrieve data widgets order from the QVBoxLayout, create data structure from what is inside every Widget. Also need drag and drop inside the QVBoxLayout.

          Thanks!


          Free Indoor Cycling Software - https://maximumtrainer.com

          1 Reply Last reply
          0
          • M Offline
            M Offline
            maximus
            wrote on 11 Apr 2014, 14:54 last edited by
            #5

            So far I can traverse the QVBoxLayout easily

            @ for (int i = 0; i < ui->verticalLayout_main->count(); i++)
            {
            qDebug() << "checking widget Data..";
            qDebug() << ui->verticalLayout_main->itemAt(i)->widget();

                if (ui->verticalLayout_main->itemAt(i)->widget()->objectName() == "IntervalWidget") {
                    qDebug() << "intervalWidget found! parse it";
                }
                else {  /// GroupBox of Interval Widget, parse each of them, recursive
                    qDebug() << "QGroupBox found! parse it";
                }
            }@
            

            Free Indoor Cycling Software - https://maximumtrainer.com

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 11 Apr 2014, 19:41 last edited by
              #6

              The drag and drop can't be done on a QVBoxLayout but that's not a problem. QScrollArea + custom widget handling the drop event (and using a QVBoxLayout) and you're good to go.

              As for the delegate, nothing forbids you to draw different things based on the model data and provide different editors. Take for example the default delegate, you don't set anything special and it gives you the adequate representation.

              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
              • M Offline
                M Offline
                maximus
                wrote on 12 Apr 2014, 04:35 last edited by
                #7

                Thanks SGaist, I want to try the homemade solution first :)

                I made custom QWidget container that has a QVBoxLayout so I can get dragDrop.
                So far I get inside the dragEnterEvent and the DropEvent fine in the container.
                Would it be possible to set a Drop Indicator in my container? I searched for such function but didn't find. I'm only using "setAcceptDrops(true);" on my container but it doesn't show the drop indicator even though it's working.

                Current Ui Strucutre :
                https://www.dropbox.com/s/p0vwzz794qefxng/currentUi1.png


                Free Indoor Cycling Software - https://maximumtrainer.com

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

                  IIRC you have to call acceptProposedAction on the dragEnterEvent and dragMoveEvent functions to show it.

                  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
                  • M Offline
                    M Offline
                    maximus
                    wrote on 14 Apr 2014, 14:16 last edited by
                    #9

                    Hi good monday, I read "this guide":http://qt-project.org/doc/qt-5/dnd.html

                    It doesn't mention how to show the drop indicator, even when it get to "event.acceptProposedAction(), nothing is shown on my custom container, I guess I probably have to subclass some other class and paint the drop indicator myself, I don't really want to get into that...I tried by subclassing "dragMoveEvent " in the container but this function doesn't get called. I'll try from sratch with a normal QListWidget and setIndexWidget. Hopefully I can find a way not to use delegate and editor I hate this stuff.. Thanks

                    My code for reference if one day you want to add a showDropIndicator function would be nice..

                    Custom container

                    @void DroppableWidget::dragEnterEvent(QDragEnterEvent *event) {

                    //// No drop indicator shown.. not good
                    qDebug() << "dragEnterEvent";
                    if (event->mimeData()->hasFormat("mt/interval") ) {
                        qDebug() << "OK CAN ACCEPT!";
                        event->acceptProposedAction();
                    }
                    

                    }

                    void DroppableWidget::dropEvent(QDropEvent *event) {

                    if (event->proposedAction() == Qt::MoveAction) {
                        qDebug() << "dropEvent  - Move Action";
                        event->acceptProposedAction();
                        /// change widget position in the QVBoxLayout...
                        ///    QVBoxLayout *verticalLayout = static_cast<QVBoxLayout*>(this->layout());
                    }
                    

                    }@

                    Custom widget (inside the container)

                    @void IntervalWidget::mousePressEvent(QMouseEvent *event) {

                    if (event->button() == Qt::LeftButton)
                        dragStartPosition = event->pos();
                    

                    }

                    //////////////////////////////////////////////////////////////////////////////////////////
                    void IntervalWidget::mouseMoveEvent(QMouseEvent *event) {

                    if (!(event->buttons() & Qt::LeftButton))
                        return;
                    if ((event->pos() - dragStartPosition).manhattanLength()
                            < QApplication::startDragDistance())
                        return;
                    
                    QDrag *drag = new QDrag(this);
                    QMimeData *mimeData = new QMimeData;
                    
                    QByteArray output;
                    mimeData->setData("mt/interval", output);
                    drag->setMimeData(mimeData);
                    
                    ///Set the row of the data moving, at destination, switch widget position
                    
                    qDebug() << "ok doing drag now.";
                    //// Image when moving the widget
                    QPixmap pixmap(this->rect().size());
                    this->render(&pixmap, QPoint(), QRegion(this->rect()));
                    
                    drag->setPixmap(pixmap);
                    Qt::DropAction dropAction = drag->exec(Qt::MoveAction&#41;;
                    

                    }@
                    .


                    Free Indoor Cycling Software - https://maximumtrainer.com

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      maximus
                      wrote on 14 Apr 2014, 14:47 last edited by
                      #10

                      I think the dropIndicator not showing is related to my custom Widget missing something.

                      I tried with a normal QListWidget here :
                      https://www.dropbox.com/s/fofinniz9ctsidz/droPIndocator.png

                      And a normal item can be drag and dropped, but not my custom widget

                      @void WorkoutCreate::on_pushButton_add_clicked()
                      {

                      ui->listWidget->addItem("Foo");
                      
                      QListWidgetItem* item;
                      item = new QListWidgetItem(ui->listWidget);
                      ui->listWidget->addItem(item);
                      
                      IntervalWidget *intervalWidget = new IntervalWidget();
                      item->setSizeHint(intervalWidget->minimumSizeHint());
                      ui->listWidget->setItemWidget(item, intervalWidget);
                      

                      }
                      @

                      EDIT:
                      Found the problem, my widget was not actually "selected" when I click it, If I click in the free space near it, it get selected and I can drag and drop it, I have to fix the selection and it should work


                      Free Indoor Cycling Software - https://maximumtrainer.com

                      1 Reply Last reply
                      0

                      1/10

                      10 Apr 2014, 14:42

                      • Login

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