前言
前一篇介紹了橫向柱圖圖。本篇將介紹基礎餅圖使用,並將其封裝一層Qt。
本篇的demo使用隱藏js代碼的方式,實現了一個餅圖的基本交互方式,並預留了Qt模塊對外的基礎接口。
使用ECharts的在線調試器,先調試出大致預期的效果。
option = {
legend: {
top: '90%',
show: false
},
series: [
{
selectedMode: 'single', // 選擇模式
selectedOffset: 10, // 選取後偏移,需要先設置選擇模式才生效
type: 'pie', // 圖例類型
radius: ['60%', '90%'], // 同心圓雙邊界區域
itemStyle: { // 數據項樣式
borderRadius: 0, // 邊界圓角
borderColor: '#FF0000', // 邊界顏色
borderWidth: 0 // 邊界寬度
},
label: {
show: true,
fontSize: '32',
fontWeight: 'bold',
formatter: '{b}\n\n{d}%',
position: 'center'
},
emphasis: {
// 高亮狀態的扇區和標籤樣式
label: {
show: false,
fontSize: '32',
fontWeight: 'bold'
}
},
labelLine: {
show: true
},
data: [
{
value: 5.6,
name: '開機率',
itemStyle: {
color: 'rgb(41, 235, 255)',
shadowBlur: 10, // 外陰影
shadowOffsetX: 0, // 外陰影x軸偏移
shadowOffsetY: 0, // 外陰影y軸偏移
shadowColor: 'rgb(41, 235, 255)' // 外陰影顏色
}
},
{
value: 5.2,
name: '',
itemStyle: {
color: 'rgba(45,62,113)',
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(45,62,113)'
}
}
]
}
]
};
此係列的標準html文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ECharts</title>
<script src="./echarts.js"></script>
</head>
<body>
<style>
#main,
html,
body{
width: 100%;
height: 100%;
overflow: hidden;
}
#main {
width: 95%;
height: 95%;
}
</style>
<div id="main"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
window.onresize = function() {
myChart.resize();
};
</script>
</body>
</html>
這裏是我們不讓鼠標點擊,只用於觀看,鼠標相關的效果EChart4和EChart5也有一些不同,ECharts4交互的坑,查看本文章最後“入坑“章節。
void PieEChartWidget::initControl()
{
_pLabelCenterUp = new QLabel(this);
_pLabelCenterUp->raise();
_pLabelCenterUp->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
_pLabelCenterUp->setText(QSTRING("開機率"));
_pLabelCenterUp->setStyleSheet("font-size: 36px;"
"font-weight: bold;"
"align: top ;"
"color: rgb(41, 235, 255);"
"padding: 0 30 10 0;");
_pLabelCenterDown = new QLabel(this);
_pLabelCenterDown->raise();
_pLabelCenterDown->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
_pLabelCenterDown->setText(QSTRING("%1%").arg(0));
_pLabelCenterDown->setStyleSheet("font-size: 64px;"
"font-weight: bold;"
"align: center;"
"color: rgb(41, 235, 255);"
"padding: 0 30 0 0;");
_pWebEngineView = new QWebEngineView(this);
_pWebEnginePage = new QWebEnginePage(this);
_pWebChannel = new QWebChannel(this);
QString filePath;
#if 0
// 使用絕對路徑
filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#else
// 使用資源路徑
filePath = "qrc:/pieEChartWidget/html/eChartWidget.html";
#endif
LOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0
// 打印html文件內容
QFile file(_indexFilePath);
file.open(QIODevice::ReadOnly);
LOG << QString(file.readAll());
file.close();
#endif
connect(_pWebEnginePage, SIGNAL(loadFinished(bool)), this, SLOT(slot_loadFinished(bool)));
_pWebEnginePage->load(QUrl(filePath));
_pWebEnginePage->setWebChannel(_pWebChannel);
_pWebEngineView->setPage(_pWebEnginePage);
// 背景透明
// _pWebEngineView->setStyleSheet("background-color: transparent");
_pWebEnginePage->setBackgroundColor(Qt::transparent);
// 鼠標穿透
_pWebEngineView->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
設置百分數,文本上要注意位置偏移,手動進行校準:
void PieEChartWidget::setPercent(double percent)
{
if(percent < 0 || percent > 100)
{
return;
}
LOG << percent;
if(percent == 100)
{
_pLabelCenterDown->setText(QSTRING("100%"));
}else{
if(_percent < 10)
{
_pLabelCenterDown->setText(QSTRING("%1%").arg(percent, 0, 'g', 2));
}else{
_pLabelCenterDown->setText(QSTRING(" %1%").arg(percent, 0, 'g', 2));
}
}
QString jsStr = QSTRING(
"option.series[0].data[0].value = %1;"
"option.series[0].data[1].value = %2;"
"myChart.setOption(option, true);")
.arg(percent)
.arg(100 - percent);
LOG << jsStr;
_percent = percent;
runJsScript(jsStr);
}
void PieEChartWidget::on_pushButton_reset_clicked()
{
initJs();
}
void PieEChartWidget::on_pushButton_flush_clicked()
{
QString jsStr =
"var empty = {};"
"myChart.setOption(empty, true);"
"myChart.setOption(option, true);";
runJsScript(jsStr);
}
void PieEChartWidget::on_pushButton_createRandom_clicked()
{
float value = qrand() % 10001 / 100;
setPercent(value);
}
void PieEChartWidget::on_pushButton_clear_clicked()
{
setPercent(0.0f);
}
void PieEChartWidget::on_doubleSpinBox_valueChanged(double arg1)
{
setPercent(ui->doubleSpinBox->value());
}
#ifndef PIEECHARTWIDGET_H
#define PIEECHARTWIDGET_H
#include <QWidget>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QWebChannel>
#include <QLabel>
namespace Ui {
class PieEChartWidget;
}
class PieEChartWidget : public QWidget
{
Q_OBJECT
public:
explicit PieEChartWidget(QWidget *parent = 0);
~PieEChartWidget();
public:
void setPercent(double percent);
protected:
void initControl();
protected slots:
void slot_loadFinished(bool result);
protected:
void initJs();
protected:
void runJsScript(QString str);
protected:
void resizeEvent(QResizeEvent *event);
private slots:
void on_pushButton_clear_clicked();
void on_pushButton_flush_clicked();
void on_pushButton_createRandom_clicked();
void on_pushButton_reset_clicked();
void on_doubleSpinBox_valueChanged(double arg1);
private:
Ui::PieEChartWidget *ui;
private:
QWebEngineView *_pWebEngineView; // 瀏覽器窗口
QWebEnginePage *_pWebEnginePage; // 瀏覽器頁面
QWebChannel *_pWebChannel; // 瀏覽器js交互
QString _htmlDir; // html文件夾路徑
QString _indexFileName; // html文件
QLabel *_pLabelCenterUp; // 顯示文字的控件
QLabel *_pLabelCenterDown; // 顯示百分比的控件
QString _initJsStr; // 初始化的js字符串
QString _initValueJsStr; // 設置值的js字符串
private:
double _percent; // 百分比(0~100)
};
#endif // PIEECHARTWIDGET_H
#include "PieEChartWidget.h"
#include "ui_PieEChartWidget.h"
#include <QFile>
#include <QMessageBox>
#include <QTimer>
// QtCreator在msvc下設置編碼也或有一些亂碼,直接一刀切,避免繁瑣的設置
//#define MSVC
#ifdef MSVC
#define QSTRING(s) QString::fromLocal8Bit(s)
#else
#define QSTRING(s) QString(s)
#endif
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
PieEChartWidget::PieEChartWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PieEChartWidget),
_pWebEngineView(0),
_pWebEnginePage(0),
_pWebChannel(0),
_htmlDir("D:/qtProject/echartsDemo/echartsDemo/modules/PieEChartWidget/html"), // 使用了絕對路徑,引到html文件夾
_indexFileName("PieEChartWidget.html"),
_pLabelCenterUp(0),
_pLabelCenterDown(0)
{
ui->setupUi(this);
QString version = "v1.0.0";
setWindowTitle(QString("基於Qt的EChartb餅狀圖Demo %1(長沙紅胖子Qt").arg(version));
// 設置無邊框,以及背景透明
// 背景透明,在界面構架時,若爲本窗口爲其他窗口提升爲本窗口時,
// 則再qss會在主窗口第一級添加frame_all,防止其他窗口提升本窗口而沖掉qss設置
// setWindowFlag(Qt::FramelessWindowHint);
// setAttribute(Qt::WA_TranslucentBackground, true);
#if 0
// 這是方法一:讓滾動條不出來(通過大小),還有一個方法是在html設置body的overflow: hidden
// resize(600 + 20, 400 + 20);
#endif
initControl();
}
PieEChartWidget::~PieEChartWidget()
{
delete ui;
}
void PieEChartWidget::setPercent(double percent)
{
if(percent < 0 || percent > 100)
{
return;
}
LOG << percent;
if(percent == 100)
{
_pLabelCenterDown->setText(QSTRING("100%"));
}else{
if(_percent < 10)
{
_pLabelCenterDown->setText(