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. QListView to display created Shapes

QListView to display created Shapes

Scheduled Pinned Locked Moved Unsolved General and Desktop
qlistqlistview
7 Posts 3 Posters 2.8k 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.
  • 6 Offline
    6 Offline
    6ort
    wrote on last edited by 6ort
    #1

    Hello,

    I am making a paint program. The user can create geometric shapes. Currently I store these shapes inside a QList<Shape*> and a QPainter iterates over the list, drawing them.

    I want to have a QListView or something similar that will display all created shapes so you can select them by clicking on their name (like in Photoshop the Layer/Shape selection panel). Each shape gets their own name like Shape1, Shape2, etc. and then are displayed in a list.

    I am trying to use QListView for this but realised I need to make a model and subclass QAbstractListModel. I did that, and moved the QList as a private member of the subclassed class. Now I have to implement the rowCount() and data() functions to return the data from the QList, but the data() function wants to return a QVariant, which doesn't have a constructor for QList, only for QStringList, so I get an error message.

    What would be the best way to store a list of Shapes ( I need polymorphism so it needs to store Shape* since specific shape types inherit from the base Shape class) while being to able to display these objects inside a list so they can easily be selected?

    Thanks

    1 Reply Last reply
    0
    • M Offline
      M Offline
      moravas
      wrote on last edited by
      #2

      Hi,

      maybe, the most easiest way is to use QTableWidget. It has a method "setCellWidget" or something similar. Is already tested with native controls, like QComboBox, so as I can imagene the solution for you:
      Create a 2 columns QTableWidget item, where the first one will displays the name of shapes, and the second one could be a QLabel instance that can display bitmaps or any other images.
      By the way: I looked for such a solution preferring MVC, and I got a tip that I can implement these solution with QListView or QTableView (both of them are model based grids), because they are inherent from QTableWidget. I didn't have to have a chance to test it.

      For your current implementation: I don't understand, why did you sublcassed from the QAbstractListView, I think QStandardListModel would be suitable for you.

      Regards,
      Norbert

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        You should not return your list when data is called, only the element corresponding to the row of the index passed to the method. The you can use a QStyledItemDelegate to render your shape in QListView unless you already return something suitable for e.g. the decoration role.

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

        6 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          You should not return your list when data is called, only the element corresponding to the row of the index passed to the method. The you can use a QStyledItemDelegate to render your shape in QListView unless you already return something suitable for e.g. the decoration role.

          6 Offline
          6 Offline
          6ort
          wrote on last edited by 6ort
          #4

          @SGaist Yes, I tried like:

          QVariant ShapeListModel::data(const QModelIndex &index, int role) const
          {
          if (role == Qt::DisplayRole)
          {
          return shapeList.at(index.row());
          }
          else
          {
          return QVariant();
          }
          }

          But I get:
          \untitled1\paintarea.cpp:12: error: C2248: 'QVariant::QVariant' : cannot access private member declared in class 'QVariant'

          Oh btw I do not need to render the shape inside the ListView, I just need there a name and maybe a toggle to hide/show the shape on the main canvas.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            You are using a custom type so you must use QVariant::fromValue

            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
            • 6 Offline
              6 Offline
              6ort
              wrote on last edited by 6ort
              #6

              OK, developing an early working prototype, but still further issues. I created my model:
              class ShapeListModel : public QAbstractListModel

              It has a member which stores the Shapes that the user can create (the shapes get created by clicking mouse on canvas, this is important):
              QList<Shape*>& shapeList;

              I implemented data() like this (so far it only gets the name of the shape, like Shape1, etc.):
              QVariant ShapeListModel::data(const QModelIndex &index, int role) const
              {
              return QVariant::fromValue(shapeList.at(index.row())->getName());
              }

              And setData() like this:
              bool ShapeListModel::setData(const QModelIndex &index, const QVariant &value, int role)
              {
              Shape* shape = value.value<Shape*>();
              shapeList.insert(shapeList.count(), shape);
              return true;
              }

              This adds a Shape* to the shapeList and the shapes are drawn. Now I want to update the ListView that displays the list of shapes, so I need to emit a dataChanged() signal (which takes QModelIndex as parameter). My problem now is that I am not adding Shapes through the ListView, but rather the shapes are added when the user draws them on the canvas. So I do not know how to use a QModelIndex, to tell the ListView, which row to refresh?

              I know that classical usage is to use setData() through the View widget to edit the data but in my program that's not the usage case as the Shapes get added as they are drawn on canvas and not added in the widget they are displayed. Not sure how to tell the widget to update the proper cell.

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                When using a custom model, the usage is to add specialized methods to your model to add/remove your custom objects. So when you add/remove a Shape you know exactly where they are so you can use beginInsertRow/endInsertRow and the update will happen automatically for you.

                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

                • Login

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