当前位置: 首页 > news >正文

treeview

QML自定义一个TreeView,使用ListView递归


在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件(在 Qt6 中出了一个继承自 TableView 的 TreeView),而且 QtQuick.Controls 1.x 中的也需要配合 C++ model 来自定义,对于一些简单的需求还要写 C++ model 就显得费事儿。

参照别人的自定义 TreeView 实现,我也使用 ListView 嵌套的方式做了一个简易的 TreeView,主要功能就是根据 json 结构来生成一个树状列表。

(2022-05-28)在最初的版本没考虑 ListView 超过 cache 范围自动销毁的问题,改版后勾选等状态放到外部数组中,释放后重新创建 delegate item 时,会从外部数组中取值进行判断该 item 是否勾选。

1.展示
先看看ui效果图-1和自己的demo图-2。三级目录,其中最后一级是勾选框。我用黑色表示无子项,白色有子项已展开,灰色有子项未展开,绿色已勾选,红色未勾选。实际使用时会替换为image。

     

//PS.后面完善了下,效果如下图

代码github:https://github.com/gongjianbo/QmlTreeView

主要代码:

//TreeView.qml

import QtQuick 2.7
import QtQuick.Controls 2.7
 
//代码仅供参考,很多地方都不完善
//还有一些样式没有导出,可以根据需求自己定义
//因为ListView有回收策略,除非cacheBuffer设置很大,所以状态不能保存在delegate.item中
//需要用外部变量或者model来存储delegate.item的状态
Rectangle {
    id: control
 
    property string currentItem //当前选中item
 
    property int spacing: 10    //项之间距离
    property int indent: 5      //子项缩进距离,注意实际还有icon的距离
    property string onSrc: "qrc:/img/on.png"
    property string offSrc: "qrc:/img/off.png"
    property string checkedSrc: "qrc:/img/check.png"
    property string uncheckSrc: "qrc:/img/uncheck.png"
 
    property var checkedArray: [] //当前已勾选的items
    property bool autoExpand: true
 
    //背景
    color: Qt.rgba(2/255,19/255,23/255,128/255)
    border.color: "darkCyan"
    property alias model: list_view.model
    ListView {
        id: list_view
        anchors.fill: parent
        anchors.margins: 10
        //model: //model由外部设置,通过解析json
        property string viewFlag: ""
        delegate: list_delegate
        clip: true
        onModelChanged: {
            console.log('model change')
            checkedArray=[]; //model切换的时候把之前的选中列表清空
        }
    }
    Component {
        id: list_delegate
        Row{
            id: list_itemgroup
            spacing: 5
            property string parentFlag: ListView.view.viewFlag
            //以字符串来标记item
            //字符串内容为parent.itemFlag+model.index
            property string itemFlag: parentFlag+"-"+(model.index+1)
 
            //canvas 画项之间的连接线
            Canvas {
                id: list_canvas
                width: item_titleicon.width+10
                height: list_itemcol.height
                //开了反走样,线会模糊看起来加粗了
                antialiasing: false
                //最后一项的连接线没有尾巴
                property bool isLastItem: (model.index===list_itemgroup.ListView.view.count-1)
                onPaint: {
                    var ctx = getContext("2d")
                    var i=0
                    //ctx.setLineDash([4,2]); 遇到个大问题,不能画虚线
                    // setup the stroke
                    ctx.strokeStyle = Qt.rgba(201/255,202/255,202/255,1)
                    ctx.lineWidth=1
                    // create a path
                    ctx.beginPath()
                    //用短线段来实现虚线效果,判断里-3是防止width(4)超过判断长度
                    //此外还有5的偏移是因为我image是透明背景的,为了不污染到图标
                    //这里我是虚线长4,间隔2,加起来就是6一次循环
                    //效果勉强
                    ctx.moveTo(width/2,0) //如果第一个item虚线是从左侧拉过来,要改很多
                    for(i=0;i<list_itemrow.height/2-5-3;i+=6){
                        ctx.lineTo(width/2,i+4);
                        ctx.moveTo(width/2,i+6);
                    }
 
                    ctx.moveTo(width/2+5,list_itemrow.height/2)
                    for(i=width/2+5;i<width-3;i+=6){
                        ctx.lineTo(i+4,list_itemrow.height/2);
                        ctx.moveTo(i+6,list_itemrow.height/2);
                    }
 
                    if(!isLastItem){
                        ctx.moveTo(width/2,list_itemrow.height/2+5)
                        for(i=list_itemrow.height/2+5;i<height-3;i+=6){
                            ctx.lineTo(width/2,i+4);
                            ctx.moveTo(width/2,i+6);
                        }
                        //ctx.lineTo(10,height)
                    }
                    // stroke path
                    ctx.stroke()
                }
 
                //项图标框--可以是ractangle或者image
                Image {
                    id: item_titleicon
                    visible: false
                    //如果是centerIn的话展开之后就跑到中间去了
                    anchors.left: parent.left
                    anchors.top: parent.top
                    anchors.leftMargin: list_canvas.width/2-width/2
                    anchors.topMargin: list_itemrow.height/2-width/2
                    //根据是否有子项/是否展开加载不同的图片/颜色
                    //color: item_repeater.count
                    //      ?item_sub.visible?"white":"gray"
                    //:"black"
                    //这里没子项或者子项未展开未off,展开了为on
                    source: item_repeater.count?item_sub.visible?offSrc:onSrc:offSrc
 
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            if(item_repeater.count)
                                item_sub.visible=!item_sub.visible;
                        }
                    }
                }
 
                //项勾选框--可以是ractangle或者image
                Image {
                    id: item_optionicon
                    visible: false
                    width: 10
                    height: 10
                    anchors.left: parent.left
                    anchors.top: parent.top
                    anchors.leftMargin: list_canvas.width/2-width/2
                    anchors.topMargin: list_itemrow.height/2-width/2
                    property bool checked: isChecked(itemFlag)
                    //勾选框
                    //color: checked
                    //       ?"lightgreen"
                    //       :"red"
                    source: checked?checkedSrc:uncheckSrc
                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            item_optionicon.checked=!item_optionicon.checked;
                            if(item_optionicon.checked){
                                check(itemFlag);
                            }else{
                                uncheck(itemFlag);
                            }
                            var str="checked ";
                            for(var i in checkedArray)
                                str+=String(checkedArray[i])+" ";
                            console.log(str)
                        }
                    }
                }
 
            }
 
            //项内容:包含一行item和子项的listview
            Column {
                id: list_itemcol
 
                //这一项的内容,这里只加了一个text
                Row {
                    id: list_itemrow
                    width: control.width
                    height: item_text.contentHeight+control.spacing
                    spacing: 5
 
                    Rectangle {
                        height: item_text.contentHeight+control.spacing
                        width: parent.width
                        anchors.verticalCenter: parent.verticalCenter
                        color: (control.currentItem===itemFlag)
                               ?Qt.rgba(101/255,255/255,255/255,38/255)
                               :"transparent"
 
                        Text {
                            id: item_text
                            anchors.left: parent.left
                            anchors.verticalCenter: parent.verticalCenter
                            text: modelData.text
                            font.pixelSize: 14
                            font.family: "Microsoft YaHei UI"
                            color: Qt.rgba(101/255,1,1,1)
                        }
 
                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                control.currentItem=itemFlag;
                                console.log("selected",itemFlag)
                            }
                        }
                    }
 
                    Component.onCompleted: {
                        if(modelData.istitle){
                            item_titleicon.visible=true;
                        }else if(modelData.isoption){
                            item_optionicon.visible=true;
                        }
                    }
                }
 
                //放子项
                Column {
                    id: item_sub
                    //也可以像check一样用一个expand数组保存展开状态
                    visible: control.autoExpand
                    //上级左侧距离=小图标宽+x偏移
                    x: control.indent
                    Item {
                        width: 10
                        height: item_repeater.contentHeight
                        //需要加个item来撑开,如果用Repeator获取不到count
                        ListView {
                            id: item_repeater
                            anchors.fill: parent
                            delegate: list_delegate
                            model: modelData.subnodes
                            property string viewFlag: itemFlag
                        }
                    }
                }
 
            }
        }//end list_itemgroup
    }//end list_delegate
 
    //勾选时放入arr中
    function check(itemFlag){
        checkedArray.push(itemFlag);
    }
 
    //取消勾选时从arr移除
    function uncheck(itemFlag){
        var i = checkedArray.length;
 
        while (i--) {
            if (checkedArray[i] === itemFlag) {
                checkedArray.splice(i,1);
                break;
            }
        }
    }
 
    //判断是否check
    function isChecked(itemFlag){
        var i = checkedArray.length;
 
        while (i--) {
            if (checkedArray[i] === itemFlag) {
                return true;
            }
        }
        return false;
    }
}
//main.qml

