Qt Graphs 模塊擬取代 charts 和 data visualization還有很長的路要走

近期關注 Qt 6.10 的分支進展, 發現了 Qt 6.10 的 charts 和 data visualization (以下簡稱 DV)已經被deprecated, 功能將會合并到 graphs 模塊。如果后面 charts\ DV 被棄用,那算是很大的API變化了。從Qt 6.5 以后開始引入的 graphs 使用的是QML的渲染器,和之前的 Qt Widgets GraphicsView 完全不同。如果有依賴上述模塊的應用,需要提前評估API的變化。

1. 可能遇到的主要問題

只要是和QML相關的東西,那問題無外乎就是老電腦的兼容性,以及跨語言的API。

1.1 老舊和低成本環境可能不再適用

QML的渲染器過度依賴OS的本地3D加速API,如 Windows的 DirectX。在VMWare/VirtualBox環境下,QML有概率無法正常渲染圖形。在只有核心顯卡,沒有配置獨立顯卡的低成本計算機上,QML也非常卡頓,甚至可能無法啟動(如果驅動比較老或者配置不正確)。

與之形成對比的,是Widgets的2D渲染,基本是在backend里自繪的,因此,不但可以支持老舊計算機,還能在 vnc、framebuf里使用。

1.2 跨語言API調用和性能問題

charts和DV是支持C++ Only模式的開發的。但是, graphs 卻不是。官網的例子里,C++ Widgets 程序使用 graphs 必須要進行QML混合編程。這里就牽扯到三個場景:

  1. 從C++中動態向 QML 刷新曲線,特別是1秒刷新23次的這種動畫。
  2. 從C++中精確獲得QML圖元的signal,如橡皮筋選擇、有圖元被雙擊等等。
  3. 從C++中查詢各個圖元的屬性和狀態。比如查詢視圖的寬度、高度,選中的狀態等。

這些操作要達到高性能、易于使用,需要特別注意不出現內存深度拷貝,且管理好QObject對象樹的生命周期(life-cycle)。

2. 初步試用

抱著試試看的態度,初步對 Qt Graphs的API進行了研究,并以最簡單的動態折線圖進行了開發測試。

pro文件

模塊包括 quickwidgets graphs quick 等模塊。

QT       += core gui widgets quickwidgets graphs quickCONFIG += c++17SOURCES += \main.cpp \graphstest.cppHEADERS += \graphstest.hFORMS += \graphstest.ui

2.2 main.cpp

#include "graphstest.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);graphsTest w;w.show();return a.exec();
}

2.3 graphstest.h

#ifndef GRAPHSTEST_H
#define GRAPHSTEST_H#include <QDateTimeAxis>
#include <QDialog>
#include <QLineSeries>
#include <QValueAxis>
#include <QVector>
QT_BEGIN_NAMESPACE
namespace Ui
{
class graphsTest;
}
QT_END_NAMESPACEclass graphsTest : public QDialog
{Q_OBJECTpublic:graphsTest(QWidget *parent = nullptr);~graphsTest();protected:void timerEvent(QTimerEvent *evt) override;
private slots:void on_pushButton_add_clicked();void on_checkBox_update_clicked();private:Ui::graphsTest *ui;QDateTimeAxis *m_ax;QValueAxis *m_ay;int m_timerEvent;QVector<QLineSeries *> m_lineSeries;
};
#endif // GRAPHSTEST_H

2.4 graphstest.cpp

