【发布时间】:2017-07-27 18:17:56
【问题描述】:
我知道这是一个非常受欢迎的问题,但我找到的解决方案都没有对我有用。
背景:我在 VS2015 中有一个 windows 窗体项目,它从文本文件中读取数据并将数据绘制为折线图上的多个系列。 Chart.MouseMove 事件找到离鼠标最近的点并在其周围画一个圆圈。圆圈在 Chart_Paint 事件中绘制
Private Sub crtLogView(sender As Object,e As PaintEventArgs) Handles crtLogView.Paint
Dim whitePen as New Pne(Color.White,2)
e.Graphics.DrawEllipse(whitePen,cir) '//cir is a Public Rectangle
End Sub
在图表上移动鼠标时,随机控件会闪烁,然后又会闪烁,这非常烦人。我在下面发布了 MouseMove 事件代码。
我尝试过的潜在解决方案:
- 打开表单的 DoubleBuffered 属性,它什么都不做
- 使用 Me.Invalidate() 和 Me.Update() 方法,不会移动圆圈
- 使用 Chart.Invalidate() 和 Chart.Update() 方法,虽然有效,但速度很慢
- 将以下代码添加到我的 Form_Load 例程中,这似乎没有任何作用
对此的任何帮助将不胜感激
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.DoubleBuffer, True)
Me.SetStyle(ControlStyles.UserPaint, True)
MouseMove 事件代码:
Private Sub crtLogView_MouseMove(sender As Object, e As MouseEventArgs) Handles crtLogView.MouseMove
'//Show data for closest point to cursor & draw circle around point
Dim hResult As HitTestResult = crtLogView.HitTest(e.X, e.Y)
Dim srsNam As String = ""
Dim mouseY As Single
Dim pntDist As Double = 0
Dim pntX As Single
Dim pntY As Single
Dim mouseX As Single
On Error GoTo ErrTrap
'//Get X-Axis Position as integer
mouseX = Int(hResult.ChartArea.AxisX.PixelPositionToValue(e.X))
'// Set time value
lblTime.Text = String.Format("{0:n2}", hResult.ChartArea.AxisX.PixelPositionToValue(e.X) / 160)
'//Get Y-Axis Position
mouseY = hResult.ChartArea.AxisY.PixelPositionToValue(e.Y)
'//Get distance from mouse to point on Series(0)
pntDist = Math.Abs(crtLogView.Series(0).Points(mouseX).YValues(0) - mouseY)
srsNam = crtLogView.Series(0).Name '//1st series name
'//Find closest series
For i As Integer = 1 To crtLogView.Series.Count - 1
If Math.Abs(crtLogView.Series(i).Points(mouseX).YValues(0) - mouseY) < pntDist Then
pntDist = Math.Abs(crtLogView.Series(i).Points(mouseX).YValues(0) - mouseY)
srsNam = crtLogView.Series(i).Name
End If
Next
'//Set Top/Left values for circle
pntY = crtLogView.ChartAreas(0).AxisY.ValueToPixelPosition(crtLogView.Series(srsNam).Points(mouseX).YValues(0)) - 4
pntX = crtLogView.ChartAreas(0).AxisX.ValueToPixelPosition(Val(mouseX)) - 4
'//Move circle to closest point
cir.Location = New Point(pntX, pntY)
'//Refresh the form to move the circle
'//This works, but takes 2+ seconds to take effect
'crtLogView.Invalidate()
'crtLogView.Update()
'//This does not work
'Me.Invalidate()
'Me.Update()
'//This works, but randomly makes other controls flash/flicker
Me.Refresh()
ErrTrap:
End Sub
【问题讨论】:
-
我不知道你为什么要使用 mousemove 事件——它会一直触发。您是否尝试过在鼠标移动时重置计时器,然后在停止时绘制圆圈?
-
为此使用图表注释或数据点标签可能会更好,而不是执行自定义绘制。如果你需要一个例子,我可以提供一个。
-
@peterG 感谢您的建议!我没有尝试过计时器,但现在有,它只会使闪烁的频率稍微降低
-
@TnTinMn 一个例子将不胜感激!我尝试将图表注释用于其他内容,但无法正确显示它们。我开始尝试 DataPoint Label 方法,但无法清除标签以移动到下一个点,所以我最终得到了鼠标接近的所有点的标签。
-
好吧,我的意思是:将计时器设置为一些小的经验选择值。每次 mousemove 事件触发时,重新启动计时器。当计时器超时时触发画圆,也就是说,我们正在尝试生成 mousemovestopped 事件。因此,鼠标移动时不会绘制任何内容,但只有在它停止时才会绘制。
标签: vb.net winforms charts graphics