qml 实现一个listview

news2024/11/16 2:19:48

主要通过qml实现listvie功能,主要包括右键菜单,滚动条,拖动改变内容等,c++ 与 qml之间的变量和函数的调用。

main.cpp

#include <QQuickItem>
#include <QQmlContext>
#include "testlistmodel.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    qmlRegisterType<TestListModel>("TestListModel", 1, 0, "TestListModel");
    engine.load(QUrl(QStringLiteral("qrc:/ui1.qml")));
    QObject* root = engine.rootObjects().first();
    QString retVal;
    QVariant message = "Hello from c++";
    QVariant returnedValue;
    QQmlProperty(root,"testmsg").write("hello,world");
    qDebug()<<"Cpp get qml property height222"<<root->property("msg");
    bool ret =QMetaObject::invokeMethod(root,"setSignalB",
                              Q_RETURN_ARG(QVariant,returnedValue),
                              Q_ARG(QVariant,message),
                              Q_ARG(QVariant,8));
    qDebug()<<"returnedValue"<<returnedValue<<root<<ret;
    return app.exec();
}

listview 的model 代码

TestListModel.h

#ifndef TESTLISTMODEL_H
#define TESTLISTMODEL_H

#include <QAbstractListModel>
typedef struct Student
{
    int     id;
    QString name;
    QString sex;
}pStudent;

class TestListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit TestListModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent) const;

    QVariant data(const QModelIndex &index, int role) const;
    virtual QHash<int, QByteArray> roleNames() const;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    Q_INVOKABLE void modifyItemText(int row1,int row2);
    Q_INVOKABLE void add();

    enum MyType{
        ID=Qt::UserRole+1,
        Name,
        Sex
    };
private:
     QVector<Student>  m_studentList;

signals:
     void    layoutChanged();
};

#endif // TESTLISTMODEL_H

TestListModel.cpp

#include "testlistmodel.h"
#include <QDebug>

TestListModel::TestListModel(QObject *parent)
    : QAbstractListModel{parent}
{
    for(int i=0;i<20;i++)
    {
        Student oneData;
        oneData.id = i;
        oneData.name  = QString("张三%1").arg(i);
        if(i%2==0)
        {
            oneData.sex = "female" ;
        }
        else
        {
            oneData.sex = "male" ;
        }
        //qDebug()<<"TestListModel"<<m_studentList.size();
        m_studentList.append(oneData);
    }   

}

int TestListModel::rowCount(const QModelIndex &parent) const
{
    //qDebug()<<"rowCount"<<m_studentList.size();
    return m_studentList.size();
}
QVariant TestListModel::data(const QModelIndex &index, int role) const
{
   // qDebug()<<"TestListModel::data11111111111"<<index.isValid();

    QVariant var;
    if ( !index.isValid() )
    {
        return QVariant();
    }
    int nRow    = index.row();
    int nColumn = index.column();
    if(Qt::UserRole+1 == role)
    {
        var = QVariant::fromValue(m_studentList.at(nRow).id);
    }
    else if(Qt::UserRole+2 == role)
    {
        var = QVariant::fromValue(m_studentList.at(nRow).name);
        // qDebug()<<"m_listData.at(nRow).name"<<m_listData.at(nRow).name;
    }
    else if(Qt::UserRole+3 == role)
    {
        var = QVariant::fromValue(m_studentList.at(nRow).sex);
        // qDebug()<<"m_listData.at(nRow).name"<<m_listData.at(nRow).name;
    }
    return var;
}

QHash<int, QByteArray> TestListModel::roleNames() const
{
    QHash<int, QByteArray> d;
    d[MyType::ID]="id";
    d[MyType::Name]="name";
    d[MyType::Sex]="sex";
    qDebug()<<"d .size"<<d.size();
    return d;
}
Qt::ItemFlags TestListModel::flags(const QModelIndex &index) const
{
    Q_UNUSED(index)
    // if(index.column() ==1)
    // {
    //     qDebug()<<"UserInfoModel::flags  1111";
    //     return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
    // }
    qDebug()<<"TestListModel::flags";
    return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}

void TestListModel::modifyItemText(int row1, int row2)
{
    m_studentList.swapItemsAt(row1,row2);
    beginResetModel();
    endResetModel();
}

void TestListModel::add()
{
    Student student;
    student.id   = 123;
    student.name = "love";
    student.sex  = "man";
    m_studentList.push_back(student);
    beginResetModel();
    endResetModel();
    emit layoutChanged();

}