#include "graphstest.h"
#include <QDateTime>
#include <QDebug>
#include <QQuickItem>
#include "ui_graphstest.h"
graphsTest::graphsTest(QWidget *parent): QDialog(parent), ui(new Ui::graphsTest), m_ax(new QDateTimeAxis(this)), m_ay(new QValueAxis(this)), m_timerEvent(-1)
{ui->setupUi(this);QDateTime dtmNow = QDateTime::currentDateTime();m_ax->setMin(dtmNow.addDays(-1));m_ax->setMax(dtmNow);m_ay->setRange(-100, 100);QList<QObject *> seriesList;ui->graphsView->setResizeMode(QQuickWidget::SizeRootObjectToView);ui->graphsView->setInitialProperties({{"seriesList", QVariant::fromValue(seriesList)},{"axisX", QVariant::fromValue(m_ax)},{"axisY", QVariant::fromValue(m_ay)},{"zoomAreaEnabled", true}});ui->graphsView->loadFromModule("QtGraphs", "GraphsView");
}graphsTest::~graphsTest()
{delete ui;
}void graphsTest::timerEvent(QTimerEvent *evt)
{if (evt->timerId() == m_timerEvent){QList<QPointF> data;QDateTime dtmNow = QDateTime::currentDateTime();const int N = m_lineSeries.size();for (int n = 0; n < N; ++n){for (int i = 0; i < 30; ++i){data << QPointF(dtmNow.addSecs(-3600 * 24.0 / 30 * (29 - i)).toMSecsSinceEpoch(),(rand() % 500 - 250) / 100.0 + n * 16 - 80);}m_lineSeries[n]->replace(data);}m_ax->setMin(dtmNow.addDays(-1));m_ax->setMax(dtmNow);if (!ui->checkBox_update->isChecked()){killTimer(m_timerEvent);m_timerEvent = -1;}}QDialog::timerEvent(evt);
}void graphsTest::on_pushButton_add_clicked()
{if (m_lineSeries.size() >= 10)return;//Add to GraphQVariant seriesListVariant = ui->graphsView->rootObject()->property("seriesList");if (seriesListVariant.canConvert<QQmlListProperty<QObject>>()){QLineSeries *newLine = new QLineSeries(this);newLine->setColor(QColor(rand() % 128, rand() % 128, rand() % 128));newLine->setHoverable(true);newLine->setName(QString("Testing %1").arg(m_lineSeries.size()));connect(newLine,&QAbstractSeries::hover,[this](const QString &seriesName, QPointF position, QPointF value) -> void{ui->lineEdit_msg->setText(QString("%1:%2 %3 = %4 %5").arg(seriesName).arg(position.x()).arg(position.y()).arg(value.x()).arg(value.y()));});//AddQQmlListProperty<QObject> prop = seriesListVariant.value<QQmlListProperty<QObject>>();prop.append(&prop, newLine);m_lineSeries.append(newLine);}if (m_timerEvent < 0)m_timerEvent = startTimer(500);
}void graphsTest::on_checkBox_update_clicked()
{if (ui->checkBox_update->isChecked())m_timerEvent = startTimer(500);
}

2.5 graphstest.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>graphsTest</class><widget class="QDialog" name="graphsTest"><property name="geometry"><rect><x>0</x><y>0</y><width>579</width><height>332</height></rect></property><property name="windowTitle"><string>graphsTest</string></property><layout class="QVBoxLayout" name="verticalLayout_2"><item><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QQuickWidget" name="graphsView"><property name="resizeMode"><enum>QQuickWidget::ResizeMode::SizeRootObjectToView</enum></property></widget></item><item><layout class="QVBoxLayout" name="verticalLayout"><property name="sizeConstraint"><enum>QLayout::SizeConstraint::SetMaximumSize</enum></property><item><widget class="QPushButton" name="pushButton_add"><property name="sizePolicy"><sizepolicy hsizetype="Fixed" vsizetype="Fixed"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property><property name="text"><string>Add Serials</string></property></widget></item><item><widget class="QCheckBox" name="checkBox_update"><property name="sizePolicy"><sizepolicy hsizetype="Maximum" vsizetype="Fixed"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property><property name="text"><string>Updating</string></property></widget></item><item><spacer name="verticalSpacer"><property name="sizePolicy"><sizepolicy hsizetype="Fixed" vsizetype="Expanding"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property><property name="orientation"><enum>Qt::Orientation::Vertical</enum></property><property name="sizeHint" stdset="0"><size><width>20</width><height>40</height></size></property></spacer></item></layout></item></layout></item><item><widget class="QLineEdit" name="lineEdit_msg"><property name="sizePolicy"><sizepolicy hsizetype="Expanding" vsizetype="Fixed"><horstretch>0</horstretch><verstretch>0</verstretch></sizepolicy></property></widget></item></layout></widget><customwidgets><customwidget><class>QQuickWidget</class><extends>QWidget</extends><header location="global">QtQuickWidgets/QQuickWidget</header></customwidget></customwidgets><resources/><connections/>
</ui>

3. 運行效果

運行效果如下,主要問題包括(BUG):

  1. 新插入的對象的色彩,會影響到舊對象的色彩。
  2. 各個連線的收尾會連接起來。

add

4 評價

Qt 團隊看起來對傳統的 Widgets 已經不是很愿意維護了,這種大規模的API變化,以及完全不顧及兼容老計算機、集成顯卡的環境的激進改進,要么是公司no zuo no die,要么說明QML技術的趨勢已經勢不可擋。

