如果没记错的话,好像是第一次在用趋势图显示数据的时候,就遇到过这个问题,当时是在一个趋势图中显示一个月中每天的数据趋势变化,结果就是根本在一张图中显示不下,X轴的文字标注都重叠到一起,当时用的是PB,里面的图形显示功能非常强大,后来好像是将文字直立显示的,避免了标注的重叠。
最近同时好像在搞趋势图,又想起这个问题,就试着在里面加个slider实现拖动以便可以显示“被多出”的部分。老规矩,先看图。
嘿嘿,其实也没用到什么,纯GDI+,用到的也不外乎就是双缓存和坐标变换。主要处理的事件就是MouseDown和MouseMove,重绘Paint。在MouseDown中变化X轴的值和Value值(这里也有变换坐标),在MouseMove中变换坐标,Paint中绘制轴、趋势图、滑块。
下面看看完整的代码:
代码
///
<summary>
/// X轴和Value值重加载
/// </summary>
private void lbchart_MouseDown( object sender, MouseEventArgs e)
{
// 是否点中滑块
IsClick = IsClickSlider( new Point(e.X, e.Y));
// 左键有效
if (e.Button == MouseButtons.Left)
{
double disvalue = 0 ; // 位移
if (curPoint.X != e.X || curPoint.Y != e.Y)
{
curPoint.X = e.X;
curPoint.Y = e.Y;
Capture = true ;
// 是否需要移动
if (IsClick)
{
IsNeedMove = true ;
}
// 位移差
disvalue = curPoint.X - oldPoint.X;
}
else
{
IsNeedMove = false ;
// 位移差
disvalue = dx;
}
// 重新复制PartValue中的值
// ****x轴移动的位移
int xd = ( int )Math.Round(disvalue / xdvalue);
curArrPos = curArrPos + xd;
if (curArrPos < 0 )
{
curArrPos = 0 ;
}
if (curArrPos > 6 )
{
curArrPos = 6 ;
}
for ( int i = curArrPos; i < curArrPos + 7 ; i ++ )
{
xPartValue[i - curArrPos] = xValue[i];
partValue[i - curArrPos] = value[i];
}
}
if (e.Button == MouseButtons.Right)
{
Capture = false ;
}
dx = 0 ;
this .lbchart.Invalidate();
}
/// <summary>
/// 鼠标移动
/// </summary>
private void lbchart_MouseMove( object sender, MouseEventArgs e)
{
Graphics g2 = CreateGraphics();
if (IsNeedMove)
{
dx = dx + (e.X - oldPoint.X);
curPoint = new Point(e.X, e.Y);
}
this .lbchart.Invalidate();
}
/// X轴和Value值重加载
/// </summary>
private void lbchart_MouseDown( object sender, MouseEventArgs e)
{
// 是否点中滑块
IsClick = IsClickSlider( new Point(e.X, e.Y));
// 左键有效
if (e.Button == MouseButtons.Left)
{
double disvalue = 0 ; // 位移
if (curPoint.X != e.X || curPoint.Y != e.Y)
{
curPoint.X = e.X;
curPoint.Y = e.Y;
Capture = true ;
// 是否需要移动
if (IsClick)
{
IsNeedMove = true ;
}
// 位移差
disvalue = curPoint.X - oldPoint.X;
}
else
{
IsNeedMove = false ;
// 位移差
disvalue = dx;
}
// 重新复制PartValue中的值
// ****x轴移动的位移
int xd = ( int )Math.Round(disvalue / xdvalue);
curArrPos = curArrPos + xd;
if (curArrPos < 0 )
{
curArrPos = 0 ;
}
if (curArrPos > 6 )
{
curArrPos = 6 ;
}
for ( int i = curArrPos; i < curArrPos + 7 ; i ++ )
{
xPartValue[i - curArrPos] = xValue[i];
partValue[i - curArrPos] = value[i];
}
}
if (e.Button == MouseButtons.Right)
{
Capture = false ;
}
dx = 0 ;
this .lbchart.Invalidate();
}
/// <summary>
/// 鼠标移动
/// </summary>
private void lbchart_MouseMove( object sender, MouseEventArgs e)
{
Graphics g2 = CreateGraphics();
if (IsNeedMove)
{
dx = dx + (e.X - oldPoint.X);
curPoint = new Point(e.X, e.Y);
}
this .lbchart.Invalidate();
}
上面是两个主要的鼠标事件,下面看看绘制代码:
代码
#region
重绘
private void lbchart_Paint( object sender, PaintEventArgs e)
{
// 初始化值
g0 = e.Graphics;
bitmap = new Bitmap(lbchart.Width, lbchart.Height);
g1 = Graphics.FromImage(bitmap);
g1.Clear( this .lbchart.BackColor);
g1.SmoothingMode = SmoothingMode.AntiAlias;
#region 绘制
// 轴
DrawAxes();
// 趋势图
DrawChart();
// 滑块
DrawSlider();
#endregion
// 绘制到lb上
g0.DrawImage(bitmap, 0 , 0 );
}
/// <summary>
/// 绘制轴
/// </summary>
private void DrawAxes()
{
Brush axesbrush = new SolidBrush(Color.Black);
Font axesfont = new Font( " 宋体 " , 15 , FontStyle.Bold);
Font valuefont = new Font( " 宋体 " , 10 , FontStyle.Regular);
// 箭头
AdjustableArrowCap cap = new AdjustableArrowCap( 3 , 3 );
cap.WidthScale = 3 ;
cap.BaseCap = LineCap.Square;
cap.Height = 3 ;
axesPen.CustomStartCap = cap;
// ****Y轴
g1.DrawLine(axesPen, lbPosX + 10 , lbPosY + 10 , lbPosX + 10 , lbHeight - 30 );
g1.DrawString( " Y " , axesfont, axesbrush, lbPosX + 15 , lbPosY + 10 );
// *****Y轴差值
ydvalue = ((lbHeight - 15 ) - (lbPosY + 10 )) / (yValue.Length + 1 );
for ( int i = 0 ; i < yValue.Length; i ++ )
{
float y = ( float )(lbHeight - 15 - (i + 1 ) * ydvalue);
g1.DrawString(yValue[i].ToString(), valuefont, axesbrush, lbPosX + 12 , y);
g1.DrawLine(valuePen, lbPosX + 10 , y, lbPosX + 15 , y);
}
// ****X轴
g1.DrawLine(axesPen, lbWidth - 5 , lbHeight - 30 , lbPosX + 10 , lbHeight - 30 );
g1.DrawString( " X " , axesfont, axesbrush, lbWidth - 15 , lbHeight - 55 );
// ******X轴差值
xdvalue = (lbWidth - 5 - (lbPosX + 10 )) / (partValue.Length - 1 );
for ( int i = 0 ; i < xPartValue.Length; i ++ )
{
float x = ( float )(lbPosX + 10 + (i) * xdvalue);
if (Convert.ToDouble(xPartValue[i].ToString()) >= 10 )
{
g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x - 12 , lbHeight - 28 );
}
else
{
g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x - 5 , lbHeight - 28 );
}
g1.DrawLine(valuePen, x, lbHeight - 30 , x, lbHeight - 35 );
}
}
/// <summary>
/// 绘制趋势图
/// </summary>
private void DrawChart()
{
// ****绘制曲线图
double dvalue = ydvalue / 5.0 ;
for ( int i = 0 ; i < partValue.Length - 1 ; i ++ )
{
double startX = lbPosX + 10 + (i) * xdvalue;
double endX = startX + xdvalue;
double startY = Convert.ToDouble(partValue[i].ToString()) * dvalue;
double endY = Convert.ToDouble(partValue[i + 1 ].ToString()) * dvalue;
g1.DrawEllipse( new Pen(Color.Red), ( float )(startX - 3 ), ( float )(startY - 3 ), 6 , 6 );
g1.DrawLine(valuePen, ( float )endX, ( float )endY, ( float )startX, ( float )startY);
}
}
/// <summary>
/// 绘制滑块
/// </summary>
private void DrawSlider()
{
// 绘制滑块
if (curPoint.X != 0 && curPoint.Y != 0 )
{
oldPoint = curPoint;
g1.DrawLine(sliderPen, lbPosX + curPoint.X, lbPosY, lbPosX + curPoint.X, lbPosY + lbHeight);
}
else
{
g1.DrawLine(sliderPen, lbWidth / 2 , lbPosY, lbWidth / 2 , lbPosY + lbHeight);
}
}
#endregion
private void lbchart_Paint( object sender, PaintEventArgs e)
{
// 初始化值
g0 = e.Graphics;
bitmap = new Bitmap(lbchart.Width, lbchart.Height);
g1 = Graphics.FromImage(bitmap);
g1.Clear( this .lbchart.BackColor);
g1.SmoothingMode = SmoothingMode.AntiAlias;
#region 绘制
// 轴
DrawAxes();
// 趋势图
DrawChart();
// 滑块
DrawSlider();
#endregion
// 绘制到lb上
g0.DrawImage(bitmap, 0 , 0 );
}
/// <summary>
/// 绘制轴
/// </summary>
private void DrawAxes()
{
Brush axesbrush = new SolidBrush(Color.Black);
Font axesfont = new Font( " 宋体 " , 15 , FontStyle.Bold);
Font valuefont = new Font( " 宋体 " , 10 , FontStyle.Regular);
// 箭头
AdjustableArrowCap cap = new AdjustableArrowCap( 3 , 3 );
cap.WidthScale = 3 ;
cap.BaseCap = LineCap.Square;
cap.Height = 3 ;
axesPen.CustomStartCap = cap;
// ****Y轴
g1.DrawLine(axesPen, lbPosX + 10 , lbPosY + 10 , lbPosX + 10 , lbHeight - 30 );
g1.DrawString( " Y " , axesfont, axesbrush, lbPosX + 15 , lbPosY + 10 );
// *****Y轴差值
ydvalue = ((lbHeight - 15 ) - (lbPosY + 10 )) / (yValue.Length + 1 );
for ( int i = 0 ; i < yValue.Length; i ++ )
{
float y = ( float )(lbHeight - 15 - (i + 1 ) * ydvalue);
g1.DrawString(yValue[i].ToString(), valuefont, axesbrush, lbPosX + 12 , y);
g1.DrawLine(valuePen, lbPosX + 10 , y, lbPosX + 15 , y);
}
// ****X轴
g1.DrawLine(axesPen, lbWidth - 5 , lbHeight - 30 , lbPosX + 10 , lbHeight - 30 );
g1.DrawString( " X " , axesfont, axesbrush, lbWidth - 15 , lbHeight - 55 );
// ******X轴差值
xdvalue = (lbWidth - 5 - (lbPosX + 10 )) / (partValue.Length - 1 );
for ( int i = 0 ; i < xPartValue.Length; i ++ )
{
float x = ( float )(lbPosX + 10 + (i) * xdvalue);
if (Convert.ToDouble(xPartValue[i].ToString()) >= 10 )
{
g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x - 12 , lbHeight - 28 );
}
else
{
g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x - 5 , lbHeight - 28 );
}
g1.DrawLine(valuePen, x, lbHeight - 30 , x, lbHeight - 35 );
}
}
/// <summary>
/// 绘制趋势图
/// </summary>
private void DrawChart()
{
// ****绘制曲线图
double dvalue = ydvalue / 5.0 ;
for ( int i = 0 ; i < partValue.Length - 1 ; i ++ )
{
double startX = lbPosX + 10 + (i) * xdvalue;
double endX = startX + xdvalue;
double startY = Convert.ToDouble(partValue[i].ToString()) * dvalue;
double endY = Convert.ToDouble(partValue[i + 1 ].ToString()) * dvalue;
g1.DrawEllipse( new Pen(Color.Red), ( float )(startX - 3 ), ( float )(startY - 3 ), 6 , 6 );
g1.DrawLine(valuePen, ( float )endX, ( float )endY, ( float )startX, ( float )startY);
}
}
/// <summary>
/// 绘制滑块
/// </summary>
private void DrawSlider()
{
// 绘制滑块
if (curPoint.X != 0 && curPoint.Y != 0 )
{
oldPoint = curPoint;
g1.DrawLine(sliderPen, lbPosX + curPoint.X, lbPosY, lbPosX + curPoint.X, lbPosY + lbHeight);
}
else
{
g1.DrawLine(sliderPen, lbWidth / 2 , lbPosY, lbWidth / 2 , lbPosY + lbHeight);
}
}
#endregion