当前位置:嗨网首页>书籍在线阅读

06-三维柱状图的创建

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

10.2.3 三维柱状图的创建

在主窗口的构造函数里创建界面和三维图表,MainWindow的构造函数代码如下:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   iniGraph3D(); //创建三维图表
   QSplitter   *splitter=new QSplitter(Qt::Horizontal);
   splitter->addWidget(ui->groupBox); //左侧控制面板
   splitter->addWidget(graphContainer);  //右侧图表
   this->setCentralWidget(splitter); 
}

构造函数里首先调用iniGraph3D()创建三维图表及其容器graphContainer,然后创建一个分隔条组件splitter,将可视化设计的控制面板groupBox与动态创建的图表容器graphContainer添加到分隔条里,作为主窗口的中心组件。

这样在运行时就获得图10-1的界面,界面具体自动填充效果,并且可以分割左侧的控制面板和右侧的图表。

iniGraph3D()函数创建图表,其实现代码如下:

void MainWindow::iniGraph3D()
{//创建图表
   graph3D = new Q3DBars();
   graphContainer = QWidget::createWindowContainer(graph3D); 
//创建坐标轴
   QStringList rowLabs; 
   QStringList colLabs;
   rowLabs << "row1" << "row2"<<"row3";
   colLabs << "col1" << "col2" << "col3" << "col4"<<"col5";
   QValue3DAxis *axisV=new QValue3DAxis; //数值坐标轴
   axisV->setTitle("value");
   axisV->setTitleVisible(true);
   QCategory3DAxis *axisRow=new QCategory3DAxis; //行坐标轴
   axisRow->setTitle("row axis");
   axisRow->setLabels(rowLabs);
   axisRow->setTitleVisible(true);
   QCategory3DAxis *axisCol=new QCategory3DAxis; //列坐标轴
   axisCol->setTitle("column axis");
   axisCol->setLabels(colLabs);
   axisCol->setTitleVisible(true);
   graph3D->setValueAxis(axisV);
   graph3D->setRowAxis(axisRow);
   graph3D->setColumnAxis(axisCol);
//创建序列
   series = new QBar3DSeries;
   series->setMesh(QAbstract3DSeries::MeshCylinder); //棒图形状
   series->setItemLabelFormat("(@rowLabel,@colLabel): %.1f"); //标签格式
   graph3D->addSeries(series);
//添加数据
   QBarDataArray *dataSet = new QBarDataArray; //数据数组
   dataSet->reserve(rowLabs.count());
   QBarDataRow *dataRow = new QBarDataRow;
   *dataRow << 1 << 2<< 3<< 4<<5; //第1行数据,有5列
   dataSet->append(dataRow);
   QBarDataRow *dataRow2 = new QBarDataRow;
   *dataRow2 << 5<< 5<< 5<< 5<<5; //第2行数据,有5列
   dataSet->append(dataRow2);
   QBarDataRow *dataRow3 = new QBarDataRow;
   *dataRow3 << 1<< 5<< 9<< 5<<1; //第3行数据,有5列
   dataSet->append(dataRow3);
   series->dataProxy()->resetArray(dataSet);
}

程序首先创建Q3DBars类的实例graph3D,然后创建一个QWidget实例graphContainer作为其容器。创建graphContainer时使用了QWidget的静态函数createWindowContainer(),这样创建的QWidget实例才可以作为QWindow及其子类组件的容器。

三维柱状图的水平面的两个轴采用QCategory3DAxis类型的坐标轴,是文字型标签坐标轴,分别为其设置轴标题和轴标签。垂直方向表示项的数值大小,所以使用QValue3DAxis类型的坐标轴。创建坐标轴后,分别设置为柱状图行坐标轴、列坐标轴和数值坐标轴,即:

graph3D->setValueAxis(axisV);
graph3D->setRowAxis(axisRow);
graph3D->setColumnAxis(axisCol);

与Q3DBars对应使用的序列是QBar3DSeries类,创建序列实例对象series,设置棒图性质和标签格式后添加到图表。

然后创建QBarDataArray数组dataSet,其元素个数等于三维柱状图的行数,也就是dataSet的每个元素是一个行的数据。

一个行的数据是QBarDataRow类型,例如,创建第1行的数据并添加到柱状图的数据数组里的代码如下:

QBarDataRow *dataRow = new QBarDataRow;
*dataRow << 1 << 2<< 3<< 4<<5; //第1行数据,有5列
dataSet->append(dataRow);

实际上,QBarDataRow和QBarDataArray都不是类,而是类型定义,在Qt的源代码中,它们的定义如下:

typedef QVector<QBarDataItem> QBarDataRow;
typedef QList<QBarDataRow *> QBarDataArray;

所以,QBarDataRow是QBarDataItem的向量,QBarDataArray是QBarDataRow的列表。数据的基本元素是QBarDataItem,也就是柱状图中的一个项,QBarDataItem只有value和rotation两个属性,用于存储项的数值和旋转角度。

在图10-5中,柱状图的数据有3行5列,添加数据时,每次添加一行的数据,但是属于一个序列。

设置完数据后,为序列的数据代理设置数据,语句如下:

series->dataProxy()->resetArray(dataSet);

程序里没有为序列先创建QBarDataProxy类型的数据代理,然后再添加到序列里。调用series->dataProxy()使用内部缺省的数据代理,resetArray(dataSet)将清除数据代理原有的数据,并使用dataSet作为数据源。