QML技術與C++的緊密互動,相當程度的緩解了API跨語言的問題,其實QML就是個調用C++ QObject 運行時的膠水語言,其和C++的聯系非常緊密。對Qt Widgets而言,如果使用了 QML的功能,就會在硬件兼容性上面大打折扣,這對于很多桌面場景而言是不能接受的。對未來技術的發展,我們會保持持續的跟蹤,并適時為我們使用 charts 的既有代碼進行 graphs的適配,并在具備 charts 的環境下優先使用 charts.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89846.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89846.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89846.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025牛客暑期多校訓練營2(部分補題)

題目鏈接&#xff1a;牛客競賽_ACM/NOI/CSP/CCPC/ICPC算法編程高難度練習賽_牛客競賽OJ B Bitwise Perfect 思路 考慮到由&#xff0c;那么只有變小的時候對答案的貢獻才能夠減少&#xff0c;從二進制的角度考慮什么時候變小&#xff0c;只有min(x,y)中的最高位1異或之后變…

Nginx的location匹配規則

Nginx的location匹配規則 為什么你的Nginx配置總是不生效&#xff1f; 改了Nginx配置無數次&#xff0c;reload命令執行了幾十遍&#xff0c;瀏覽器訪問時卻依然返回404&#xff1f;運維工程師小張上周就遇到了這個問題&#xff1a;明明配置了location /static/ { root /var/ww…

USB 2.0 vs USB 3.0:全面技術對比與選擇指南

USB 2.0 vs USB 3.0&#xff1a;全面技術對比與選擇指南 引言 在當今數字時代&#xff0c;USB接口已成為連接設備與計算機的最普遍標準之一。從2000年USB 2.0的發布到2008年USB 3.0的問世&#xff0c;USB技術經歷了顯著的演進。本文將深入比較這兩種廣泛使用的USB標準&#xff…

DApp架構設計與開發流程指南

目錄 DApp架構設計與開發流程指南 引言:DApp的核心特性 一、DApp架構設計 1.1 分層架構設計 各層核心組件: 1.2 典型架構模式 1.2.1 全去中心化架構 1.2.2 混合架構(推薦) 二、開發流程 2.1 敏捷開發流程 2.2 詳細開發階段 階段1:需求分析與設計(1-2周) 階段2:智能合約…

Windows下odbc配置連接SQL Server

一、查看SQL Server服務是否啟動打開SQL Server 2022配置管理器查看SQL Server運行狀態&#xff0c;可以設置 啟動或停止服務二、windows下如何配置ODBC數據源1、Windows搜索欄中輸入“ODBC數據源管理器”并選擇“以管理員身份運行”來打開它2、添加新的數據源ODBC數據源管理器…

MySQL—表設計和聚合函數以及正則表達式

文章目錄一、第一范式&#xff08;原子性&#xff09;二、第二范式&#xff08;消除部分依賴&#xff09;三、第三范式&#xff08;消除傳遞依賴&#xff09;四、表設計五、聚合函數六、正則表達式MySQL 的三大范式&#xff08;1NF、2NF、3NF&#xff09;是關系型數據庫設計的核…

基于Electron打包jar成Windows應用程序

基于Electron打包jar成Windows應用程序簡介注意編譯及命令&#xff1a;運行效果登錄界面用戶管理界面界面全屏鎖屏界面文檔查看界面簡介 本文介紹了一種將maven jar包打包成Windows下EXE可執行程序的方法。 Maven打包Java Web應用成jar&#xff0c;Electron封裝jar成Windows …

Autosar RTE實現觀測量生成-基于ETAS軟件

文章目錄前言觀測量定義arTypedPerInstanceMemoryPorts Measurable工具鏈配置及使用Port中的配置arTypedPerInstanceMemory觀測量生成文件分析總結前言 之前我們在XCP中&#xff0c;對于標定量和觀測量并沒有嚴格按照Autosar標準中定義&#xff0c;Autosar RTE中對標定量和觀測…

【REACT18.x】creat-react-app在添加eslint時報錯Environment key “jest/globals“ is unknown

今天在創建新項目的時候&#xff0c;給cra創建的項目添加eslint支持&#xff0c;出現如下報錯 添加eslint npx eslint --init頁面報錯 Compiled with problems:ERROR [eslint] package.json eslint-config-react-app/jest#overrides[0]:Environment key "jest/globals&…

Linux的例行性工作 -- (練習)

1、atd和crond兩個任務管理程序的區別 答&#xff1a; atd 專為一次性任務設計&#xff0c;允許用戶在特定未來時間點&#xff08;絕對或相對時間&#xff09;執行單次命令后就結束。 crond 則是周期性任務的調度核心&#xff0c;通過配置文件&#xff08;crontab&#xff09;實…