ui.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.2
import TestListModel 1.0


import QtQuick 2.12

import QtQuick 2.2
import QtQml.Models 2.2
//import QtQuick.Controls 2.12
//QtQuick.Controls 2.12  和QtQuick.Controls.Styles 1.4不匹配
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
import QtQuick.Controls 2.12
import QtLocation 5.15
//import "CustomMenuItem.qml"
// import QtQuick.Controls 2.15

//import QtQuick.Controls 2.5


Window {
    id:window
    //anchors.centerIn: parent
    width: 650;
    height: 457
    visible: true
    flags: Qt.FramelessWindowHint | Qt.Dialog
    property string testmsg: "GongJianBo1992"
    Rectangle{
        id:rect1;
        anchors.fill: parent;
        border.width: 1;
        color: "transparent";
        border.color: "red";
        clip:true//这一属性设置表示如果他的子类超出了范围,那么就剪切掉,不让他显示和起作用
    }
    //无边框移动
    MouseArea {
        id: dragRegion
        anchors.fill: parent
        property point clickPos: "0,0"
        onPressed: {
            clickPos = Qt.point(mouse.x,mouse.y)
        }
        onReleased: {
            clickPos = Qt.point(0,0)
        }
        onPositionChanged: {
            //鼠标偏移量
            var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
            //如果mainwindow继承自QWidget,用setPos
            window.setX(window.x+delta.x)
            window.setY(window.y+delta.y)
        }
    } 
    Menu {
        id: contextMenu
        background: Rectangle {// @disable-check M16
            anchors.fill:parent
            implicitWidth: 200
            implicitHeight: 30
            color: "lightblue"
        }
        Action{
            id:no1
            text:"123"
            onTriggered:
            {
                console.log("选项一被点击")
                tableView.selectAllItem()
            }
            // @disable-check M16
        }
        Menu{
            background: Rectangle {// @disable-check M16
                anchors.fill:parent
                implicitWidth: 200
                implicitHeight: 30
                color: "lightblue"
            }
            title:"love"
            Action{
                id:no4
                text:"789"
                onTriggered:
                {
                    console.log("选项六被点击")
                    tableView.selectAllItem()
                }
            }
        }
        Action {
            id:no2
            text:"234"
            onTriggered:
            {
                console.log("选项二被点击")
                tableView.disselectAllItem()
            }
        }
        MenuSeparator {
            contentItem: Rectangle {// @disable-check M16
                implicitWidth: 200
                implicitHeight: 1
                color: "#21be2b"
            }
        }
        Action {
            id:no3
            text:"345"
            onTriggered: console.log("选项三被点击")
        }
        delegate: MenuItem {// @disable-check M16
            id: menuItem
            height: 40// @disable-check M16
             contentItem: Text{// @disable-check M16
              text:menuItem.text
              color: menuItem.highlighted? "gary": "blue"
            }
            background: Rectangle{// @disable-check M16
                implicitWidth: 200
                implicitHeight: 30
                color: menuItem.highlighted? "purple":"lightblue"
            }
            arrow: Image {// @disable-check M16
                id: arrowImage
                x: parent.width - width
                y: parent.height/2 -height/2
                visible: menuItem.subMenu
                source: "qrc:/Right arrow.png"
            }
        }

    }
     TestListModel{
        id: myMode
        onLayoutChanged:{
           console.log("LayoutChanged")
        }
     }
     // Page{
     //    x:listwidget.x
     //    y:listwidget.y
     //    width:  listwidget.width
     //    height: listwidget.height
     //    background: Rectangle{
     //        anchors.fill: parent
     //        color: "white"
     //        border.width: 1
     //        border.color: "black"
     //    }
     // }
     Rectangle{
         width:  window.width-60+2
         height: 300+2
         border.color: "lightgreen"
         border.width: 1
         color: "transparent"
         x:30
         y:40
     ListView {
         id: listwidget
         width:  parent.width-2//window.width-60
         height: parent.height-2//   300
         x:1
         y:1
         interactive: false // @disable-check M16
         model: myMode
         clip: true  //不写的话,滚动的时候,listview会有拖拽的感觉
         //orientation: ListView.Vertical //垂直列表        
         ScrollBar.vertical: ScrollBar {
             id: scrollBar
             hoverEnabled: true
             active: hovered || pressed
             policy: ScrollBar.AlwaysOn
             orientation: Qt.Vertical
             size: 0.8
             anchors.top: parent.top
             anchors.right: parent.right
             anchors.bottom: parent.bottom
             contentItem: Rectangle  {
                 implicitWidth: 6  //没指定的时候的宽度
                 implicitHeight: 100 //没有指定高度的时候
                 radius: width / 2
                 color: scrollBar.pressed ? "#81e889" : "#c2f4c6"

             }
         }
        Rectangle{
             id : dargRect
             width: 100
             height: 30
             visible: false
             color: "lightgray";
             Text {
                 anchors.verticalCenter: parent.verticalCenter
                 anchors.horizontalCenter: parent.horizontalCenter
                 id: dargRectText
                 // text: "123"
                 horizontalAlignment: Text.AlignHCenter
                 verticalAlignment: Text.AlignVCenter
             }
         }
         delegate: Item{
             id:itemDrag1
             width: window.width-60
             height: 30
             property int dragItemIndex: 0
             property bool isHover: false
             Rectangle {
                 width: window.width-60
                 height: 30
                 //radius: 5;
                 // border.width: 1
                 // border.color: "white"
                 color:isHover === true? "lightgreen":listwidget.currentIndex === index ? "lightblue" : "gray"
                 Text {
                     id:itemDrag2
                     anchors.verticalCenter: parent.verticalCenter
                     anchors.left: parent.left
                     // text: "123"
                     horizontalAlignment: Text.AlignHCenter
                     verticalAlignment: Text.AlignVCenter
                     text: id+":"+name+":"+sex
                 }                
                 MouseArea {
                     id: mouseArea
                     anchors.fill: parent
                     acceptedButtons: Qt.LeftButton | Qt.RightButton
                     hoverEnabled: true
                     onWheel: {// @disable-check M16
                         // 当滚轮被滚动时调用
                         // 事件参数wheel提供了滚动的方向和距离
                         if (wheel.angleDelta.y > 0) {
                             //console.log("向上滚动")
                             scrollBar.decrease();
                         }
                         else {
                             //console.log("向下滚动")
                             scrollBar.increase();
                         }
                     }
                     onEntered:
                     {
                         isHover = true
                         //console.log("onEntered" +isHover)
                     }
                     onExited:
                     {
                         isHover = false
                         //console.log("onExited" +isHover)
                     }
                     onClicked:
                     {
                         if (mouse.button === Qt.RightButton)//菜单
                         {
                             console.log("menu RightButton")
                             contextMenu.popup()
                         }
                         else
                         {
                             //var other_index = listwidget.indexAt(mouseArea.mouseX , mouseArea.mouseY );

                             listwidget.currentIndex = index // 点击时设置当前索引为该项的索引值
                             dragItemIndex = index;
                             console.log("onClicked"+index)
                         }
                     }
                     onPressAndHold:  {
                         if(mouse.button === Qt.LeftButton)
                         {
                             console.log("onPressAndHold"+index)
                             listwidget.currentIndex = index
                             dargRect.x = mouseX +itemDrag1.x
                             dargRect.y = mouseY+itemDrag1.y
                             dragItemIndex = index;
                             dargRectText.text = itemDrag2.text
                             dargRect.visible = true
                         }
                     }
                     onReleased:{
                        if(dargRect.visible === true)
                        {
                            dargRect.visible = false
                            var other_index = listwidget.indexAt(mouseX +itemDrag1.x , mouseY+itemDrag1.y );
                            console.log("onReleased"+other_index)
                            if(dragItemIndex!==other_index)
                            {
                            var afterItem   = listwidget.itemAtIndex(other_index );
                            // listwidget.myModel.get(other_index).text
                            myModel.modifyItemText(dragItemIndex,other_index)
                            //console.log("onReleased"+myModel)
                            }

                        }
                     }
                     onPositionChanged:{
                         //console.log("onPositionChanged111" + mouse.button)
                         if(mouse.button === Qt.LeftButton)
                         {
                             //console.log("onPositionChanged222")
                             var other_index = listwidget.indexAt(mouseX +itemDrag1.x , mouseY+itemDrag1.y );
                             listwidget.currentIndex  = other_index;
                             dargRect.x = mouseX +itemDrag1.x
                             dargRect.y = mouseY+itemDrag1.y
                         }
                     }                     
                 }
             }
         }
     }
 }
    Button {
        id: button1
        x: parent.width-80
        y: parent.height-36
        width:70
        height:30
        //text: qsTr("Button")
        background:Rectangle // @disable-check M16
        {
            //anchors.fill: parent
            border.color: "royalblue"
            border.width: 1
            color: button1.down ? "red" :(button1.hovered?"blue":"lightsteelblue")
        }
        Text {
            text: "1213";
            // anchors.fill: parent
            anchors.centerIn: parent;
            color: button1.hovered?"yellow":"red";
            font.pixelSize: 13;
            //font.weight: Font.DemiBold
        }       
        Connections {
            target: button1
            function onClicked()
            {
                window.close();
            }
        }
    }
    function myQmlFunction( msg,index) {
            console.log("Got message:", msg)
            return "some return value"
        }
    function setSignalB(name, value){

           console.log("setPoint"+" "+testmsg);
           console.log("qml function processB",name,value);
           myMode.add();
           return value
       }

}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1935337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(自用)高性能网络编程

