本节介绍的内容续《# 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);
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.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"));
int DataModel::rowCount(const QModelIndex &parent) const
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();
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
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
anchors.right: parent.right
source: "qrc:/qml/Image/delete.jpg"
MouseArea{
anchors.fill: parent
onClicked:
console.log("移除当前的Item",index)
datamodel.remove(index)
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枭
软件工程开发