import QtQuick 2.7
import QtQuick.Controls 2.7
import QtQuick.Window 2.7
 
Window {
    id: root_window
    visible: true
    width: 640
    height: 480
    title: qsTr("QmlTreeView By GongJianBo")
    color: Qt.rgba(3/255,26/255,35/255,1)
 
    //滚动条可以自己设置
    //ListView横向滚动条需要设置如下两个参数(如果是竖向的ListView)
    //contentWidth: 500
    //flickableDirection: Flickable.AutoFlickIfNeeded
    TreeView{
        id: item_tree
        width: parent.width/2
        anchors{
            left: parent.left
            top: parent.top
            bottom: parent.bottom
            margins: 10
        }
        //model: []
 
        //set model data
        Component.onCompleted: {
            console.log(1)
            root_window.setTestDataA();
            console.log(2)
        }
    }
 
    Column{
        anchors{
            right: parent.right
            top: parent.top
            margins: 10
        }
        spacing: 10
        Button{
            text: "ChangeModel"
            checkable: true
            //changed model data
            onClicked: {
                if(checked){
                    root_window.setTestDataB();
                }else{
                    root_window.setTestDataA();
                }
            }
        }
        Button{
            text: "AutoExpand"
            onClicked: item_tree.autoExpand=!item_tree.autoExpand
        }
    }
 
    function setTestDataA(){
        item_tree.model=JSON.parse('[
        {
            "text":"1 one",
            "istitle":true,
            "subnodes":[
                {"text":"1-1 two","istitle":true},
                {
                    "text":"1-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"1-2-1 three","isoption":true},
                        {"text":"1-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {
            "text":"2 one",
            "istitle":true,
            "subnodes":[
                {"text":"2-1 two","istitle":true},
                {
                    "text":"2-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"2-2-1 three","isoption":true},
                        {"text":"2-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {
            "text":"3 one",
            "istitle":true,
            "subnodes":[
                {"text":"3-1 two","istitle":true},
                {"text":"3-2 two","istitle":true}
            ]
        },
        {
            "text":"4 one",
            "istitle":true,
            "subnodes":[
                {"text":"4-1 two","istitle":true},
                {
                    "text":"4-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"4-2-1 three","isoption":true},
                        {"text":"4-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {
            "text":"5 one",
            "istitle":true,
            "subnodes":[
                {"text":"5-1 two","istitle":true},
                {
                    "text":"5-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"5-2-1 three","isoption":true},
                        {"text":"5-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {
            "text":"6 one",
            "istitle":true,
            "subnodes":[
                {"text":"6-1 two","istitle":true},
                {"text":"6-2 two","istitle":true}
            ]
        }
    ]')
    }
 
    function setTestDataB(){
        item_tree.model=JSON.parse('[
        {
            "text":"1 one",
            "istitle":true,
            "subnodes":[
                {
                    "text":"1-1 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"1-1-1 three","isoption":true},
                        {"text":"1-1-2 three","isoption":true}
                    ]
                },
                {
                    "text":"1-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"1-2-1 three","isoption":true},
                        {"text":"1-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {
            "text":"2 one",
            "istitle":true,
            "subnodes":[
                {"text":"2-1 two","istitle":true},
                {
                    "text":"2-2 two",
                    "istitle":true,
                    "subnodes":[
                        {"text":"2-2-1 three","isoption":true},
                        {"text":"2-2-2 three","isoption":true}
                    ]
                }
            ]
        },
        {"text":"3 one","istitle":true},
        {
            "text":"4 one",
            "istitle":true,
            "subnodes":[
                {"text":"4-1 two","istitle":true},
                {"text":"4-2 two","istitle":true}
            ]
        }
    ]')
    }
}
2.参考
思路参考:https://github.com/peihaowang/QmlTreeWidget

ListView 文档:https://doc.qt.io/qt-5/qml-qtquick-listview.html

相关文章:

treeview

QML自定义一个TreeView&#xff0c;使用ListView递归 在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件&#xff08;在 Qt6 中出了一个继承自 TableView 的 TreeView&#xff09;&#xff0c;而且 QtQuick.Controls 1.x 中的也需要配合 C model 来自定义&#xff0c…...

Android开发中自定义View实现RecyclerView下划线

本篇文章主要讲解的是有关RecyclerView下划线的使用&#xff0c;主要有几个方法&#xff0c;具体如下&#xff1a; 第一种方式&#xff1a;网格分割线 public class GridDivider extends RecyclerView.ItemDecoration { private Drawable mDividerDarwable; private i…...

MySQL前百分之N问题--percent_rank()函数

PERCENT_RANK()函数 PERCENT_RANK()函数用于将每行按照(rank - 1) / (rows - 1)进行计算,用以求MySQL中前百分之N问题。其中&#xff0c;rank为RANK()函数产生的序号&#xff0c;rows为当前窗口的记录总行数 PERCENT_RANK()函数返回介于 0 和 1 之间的小数值 selectstudent_…...

【高效开发工具系列】Wolfram Alpha

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

分享7种SQL的进阶用法

推荐一款ChatGPT4.0国内站点,每日有免费使用额度,支持PC、APP、VScode插件同步使用 SQL(Structured Query Language)是一种强大的数据库查询和操作语言,它用于与关系数据库进行交互。随着数据的不断增长和应用需求的日益复杂,掌握SQL的进阶用法对于数据库管理员、数据分析…...

protobuf-go pragma.go 文件介绍

pragma.go 文件 文件位于&#xff1a; https://github.com/protocolbuffers/protobuf-go/blob/master/internal/pragma/pragma.go 该文件核心思想&#xff1a; 利用 Golang 语法机制&#xff0c;扩展 Golang 语言特性 目前&#xff0c;该文件提供以下 4 个功能&#xff1a; …...

C#设置程序开机启动

1&#xff1a;获取当前用户&#xff1a; System.Security.Principal.WindowsIdentity identity System.Security.Principal.WindowsIdentity.GetCurrent();System.Security.Principal.WindowsPrincipal principal new System.Security.Principal.WindowsPrincipal(identity);…...

爱可声助听器参与南湖区价值百万公益助残捐赠活动成功举行

“声音大小合适吗&#xff1f;能听清楚吗&#xff1f;”今天下午&#xff0c;一场助残捐赠活动在南湖区凤桥镇悄然举行&#xff0c;杭州爱听科技有限公司带着验配团队和听力检测设备来到活动现场&#xff0c;为南湖区听障残疾人和老人适配助听器。 家住余新镇的75岁的周奶奶身体…...

SpringBoot 实现定时任务

在项目我们会有很多需要在某一特定时刻自动触发某一时间的需求&#xff0c;例如我们提交订单但未支付的超过一定时间后需要自动取消订单。 定时任务实现的几种方式&#xff1a; Timer&#xff1a;java自带的java.util.Timer类&#xff0c;使用这种方式允许你调度一个java.util…...

将Vue2中的console.log调试信息移除

前端项目构建生产环境下的package时&#xff0c;咱们肯定要去掉development环境下的console.log&#xff0c;如果挨个注释可就太费劲了&#xff0c;本文介绍怎么使用 babel-plugin-transform-remove-console 移除前端项目中所有的console.log. 1. 安装依赖 npm install babel-…...

EMC设计检查建议,让PCB layout达到最佳性能

EMC&#xff1a;Electro Magnetic Compatibility的简称&#xff0c;也称电磁兼容&#xff0c;各种电气或电子设备在电磁环境复杂的共同空间中&#xff0c;以规定的安全系数满足设计要求的正常工作能力。 本章对于 RK3588产品设计中的 ESD/EMI防护设计及EMC的设计检查给出了建议…...

常用抓包软件集合(Fiddler、Charles)

1. Fiddler 介绍&#xff1a;Fiddler是一个免费的HTTP和HTTPS调试工具&#xff0c;支持Windows平台。它可以捕获HTTP和HTTPS流量&#xff0c;并提供了丰富的调试和分析功能。优点&#xff1a;易于安装、易于使用、支持多种扩展、可以提高开发效率。缺点&#xff1a;只支持Wind…...

C++入门(一)— 使用VScode开发简介

文章目录 C 介绍C 擅长领域C 程序是如何开发编译器、链接器和库编译预处理编译阶段汇编阶段链接阶段 安装集成开发环境 &#xff08;IDE&#xff09;配置编译器&#xff1a;构建配置配置编译器&#xff1a;编译器扩展配置编译器&#xff1a;警告和错误级别配置编译器&#xff1…...

PeakCAN连接到WSL2 Debian

操作步骤 按照以下步骤进行操作&#xff1a; 在Windows下安装PeakCAN驱动并安装&#xff0c;地址是https://www.peak-system.com/PCAN-USB.199.0.html?&L1 在Windows下安装usbipd&#xff0c;地址是https://github.com/dorssel/usbipd-win/releases&#xff0c;最新版是…...

Spring Boot导出EXCEL 文件

主要功能:实现java导出excel到本地 JDK版本&#xff1a;openJDK 20.0.1 依赖pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchem…...

编程笔记 html5cssjs 060 css响应式布局

编程笔记 html5&css&js 060 css响应式布局 一、响应式布局二、Bootstrap简介总结 CSS响应式布局是一种可以在不同设备&#xff08;例如桌面电脑、平板电脑、手机等&#xff09;上自动调整页面布局和样式的技术。 一、响应式布局 使用CSS响应式布局的关键是媒体查询&am…...

建筑行业如何应用3D开发工具HOOPS提升实时设计体验?

建筑行业一直在迅速发展&#xff0c;技术的不断创新也为其带来了新的机遇与挑战。在这一领域&#xff0c;三维图形技术的应用变得尤为重要。HOOPS技术&#xff0c;作为一套用于开发三维图形应用程序的工具和库&#xff0c;为建筑行业带来了深刻的变革。本文将探讨HOOPS技术在建…...

【grafana】使用教程

【grafana】使用教程 一、简介二、下载及安装及配置三、基本概念3.1 数据源&#xff08;Data Source&#xff09;3.2 仪表盘&#xff08;Dashboard&#xff09;3.3 Panel&#xff08;面板&#xff09;3.4 ROW&#xff08;行&#xff09;3.5 共享及自定义 四、常用可视化示例4.1…...

seata 分布式

一、下载安装seata 已经下载好的朋友可以跳过这个步骤。这里下载的是seata1.6.1这个版本。 1、进入seata官网 地址&#xff1a; https://seata.io/zh-cn/index.html 2、进入下载 3、点击下载地址 下载地址&#xff1a; https://github.com/seata/seata 二、配置seata 进入c…...

前端面试题-说说你了解的js数据结构?(2024.1.29)

1、数组 (Array) 数组是一组有序的值的集合&#xff0c;可以通过索引访问。JavaScript 数组可以包含不同的数据类型&#xff0c;并且长度是动态的。 let myArray [1, hello, true, [2, 3]];2、对象 (Object) 对象是无序的键值对的集合。每个键都是字符串或符号&#xff0c;…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...