Epoll - Reactor 设计模式 以餐厅大点餐为例 Reactor优点 Epoll - IO多路复用 1.创建EPOLL 句柄 相关函数 epoll_create #include <sys/epoll.h>int epoll_create(int size); 作用&#xff1a; 创建一个 epoll 实例 参数: size 参数用于指定 epoll 实例中管理的…

MongoDB教程(十二):MongoDB数据库索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

vue3前端开发-小兔鲜项目-图片懒加载的自定义标签

vue3前端开发-小兔鲜项目-图片懒加载的自定义标签&#xff01;很多大型网站&#xff0c;因为首页面渲染的内容太多了&#xff0c;然而有些用户&#xff0c;可能在顶部就发现了自己感兴趣的内容&#xff0c;直接就点击跳转去了其他页面&#xff0c;因此&#xff0c;完全没有必要…

Spring纯注解开发

前言 Spring3.0引入了纯注解开发的模式&#xff0c;框架的诞生是为了简化开发&#xff0c;那注解开发就是简化再简化。Spring的特性在整合MyBatis方面体现的淋漓尽致哦 一.注解开发 以前跟老韩学习SE时他就说&#xff1a;注解本质是一个继承了Annotation 的特殊接口,其具体实…

Apache SeaTunnel——OLAP 引擎的数据动脉

