Qt圖形圖像開發(fā)之Qt曲線圖美化QChart QScatterSeries 空心點(diǎn)陣圖,鼠標(biāo)移動(dòng)到上面顯示數(shù)值,鼠標(biāo)移開數(shù)值消失效果實(shí)例
最近接到一個(gè)Qt QChart曲線圖美化的需求,畫一個(gè)折線圖,關(guān)鍵點(diǎn)使用空心的圓點(diǎn)標(biāo)識(shí)出來(lái),鼠標(biāo)移動(dòng)到關(guān)鍵點(diǎn)上,顯示出當(dāng)前數(shù)值;鼠標(biāo)移走數(shù)值消失。
效果圖如下:
我們遇到這個(gè)需求的時(shí)候,第一時(shí)間就會(huì)想到使用 QLineSeries 畫折線圖。
首先初始化
QChart *chart = new QChart(); chart->legend()->setVisible(false); ui->chartView->setChart(chart); ui->chartView->setRenderHint(QPainter::Antialiasing); chart->setBackgroundBrush(QBrush(QColor(248, 251, 255)));
將每個(gè)點(diǎn)添加到QLineSeries序列中。然后就會(huì)形成折線圖。如下:
QChart *chart = ui->chartView->chart(); chart->removeAllSeries(); chart->removeAxis(chart->axisX()); chart->removeAxis(chart->axisY()); //折線圖 QLineSeries *series0 = new QLineSeries(); QPen pen; pen.setStyle(Qt::SolidLine); pen.setWidth(4); pen.setColor(QColor(21, 100, 255)); series0->setPen(pen);//折現(xiàn)序列的線條設(shè)置 QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0); series0->clear(); qsrand(QTime::currentTime().second()); qreal t=0, y1, intv=1; qreal rd; int cnt=16; for (int i=0; i<cnt; i++) { rd = (qrand() % 100); y1=rd; series0->append(t, y1); t+=intv; }
這是完成了第一步,畫出來(lái)了折線圖。但是對(duì)于那些圓點(diǎn)要顯示出來(lái)的話我們可以考慮使用QScatterSeries來(lái)畫一些離散的點(diǎn)。
QScatterSeries *series1 = new QScatterSeries(); series1->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點(diǎn) series1->setBorderColor(QColor(21, 100, 255)); //離散點(diǎn)邊框顏色 series1->setBrush(QBrush(QColor(21, 100, 255)));//離散點(diǎn)背景色 series1->setMarkerSize(12); //離散點(diǎn)大小 QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0); QScatterSeries *series1 = (QScatterSeries *)ui->chartView->chart()->series().at(1); series0->clear(); series1->clear(); qsrand(QTime::currentTime().second()); qreal t=0, y1, intv=1; qreal rd; int cnt=16; for (int i=0; i<cnt; i++) { rd = (qrand() % 100); y1=rd; series0->append(t, y1); series1->append(t, y1); t+=intv; }
然后我們添加了一些離散的點(diǎn),效果如下圖:
很顯然,雖然添加了離散的圓形的點(diǎn),但是并沒(méi)有滿足我們的需求,因?yàn)樾枨笫强招牡膱A點(diǎn)。而且控件也沒(méi)提供相關(guān)函數(shù)可以設(shè)置成空心。但是這里面有3個(gè)函數(shù)值得注意
series1->setBorderColor(QColor(21, 100, 255)); //離散點(diǎn)邊框顏色 series1->setBrush(QBrush(QColor(21, 100, 255)));//離散點(diǎn)背景色 series1->setMarkerSize(12); //離散點(diǎn)大小
因?yàn)榭梢栽O(shè)置一個(gè)點(diǎn)的大小,邊框和顏色。那我們?nèi)绻雽?shí)現(xiàn)一個(gè)空心的離散點(diǎn)就可以這樣做:
以同一個(gè)位置為圓心,畫兩個(gè)半徑不同的實(shí)心圓。下面的圓半徑大,顏色就是邊框的顏色藍(lán)色;上面的圓形半徑小,顏色設(shè)置為白色。這樣兩個(gè)圓形疊加起來(lái)的效果,視覺(jué)上就是一個(gè)空心的圓形。按照這個(gè)思路,我們需要使用2個(gè)QScatterSeries序列
series0 : 半徑較大,背景為藍(lán)色,充當(dāng)邊框。
series1:半徑較小,北京為白色,充電圓心。
//散點(diǎn)圖(用于邊框) QScatterSeries *series1 = new QScatterSeries(); series1->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點(diǎn) series1->setBorderColor(QColor(21, 100, 255)); //邊框顏色 series1->setBrush(QBrush(QColor(21, 100, 255)));//背景顏色 series1->setMarkerSize(12); //點(diǎn)大小 //散點(diǎn)圖(用于中心) QScatterSeries *series2 = new QScatterSeries(); series2->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點(diǎn) series2->setBorderColor(Qt::white);//邊框顏色 series2->setBrush(QBrush(Qt::white));//背景顏色 series2->setMarkerSize(6);//點(diǎn)大小 chart->addSeries(series1); chart->addSeries(series2); QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0); QScatterSeries *series1 = (QScatterSeries *)ui->chartView->chart()->series().at(1); QScatterSeries *series2 = (QScatterSeries *)ui->chartView->chart()->series().at(2); series0->clear(); series1->clear(); series2->clear(); qsrand(QTime::currentTime().second()); qreal t=0, y1, intv=1; qreal rd; int cnt=16; for (int i=0; i<cnt; i++) { rd = (qrand() % 100); y1=rd; series0->append(t, y1); series1->append(t, y1); series2->append(t, y1); t+=intv; }
效果如下:
做完這些,我們還有最后一個(gè)需求就是鼠標(biāo)移動(dòng)到這些離散的點(diǎn)上,要顯示出當(dāng)前點(diǎn)的數(shù)值。由于框架并沒(méi)有提供相關(guān)的api,所以我們要自己完成這項(xiàng)工作。我們可以想象,顯示的數(shù)值需要使用QLabel承載,當(dāng)鼠標(biāo)移動(dòng)到這些點(diǎn)上,QLabel就show,移開就hide。那么怎么確定鼠標(biāo)是否移動(dòng)到這些離散點(diǎn)上呢?查閱文檔,我們發(fā)現(xiàn)QCatterSeries有這樣一個(gè)信號(hào)
他的意思就是,這是一個(gè)信號(hào),當(dāng)鼠標(biāo)移動(dòng)到上面,或者從上面移開就會(huì)發(fā)射這個(gè)信號(hào),其中point是移動(dòng)到哪個(gè)點(diǎn)上,當(dāng)移動(dòng)到上面,state=true;否則state就為false。
我們可以連接這個(gè)信號(hào)到我們自己的槽函數(shù)
connect(series2, &QScatterSeries::hovered, this, &TDMTrendChartForm::slotPointHoverd);//用于鼠標(biāo)移動(dòng)到點(diǎn)上顯示數(shù)值
void TDMTrendChartForm::slotPointHoverd(const QPointF &point, bool state) { if (state) { m_valueLabel->setText(QString::asprintf("%1.0f%", point.y())); QPoint curPos = mapFromGlobal(QCursor::pos()); m_valueLabel->move(curPos.x() - m_valueLabel->width() / 2, curPos.y() - m_valueLabel->height() * 1.5);//移動(dòng)數(shù)值 m_valueLabel->show();//顯示出來(lái) } else m_valueLabel->hide();//進(jìn)行隱藏 }
實(shí)例源碼中完善些代碼,增加鼠標(biāo)懸浮在離散點(diǎn)上,應(yīng)該顯示漸變的邊框。
這樣我們就完成了相關(guān)功能。完整代碼可以在這里下載
本文主要講解了Qt曲線圖美化QCharts QScatterSeries 空心點(diǎn)陣圖,鼠標(biāo)移動(dòng)到上面顯示數(shù)值,鼠標(biāo)移開數(shù)值消失效果實(shí)例,更多關(guān)于Qt曲線圖QCharts模塊的知識(shí)請(qǐng)查看下面的相關(guān)鏈接
相關(guān)文章
C++編程中使用設(shè)計(jì)模式中的policy策略模式的實(shí)例講解
這篇文章主要介紹了C++編程中使用設(shè)計(jì)模式中的policy策略模式的實(shí)例講解,文章最后對(duì)策略模式的優(yōu)缺點(diǎn)有一個(gè)簡(jiǎn)單的總結(jié),需要的朋友可以參考下2016-03-03C語(yǔ)言數(shù)組實(shí)現(xiàn)三子棋應(yīng)用實(shí)例
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)組實(shí)現(xiàn)三子棋應(yīng)用實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C++基于Boost.Asio實(shí)現(xiàn)端口映射器的過(guò)程詳解
Boost.Asio 是一個(gè)功能強(qiáng)大的 C++ 庫(kù),用于異步編程和網(wǎng)絡(luò)編程,它提供了跨平臺(tái)的異步 I/O 操作,在這篇文章中,我們將深入分析一個(gè)使用 Boost.Asio 實(shí)現(xiàn)的簡(jiǎn)單端口映射服務(wù)器,文中有詳細(xì)的代碼講解,需要的朋友可以參考下2023-11-11C++實(shí)現(xiàn)LeetCode(42.收集雨水)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(42.收集雨水),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言結(jié)構(gòu)體版學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言結(jié)構(gòu)體版的學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02