《Java語言程序設計》1.6 復習題

1.6.1 什么是Java語言規范?計算機有嚴格的使用規則。如果編寫程序時沒有遵循這些規則&#xff0c;計算機就不能理解程序。Java語言規范和Java API定義了Java的標準。Java語言規范(Java language specification)是對Java程序設計語言的語法和語義的技術定義。應用程序接口(Appl…

【機器學習深度學習】什么是量化?

目錄 前言 一、量化的基本概念 1.1 量化對比示例 1.2 量化是如何實現的&#xff1f; 二、為什么要進行量化&#xff1f; 2.1 解決模型體積過大問題 2.2 降低對算力的依賴 2.3 加速模型訓練和推理 2.4 優化訓練過程 2.5 降低部署成本 小結&#xff1a;量化的應用場…

告別 T+1!解密金融級實時數據平臺的構建與實踐

在數字金融浪潮下&#xff0c;數據處理的“實時性”已不再是加分項&#xff0c;而是逐漸成為決定業務價值的核心競爭力。然而&#xff0c;金融機構在追求實時的道路上&#xff0c;往往陷入一個新的困境&#xff1a;實時分析系統與離線大數據平臺形成了兩套獨立的“煙囪”&#…

[Python] -項目實戰7- 用Python和Tkinter做一個圖形界面小游戲

一、為什么從小游戲入門GUI? 趣味性強:小游戲直觀、有趣,一學就上手。 系統掌握事件驅動:了解按鈕點擊、鍵盤響應、圖形刷新機制。 扎實基礎:為日后構建更復雜應用奠定 GUI 編程基礎。 二、選定游戲:猜數字小游戲 ?? 這個小游戲界面簡單,核心機制是:3 個按鈕分別…

【18】MFC入門到精通——MFC(VS2019)+ OpenCV 顯示圖片的3種方法

MFC (VS2019)+ OpenCV,顯示圖片的3種方法 1 方法介紹 2 方法一:嵌套OpenCV窗口顯示圖片 2.1 建立供工程 添加控件 2.2 引用頭文件 2.3 找到OnInitDialog()函數,在其中添加如下代碼 2.4 在button觸發函數中加入代碼(就是你雙擊button進入的函數) 2.5 注意事項 3 方法二:…

以“融合進化 智領未來”之名,金倉Kingbase FlySync:國產數據庫技術的突破與創新

目錄開篇&#xff1a;國產數據庫的歷史性跨越一、KFS 產品定位及發展歷程回顧1.1 Kingbase FlySync 發展1.2 Kingbase FlySync與Oracle GoldenGate的對比分析1.2.1 Kingbase FlySync 功能優勢1.2.2 技術架構對比1.2.3 性能與擴展性二、數字化時代的新挑戰2.1 決策實時性要求越來…

服務器配置錯誤漏洞

文章目錄一、文件解析漏洞1.Apache HTTPD多后綴解析漏洞二、目錄遍歷漏洞1.Apache目錄遍歷漏洞2.Nginx目錄穿越漏洞服務器配置錯誤漏洞指因服務器&#xff08;含系統、Web服務、數據庫等&#xff09;的參數設置、權限分配、組件配置等不當&#xff0c;導致的安全問題&#xff0…

大模型預測輸尿管上段結石技術方案大綱

目錄 1. 術前階段 2. 術中階段 3. 術后階段 4. 并發癥風險預測 5. 根據預測定手術方案 6. 麻醉方案 7. 術后護理 8. 統計分析 9. 技術驗證方法 10. 實驗證據 11. 健康教育與指導 12. 完整術方案流程圖(Mermaid) 1. 術前階段 步驟 關鍵要素 可編輯字段 1.1 影像采集 CT-IVU / …

docker compose 編排容器 mysql Springboot應用

寫一個docker-compose.yml文件 內容如下&#xff1a; services:db:image: "docker.xuanyuan.me/library/mysql:8.3.0"restart: unless-stoppedhostname: dbports:- "3306:3306"container_name: mysqlenvironment:- "MYSQL_ROOT_PASSWORD1234"m…

React 中 props 的最常用用法精選+useContext

? React 最常用 props 用法 10 例? 1. 傳遞字符串 / 數字 / 布爾值function UserCard({ name, age, isVip }) {return (<div>{name} - {age} - {isVip ? VIP : 普通用戶}</div>); }<UserCard name"張三" age{18} isVip{true} />? 2. 傳遞函數&…