导读本文将分享如何利用 Apache SeaTunnel 将各个业务系统的数据同步到 OLAP 引擎。 主要内容包括以下六大部分&#xff1a; 1. Apache SeaTunnel 项目介绍 2. Apache SeaTunnel 核心功能 3.SeaTunnel 在 OLAP 场景下的应用 4. 社区近期计划 5. WhaleTunnel 产品特性 6. …

【框架】PHP框架详解-symfony框架

目录 一、框架概述 二、核心组件 三、特点与优势 四、开发流程 新机制 层次 网络应用框架 包涵观念 兼容的数据库 结构 开发环境捆绑 应用开源项目 公共特性 Symfony是一个用PHP语言编写的开放源代码的Web应用框架,旨在加速Web应用程序的开发过程,提高代码的可维…

VS2019+CMake+Vtk9.3.0+Qt5.14.2 配置

VS2019CMakeVtk9.3.0Qt5.14.2 配置环境 第一步 下载 基本配置 系统环境&#xff1a;windows11 x64 Qt&#xff1a;5.14.2 这是最后最新的LTS qt离线版本&#xff0c;后续版本都需要在线安装&#xff0c;同时使用qt5.14也避免版权问题。 Qt 5.14&#xff1a;大部分模块基于LG…

去中心化技术的变革力量:探索Web3的潜力

随着区块链技术的发展和应用&#xff0c;去中心化技术正成为数字世界中的一股强大变革力量。Web3作为去中心化应用的新兴范式&#xff0c;正在重新定义人们对于数据、互联网和价值交换的认知。本文将探索去中心化技术的基本概念、Web3的核心特征及其潜力应用&#xff0c;展示其…

Zabbix × openGauss完成兼容 | 信创路上,得其法则事半功倍

在当今快速发展的信息技术领域&#xff0c;数据库作为核心组件之一&#xff0c;其性能、可靠性和兼容性一直是企业和开发者关注的焦点。 近期&#xff0c;Zabbix与openGauss完成了兼容性认证&#xff0c;经过严格联合测试&#xff0c;双方产品实现完全兼容&#xff0c;整体运行…

手写简易版Spring IOC容器【学习】

