最开始使用 qchart 实现项目要求 qchart不知道怎么实现XY轴上面的箭头 囧
后面 轴上面显示的单位 移动不到 箭头附近 而且数据点需要散点类,也需要连线,数据list也有标题,数据多 一点管理太麻烦,数据拖动弄的一团糟。
整了几天 还有一些细节还是不知道怎么设置,查来查去 都是一些基础的东西
还是太菜了,学无止境!
后面等不起 用qpainter 实现 需要的功能 类似 qchart
这是demo
主要代码:
数据list使用结构体
struct paint_point_struct { bool is_paint_data_title; // 是否绘制数据标题 QString title; // 数据标题 QList<QPointF>data_list; // 绘图数据 bool is_draw_line; // 是否将数据点用线连接 Qt::PenStyle ps; // 线类型 bool is_draw_point; // 数据点是否绘制为圆点 int point_marker_size; // 圆点大小 paint_point_struct() { is_paint_data_title = true; // 默认绘制数据标题 title.clear(); is_draw_line = true; // 默认数据点用线连接 data_list.clear(); ps = Qt::SolidLine; // 默认是实线 //ps = Qt::DotLine; // 默认是虚线 is_draw_point = true; // 默认数据点绘制为圆点 point_marker_size = 5; // 圆点大小默认为5 } };/* 绘制标题 */ void mychart::paint_title(QPainter *painter) { if(title_string.isEmpty()) { title_height = 0; return; } ResetDefaultCoordinate(painter); painter->setFont(*title_font); int width = this->width() / 2; // int height = this->height(); QFontMetrics fm(*title_font); int axis_x_string_width = fm.width(title_string); int axis_x_string_heigh = fm.height(); // X轴字符的高度 int rect_y = 0 + 5; title_height = rect_y + axis_x_string_heigh + 5; if(coordinate_dir) { rect_y = 0; title_height = 0; } QRectF rect(width - axis_x_string_width / 2, rect_y, axis_x_string_width, axis_x_string_heigh); painter->drawText(rect,title_string); title_height = rect_y + axis_x_string_heigh + 5; }/* 绘制数据点 */ void mychart::paint_points(QPainter *painter) // 绘制数据点 { for(int i = 0;i < paint_point_list.length();i++) { if(coordinate_dir) SetMathCoordinate(painter); else ResetDefaultCoordinate(painter); // 左上角 QPointF point_end; for(int j = 0;j < paint_point_list.at(i).data_list.length();j++) { QPointF point_at_list = paint_point_list.at(i).data_list.at(j); QPointF point; point.setX(m_ptStartPos.x() + (point_at_list.x() - axis_x_range.x()) * m_axisWidth / (axis_x_range.y() - axis_x_range.x())); point.setY(m_ptStartPos.y() + (point_at_list.y() - axis_y_range.x()) * m_axisHeight / (axis_y_range.y() - axis_y_range.x())); if(paint_point_list.at(i).is_draw_point) painter->drawEllipse(point,paint_point_list.at(i).point_marker_size,paint_point_list.at(i).point_marker_size); if(paint_point_list.at(i).is_draw_line) // 数据点用线连接 { if(j != 0) { QPen pen; pen.setStyle(paint_point_list.at(i).ps); painter->setPen(pen); painter->drawLine(point, point_end);// 绘制数据连接线(折线) } point_end = point; } } /* 绘制数据标题 */ if(paint_point_list.at(i).is_paint_data_title && !paint_point_list.at(i).title.isEmpty()) { ResetDefaultCoordinate(painter); // 左上角 QFont font("SimSun", 16, 50); painter->setFont(font); /* 确定字符的长宽 */ QFontMetrics fm(font); int axis_x_string_width = fm.width(paint_point_list.at(i).title); int axis_x_string_heigh = fm.height(); // X轴字符的高度 int rect_x = point_end.x() + paint_point_list.at(i).point_marker_size + 10; int rect_y = (point_end.y() - axis_x_string_heigh / 2); if(coordinate_dir) rect_y = this->height() - rect_y - axis_x_string_heigh; QRectF rect(rect_x, rect_y, axis_x_string_width, axis_x_string_heigh); painter->drawText(rect,paint_point_list.at(i).title); } } }坐标轴刻度可能是其他乱七八糟的字符
/* 绘制刻度文本 */ void mychart::paint_coordinate_scale_text(QPainter *painter) { ResetDefaultCoordinate(painter); painter->setFont(*text_font); /* 确定字符的长宽 */ QFontMetrics fm(*text_font); int axis_x_string_width = fm.width("0"); int axis_x_string_heigh = fm.height(); // X轴字符的高度 for(int i = 0;i < axis_y_count;i++) { /* 确定Y轴上的字符最大宽度 */ QString y_string = (y_scale_string_list.isEmpty())? QString::number((axis_y_range.y() - axis_y_range.x()) / (axis_y_count - 1) * i,'f',2): y_scale_string_list.at(i); int string_width = fm.width(y_string); axis_x_string_width = (string_width > axis_x_string_width)?string_width:axis_x_string_width; } QPoint axisStartPoint; // 刻度线坐标 int string_scale_base = 0; // 第一个刻度文本结束点坐标(根据刻度范围动态显示刻度文本,防止文本全部叠在一起) /* 画X刻度文本标识 */ int count = (!x_scale_list.isEmpty())?x_scale_list.length():axis_x_count; for(int i = count - 1;i >= 0;i--) // 从最后一个刻度文本开始,优先绘制最大刻度文本 { qreal x = m_ptStartPos.x() + m_axisWidth / (count - 1) * i; if(!x_scale_list.isEmpty()) x = m_ptStartPos.x() + (x_scale_list.at(i) - x_scale_list.at(0)) * m_axisWidth / (x_scale_list.last() - x_scale_list.at(0)); axisStartPoint.setX(x); axisStartPoint.setY(m_ptStartPos.y()); QString scale_str = (x_scale_string_list.isEmpty())? QString::number((axis_x_range.y() - axis_x_range.x()) / (count - 1) * i,'f',0): x_scale_string_list.at(i); axis_x_string_width = fm.width(scale_str); axis_x_string_heigh = fm.height(); // X轴字符的高度 int rect_y = axisStartPoint.y() - scale_value - axis_x_string_heigh; if(coordinate_dir) rect_y = this->height() - rect_y - axis_x_string_heigh; QRectF rect(axisStartPoint.x() - axis_x_string_width / 2, rect_y, axis_x_string_width, axis_x_string_heigh); if(scale_str.isEmpty())continue; if(i == count - 1) // 从最后一个刻度文本开始 { string_scale_base = axisStartPoint.x() - axis_x_string_width / 2; // 计算文本起点X坐标 } if((axisStartPoint.x() + axis_x_string_width / 2 > string_scale_base) && (i < count - 1)) { continue; // 文本重叠 } else { string_scale_base = axisStartPoint.x() - axis_x_string_width / 2; } painter->drawText(rect,scale_str); } /* 画Y刻度文本标识 */ count = (!y_scale_string_list.isEmpty())?y_scale_string_list.length():axis_y_count; for(int i = count - 1;i >= 0;i--) { qreal y = m_ptStartPos.y() + m_axisHeight / (count - 1) * i; if(!y_scale_list.isEmpty()) y = m_ptStartPos.y() + (y_scale_list.at(i) - y_scale_list.at(0)) * m_axisHeight / (y_scale_list.last() - y_scale_list.at(0)); axisStartPoint.setX(m_ptStartPos.x()); axisStartPoint.setY(y); QString scale_str = (y_scale_string_list.isEmpty())? QString::number((axis_y_range.y() - axis_y_range.x()) / (count - 1) * i,'f',2): y_scale_string_list.at(i); axis_x_string_width = fm.width(scale_str); axis_x_string_heigh = fm.height(); // X轴字符的高度 int rect_y = axisStartPoint.y() - axis_x_string_heigh / 2; if(coordinate_dir) rect_y = this->height() - rect_y - axis_x_string_heigh; QRectF rect(axisStartPoint.x() - scale_value - axis_x_string_width, rect_y, axis_x_string_width, axis_x_string_heigh); if(scale_str.isEmpty())continue; if(i == count - 1) // 从最后一个刻度文本开始,优先绘制最大刻度文本 { string_scale_base = axisStartPoint.y() - axis_x_string_heigh / 2; // 计算文本起点X坐标 } if((axisStartPoint.y() + axis_x_string_heigh / 2 > string_scale_base) && (i < count - 1)) { continue; // 文本重叠 } else { string_scale_base = axisStartPoint.y() - axis_x_string_heigh / 2; } painter->drawText(rect,scale_str); } /* 设置XY轴单位字符 */ if(!x_unit_string.isEmpty()) { axis_x_string_width = fm.width(x_unit_string); axis_x_string_heigh = fm.height(); // X轴字符的高度 int rect_y = m_ptStartPos.y() + m_ptStartPos.x() / 10; if(coordinate_dir) rect_y = this->height() - rect_y - axis_x_string_heigh; QRectF rect(m_ptStartPos.x() + m_axisWidth + m_ptStartPos.x() / 2 - axis_x_string_width / 2, rect_y, axis_x_string_width, axis_x_string_heigh); painter->drawText(rect,x_unit_string); } if(!y_unit_string.isEmpty()) { axis_x_string_width = fm.width(y_unit_string); axis_x_string_heigh = fm.height(); // Y轴字符的高度 int rect_y = (m_ptStartPos.y() + m_axisHeight + m_ptStartPos.y() - axis_x_string_heigh); if(coordinate_dir) rect_y = this->height() - rect_y - axis_x_string_heigh; QRectF rect(m_ptStartPos.x() + m_axisHeight / 75 * 2, rect_y, axis_x_string_width, axis_x_string_heigh); painter->drawText(rect,y_unit_string); } }https://download.csdn.net/download/zsj_rainsy/87032911