本节介绍的内容续《# 1、ListView的使用介绍(Qt QML C++)》的内容( 1、ListView的使用介绍(Qt QML C++) - 掘金 (juejin.cn) );并在这个基础上增加相关QML嵌入到QMainWindow中内容,具体详细介绍,在后面的文章会相继介绍。

一、C++ QApplication内嵌QML

1、内嵌的QML的内容是在渐变色背景,绘制一个矩形进行旋转,并显示文字内容。

import QtQuick 2.0
Rectangle {
    // 渐变的背景颜色
    gradient: Gradient{
        GradientStop{ position: 0; color: "steelblue"}
        GradientStop{ position: 1; color: "black"}
    // 画面中间的旋转内容
    Rectangle{
        property int d: 100
        id: square
        width: d
        height: d
        anchors.centerIn: parent
        color: "green"
        NumberAnimation on rotation {
            from: 360;
            to: 0;
            duration: 4000;
            loops: Animation.Infinite;
    // 画面中间显示的文字内容
    Text{
        anchors.centerIn: parent
        text: "Qt Quick running in a widget"
        color: "purple"
        font.bold: true
        font.pointSize: 14

QMainWindow内嵌QML项目创建:

C++编码:

ui->ptr_quick_layout(表示的是quickWidget窗口的布局)

二、在C++ QApplication内嵌QML,新建自定义的Model-View使用ListView

DataModel.h:

#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QAbstractListModel>
#include <QList>
// 自定义数据
class Data
public:
    Data(const QString& title,const QString& color):title_(title),color_(color){}
    QString title() const;
    QString color() const;
private:
    QString title_;
    QString color_;
class DataModel : public QAbstractListModel
    Q_OBJECT
public:
    enum DataRoles{
        TitleRole = Qt::DisplayRole + 1,
        ColorRole,
    explicit DataModel(QObject *parent = nullptr);
    // Header:
    // QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    // 插入数据
    Q_INVOKABLE void insert(int index,const Data& data);
    Q_INVOKABLE void insert(int index,const QString& str_title,const QString& str_color);
    // 删除数据
    Q_INVOKABLE void remove(int index);
protected:
    virtual QHash<int, QByteArray> roleNames() const;
private:
    // 数据列表
    QList<Data> data_list_;
#endif // DATAMODEL_H

DataModel.cpp:

#include "DataModel.h"
#include <QDebug>
DataModel::DataModel(QObject *parent)
    : QAbstractListModel(parent)
    data_list_.append(Data("orange item","orange"));
    data_list_.append(Data("red item","red"));
    data_list_.append(Data("blue item","blue"));
//QVariant DataModel::headerData(int section, Qt::Orientation orientation, int role) const
//    // FIXME: Implement me!
int DataModel::rowCount(const QModelIndex &parent) const
    // For list models only the root node (an invalid parent) should return the list's size. For all
    // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
    if (parent.isValid())
        return 0;
    return data_list_.count();
QVariant DataModel::data(const QModelIndex &index, int role) const
    if (!index.isValid())
        return QVariant();
    Data const& p = data_list_[index.row()];
    if(role == TitleRole)
        return p.title();
    else if(role == ColorRole)
        return p.color();
    // FIXME: Implement me!
    return QVariant();
void DataModel::insert(int index, const Data &data)
    if(index < 0 || index > data_list_.count())
        index = 0;
    emit beginInsertRows(QModelIndex(),index,index);
    data_list_.insert(index,data);
    emit endInsertRows();
void DataModel::insert(int index, const QString &str_title, const QString &str_color)
    if(index < 0 || index > data_list_.count())
        index = 0;
    emit beginInsertRows(QModelIndex(),index,index);
    data_list_.insert(index,Data(str_title,str_color));
    emit endInsertRows();
void DataModel::remove(int index)
    if(index < 0 || index > data_list_.count())
        return;
    emit beginRemoveRows(QModelIndex(),index,index);
    data_list_.removeAt(index);
    emit endRemoveRows();
QHash<int, QByteArray> DataModel::roleNames() const
    QHash<int,QByteArray> roles;
    roles[TitleRole] = "dmTitle";
    roles[ColorRole] = "dmColor";
    return roles;
QString Data::title() const
    return title_;
QString Data::color() const
    return color_;

这边需要注意观察insert和remove两个函数的内部实现,关系到,在QML显示的时候数据更新的问题:

模型为了调整链表数据结构的接口,这可以提供insertRows()和removeRows()函数来实现(insert和remove)当实现这些函数的时候,最重要的是调用适当的函数,以便所有连接的视图都可以知道任何更改;
一个insertRows()函数的实现:必须先执行beginInsertRow()函数,然后插入一行新的数据,再然后必须立即执行endInsertRows()函数;
一个removeRows()函数的实现:必须先执行beginRemoveRows()函数,然后再移除一行数据,再然后必须立即执行endRemoveRows()函数;

注意:子类化模型的一些通用准则可以参考Model Subclassing Reference。

待嵌入到C++QMainWindow的QML内容:

datashow.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0
import DataModelItem 1.0
Rectangle
    // property var index_t: view.currentIndex
    DataModel{
        id: datamodel
    ListView{
        id: view
        anchors.top: parent.top
        width: parent.width
        height: parent.height - addItem.height
        model: datamodel
        focus: true
        delegate: Rectangle{
            id: itemshow
            width: view.width
            height: 41
            border.color: Qt.darker(color)
            color: dmColor
            Text{
                anchors.left: parent.left
                text: dmTitle
            Image {
                id: icon
                z:1 // 当多出的点击信号出现冲突,通过调整Z的坐标进行管理
                anchors.right: parent.right
                source: "qrc:/qml/Image/delete.jpg"
                MouseArea{
                    anchors.fill: parent
                    onClicked:
                        console.log("移除当前的Item",index)
                        datamodel.remove(index)
            // 实现ListView的Item的切换
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("选中当前的Item",index)
                    itemshow.ListView.view.currentIndex = index
    Button{
        id: addItem
        anchors.top: view.bottom
        width: parent.width
        height: 32
        Text {
            id: addText
            text: qsTr("增加")
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
        onClicked: {
            var index_t = view.currentIndex;
            console.log("添加设备");
            datamodel.insert(index_t,"green Item","green");

C++部分代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QUrl>
#include <QQuickItem>
#include <QtQuickWidgets/QQuickWidget>
#include <QQuickView>
#include "DataModel.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    ui->setupUi(this);
    QUrl source("qrc:/main.qml");
    QQuickView *ptr_quick_view = new QQuickView();
    QWidget *ptr_qml_widget = QWidget::createWindowContainer(ptr_quick_view,this);
    ptr_quick_view->setResizeMode(QQuickView::SizeRootObjectToView);
    ptr_quick_view->setSource(source);
    ui->ptr_quick_layout->addWidget(ptr_qml_widget);
    DataModel model;
    qmlRegisterType<DataModel>("DataModelItem",1,0,"DataModel");
    QQuickView *ptr_test_view = new QQuickView();
    QWidget *ptr_test_widget = QWidget::createWindowContainer(ptr_test_view,this);
    ptr_test_view->setResizeMode(QQuickView::SizeRootObjectToView);
    ptr_test_view->setSource(QUrl("qrc:/datashow.qml"));
    ui->ptr_test_layout_->addWidget(ptr_test_widget);
MainWindow::~MainWindow()
    delete ui;
    ZMGC枭
        软件工程开发
       
私信