这里写自定义目录标题 BeanDefinitionbeanDefinition类 单例对象单例对象注册(SingletonBeanRegistry)DefaultSingletonBeanRegistry 模板方法 BeanFactoryBeanFactory接口AbstractBeanFactory 抽象工厂模板 (getBean)AbstractAutowireCapableBeanFactory (createBean 创建bean…

离散数学,汉密尔顿图判定的实际问题,平面图,平面图的判定,欧拉公式,对偶图,五色定理的证明

目录 1.汉密尔顿图判定的实际问题 判断是否是汉密尔顿图 思考&#xff1a;下图中哪些是汉密尔顿图 例子 2.平面图 平面图的基本概念 并非所有的图都能嵌入平面 平面图的面与次数 欧拉公式 欧拉公式的证明 3.平面图的判定 同胚 kuratowski定理 ​4.对偶图 四…

docker 安装并测试(Ubuntu下)

1. 确认安装环境&#xff08;操作系统版本和 CPU 架构&#xff09; 2. 如果有旧版本的 docker 需要进行卸载 使用 docker 命令检查是否已经安装了 docker 如果 docker 已经安装&#xff0c;使用以下命令卸载&#xff1a; apt-get purge docker-ce docker-ce-cli containerd…

​1:1公有云能力整体输出,腾讯云“七剑”下云端

【全球云观察 &#xff5c; 科技热点关注】 曾几何时&#xff0c;云计算技术的兴起&#xff0c;为千行万业的数字化创新带来了诸多新机遇&#xff0c;同时也催生了新产业新业态新模式&#xff0c;激发出高质量发展的科技新动能。很显然&#xff0c;如今的云创新已成为高质量发…

【qt】VS中如何配置Qt环境

https://download.qt.io/official_releases/vsaddin/ 首先需要下载一下vsaddin,上面的是下载的网站. 下载的时候可能会出现下图的情况 说明你下的vsaddin和您的VS版本不匹配,所以你可以多下几个其他版本的vsAddin,一般都是和你VS版本相匹配的才可以,如Vs2022,那就试试vsaddin2…

Alpine Linux 轻量级Linux 适合于 docker 容器镜像

Alpine Linux是创始于2010年4月及以前的、一款开源社区开发的、基于musl libc和BusyBox的轻量级Linux发行版&#xff1b;适合用来做路由器、防火墙、VPNs、VoIP 盒子以及服务器的操作系统。 Alpine 的意思是“高山的”。Alpine Linux 围绕 musl libc 和 busybox 构建。这使得它…

Spring后端框架复习总结

之前写的博客太杂,最近想把后端框架的知识点再系统的过一遍,主要是Spring Boot和Mybatis相关,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写java后端专栏,这篇不再赘述。 目录 Spring什么是AOP?底层原理?事务…

[PM]产品运营

生命周期 运营阶段 主要工作 拉新 新用户的定义 冷启动 拉新方式 促活 用户活跃的原因 量化活跃度 运营社区化/内容化 留存 用户流失 培养用户习惯 用户挽回 变现 变现方式 付费模式 广告模式 数据变现 变现指标 传播 营销 认识营销 电商营销中心 拼团活动 1.需求整理 2.…

Linux中安装MySQL

1、新建目录用来存放MySQL安装包&#xff1a; mkdir upload、cd upload 2、输入命令下载MySQL安装包&#xff1a; wget https://cdn.mysql.com/archives/mysql-8.0/mysql-8.0.18-el7-x86_64.tar.gz 3、在系统中安装一系列软件包的&#xff1a; yum -y install wget cmake gcc g…

SonarQube执行代码扫描失败,Can not execute Findbugs

SonarQube 版本 9.2.4 SonarQube执行代码扫描失败&#xff0c;报错如下 remote: INFO: Sensor FindBugs Sensor [findbugs] remote: INFO: Findbugs plugin version: 4.2.6 remote: INFO: JavaResourceLocator.binaryDirs() not available before SonarQube …

【Vue】深入了解 v-for 指令:从基础到高级应用的全面指南

文章目录 一、v-for 指令概述二、v-for 指令的基本用法1. 遍历数组2. 遍历对象3. 使用索引 三、v-for 指令的高级用法1. 组件列表渲染2. 使用 key 提升性能3. 嵌套循环 四、结合其他功能的高级用法1. 处理过滤和排序后的结果2. 迭代数值范围3. 结合其他命令使用模板部分 (<t…