Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [SOLVED] QML/C++ questions
QtWS25 Last Chance

[SOLVED] QML/C++ questions

Scheduled Pinned Locked Moved QML and Qt Quick
7 Posts 3 Posters 5.4k 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.
  • J Offline
    J Offline
    jhndnn
    wrote on last edited by
    #1

    I have an existing C++ GUI using a QGraphicsScene and I'd like to add some QML elements to it. In particular I want a popup with a nice flickable ListView and the only way I think that can be done is by using the QML ListView. I've gotten my QML item to show up when the user clicks on a particular QGraphicsObject but am having some issues that are pretty basic.

    1. The ListView is displayed and can scroll but it's not possible to select any of items in the list.
    2. Assuming I get selection working, how do I notify my C++ code that the user has selected something in the list?

    Here's the C++ and QML code I'm using as a testbed

    @#include <QtGui/QApplication>
    #include <QGraphicsObject>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    #include <QPaintEngine>
    #include <QDebug>
    #include <QtDeclarative/QtDeclarative>

    class Graphic : public QGraphicsObject
    {
    public:
    Graphic(QGraphicsScene* scene):scene(scene)
    {
    }

    virtual void paint(QPainter painter, const QStyleOptionGraphicsItem option, QWidget widget)
    {
    Q_UNUSED(option);
    Q_UNUSED(widget);
    QRectF rc = boundingRect();
    QRectF normalizedRc = QRectF(0, 0, rc.width(), rc.height());
    painter->fillRect(normalizedRc, Qt::red);
    painter->setPen(Qt::black);
    painter->drawText(normalizedRc, Qt::TextWordWrap, "Press Me");
    }
    QRectF boundingRect() const { return QRectF(0, 0, 200, 20); }
    protected:
    QGraphicsScene
    scene;
    virtual void mousePressEvent(QGraphicsSceneMouseEvent
    event)
    {
    QStringList items;
    for( int ix = 0; ix < 20; ix++)
    {
    QString str;
    items.append(str.sprintf("item %i", ix+1));
    }
    QDeclarativeEngine
    engine = new QDeclarativeEngine;
    QDeclarativeContext *context = new QDeclarativeContext(engine->rootContext());
    context->setContextProperty("myModel", items);
    QDeclarativeComponent component(engine, QUrl::fromLocalFile("Popup.qml"));
    QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create(context));
    item->setWidth(boundingRect().width());
    item->setHeight(100);
    item->setPos(pos().x(), pos().y() +boundingRect().height() );
    scene->addItem(item);
    }

    };

    int main(int argc, char argv[])
    {
    QApplication a(argc, argv);
    QGraphicsScene
    scene = new QGraphicsScene(0, 0, 400, 400);
    Graphic* gr = new Graphic(scene);
    gr->setPos(100,100);
    scene->addItem(gr);
    QGraphicsView view(scene);
    view.show();
    return a.exec();
    }
    @

    @
    import Qt 4.7

    Rectangle
    {
    color:"lightgray"
    border.color:"gray"
    border.width:1
    ListView
    {
    anchors.margins:2
    anchors.fill:parent
    clip: true;
    model: myModel;
    delegate: Text
    {
    text:modelData
    }
    highlight: Rectangle
    {
    color: "lightsteelblue"
    radius: 5
    }
    }
    }
    @

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kkrzewniak
      wrote on last edited by
      #2

      I'd recommend using a QAbstractListModel subclass for the model.
      Or.
      An easy way I can think of is making a helper class sub-classing QObject, than registering it as a context property. But if you stick to using a simple QList for the model there is no way your QML list view will get notified that the models data has changed.

      @
      class Helper : public QObject
      {
      Q_OBJECT
      public:
      //Constructor ect.
      //...
      Q_INVOKABLE void entryClicked(int index);
      //.....
      }

      //In C++
      context->setContextProperty("Helper",myHelper);

      //QML in delegate
      MouseArea{
      anchors.fill: parent
      onClicked: {
      Helper.entryClicked(index)
      }
      }
      @
      Just an idea.

      Me, Grimlock, not "nice dino". ME BASH BRAINS!

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jhndnn
        wrote on last edited by
        #3

        Thanks - that appears to work as far as letting me know when an item is clicked in the ListView. The odd thing is that it still isn't selecting the item when I click on it. Is that something that I have to manually deal with? One might assume that the ListView would select the item for me when it was clicked.

        Another issue would be if the user didn't use the mouse to select the item - what if they used the cursor keys to move the selection. In that case I wouldn't get any feedback that had happened.

        Is there really no way to be easily notified when an item ( or items with multi selection ) is selected in a ListView?

        1 Reply Last reply
        0
        • J Offline
          J Offline
          jhndnn
          wrote on last edited by
          #4

          I missed the first line of your answer about using a QAbstractListModel. Since I didn't have any luck using the QStringList ( and trying the stringlistmodel example showed that selection didn't work their either ) I thought I've give that a try.

          I implemented a QAbstractListModel that uses a QStringList to back the data - basically I copied the code from here - http://www.java2s.com/Code/Cpp/Qt/stringlistmodelexample.htm. When I assign that to my context it appears to get the correct number of items but it doesn't display my item data and prints the following error in Application Output
          @
          file:///C:/code/test/QmlTest-build-desktop/Popup.qml:24: ReferenceError: Can't find variable: modelData
          @
          Any idea what I should use in my QML delegate to reference the data inside my QAbstractListModel? Apparently modelData is not the correct thing to use.

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jhndnn
            wrote on last edited by
            #5

            Ok, so I figured out there is a QStringListModel which derives from QAbstractListModel. Switching to that and I still have the same issues. I can't select any of the items in the ListView and I can't figure out how to access the string inside the delegate - it can't find modelData.

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mbrasser
              wrote on last edited by
              #6

              Hi,

              http://doc.qt.nokia.com/4.7-snapshot/qdeclarativemodels.html should give more information on using the modelData property (which types of models it works with, etc).

              You do need to set the current item explicitly using the mouse. Typically this is done similar to the following (from the QML pathview example):

              @
              //inside your delegate
              MouseArea {
              anchors.fill: parent
              onClicked: view.currentIndex = index
              }
              @

              This doesn't seem to be well documented at the moment -- I've created "QTBUG-18601":http://bugreports.qt.nokia.com/browse/QTBUG-18601 for this.

              Regards,
              Michael

              1 Reply Last reply
              0
              • J Offline
                J Offline
                jhndnn
                wrote on last edited by
                #7

                Thanks. That's exactly what I was looking for. It would also be nice to document how one determines that something in the ListView was selected. After a couple more hours yesterday I finally figured out I could add a signal to my QML which would be called from onCurrentIndexChanged and then hook that signal up to a slot in my C++ code.

                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