问题描述:
如何用VB做一个程序可以用鼠标画曲线,
解析:
在工控制软件中,实时曲线的绘制用途非常的广泛,它可以很直观的显示腊腔者出监控数据的变化值和变化趋势。在VB中实现曲线的绘制有很多种方法,本文介绍一种非常简单的方法来实现实时曲轮薯线的绘制。
在VB中实现实时曲线的绘制,要利用VB的PictureBox(图像)控件,和画线函数line(x1,y1)-(x2,y2)。PictureBox控件,可以作为一个“容器”,在它的里面可以包含很多的对象。也可以执行很多VB的内部函数。
要实现实时曲线的绘制,肯定要有外部实时数据的输入,这里假设是有一个数据从计算机的串口输入 定义该数据变量为DataFromCom。实时曲线反映的就是该数据。
打开VB6.0中文版,新建一个项目和窗体,修改窗体的属性,将“Heigh”修改为:8000,“Width”修改为在窗体中放如一个PictureBox控件。然后重新定义PictureBox控件的一些基本属性,在VB中选中PictureBox控件,直接在它的属性框中,修改一些属性参数。“名称”改为Pic。 “AutoRedraw”改为:True。“BackColor”改为:&H***********&(墨绿色背景颜色)。”Heigh”改为:5000。“Width”改为:8000。如图1所示:
然后要重新定义PictureBox控件的坐标系。图像框的默认坐标系,是从左上角开始的,不符合我们的画线要求。修改坐标系的目的是让曲线从图像框的左边正中间,开始画线。修改图像框的坐标系,这里定义一个过程PicScale(),代码如下:
Private Sub PicScale(picX As PictureBox)
picX.Scale (0, PicX.ScaleHeight)-(picX.ScaleWidth, -PicX.ScaleHeight)
End Sub
一般的实时曲线显示的时候在屏幕的正中间有一条基准线,这圆毁里也要画出这条基准线,用一个过程PicMidleLine()来实现,代码如下:
Private Sub PicMidleLine( picX As PictureBox)
picX.Line (0, 0)-(picX.ScaleWidth, 0), vbGreen '画出中线
End Sub
要画一条实时曲线,坐标轴的设定很重要,在这里把X轴设定为时间轴,Y轴设定为数据轴。对应X轴我们定义一个时间变量TimeCount,TimeCount会随着时间逐渐递增,每次递增,对应着一个从串口读过来的数据DataFromCom,这样图像框中的(x,y)坐标点实际上就对应着(TimeCount,DataFromCom)如果只是当TimeCount发生变化时就在图像框上画一个点,就只需调用VB中的画像素的函数point(x,y),这里x,y为所画的点的坐标。单这样画出来的是一个个不连续的点。我们想要的是实时的连续的曲线,所以要调用VB中的画线的函数line(x1,y1)-(x2,y2),这里(x1,y1)(x2,y2)为所要画的线的起点和终点的坐标。只要把上次串口读过来的数据(这里把它定义为变量DataFromComLast)和现在串口读过来的数据(DataFromCom)和TimeCount相对应,调用line(x1,y1)-(x2,y2)函数就可以在图像框中画出实时的曲线了。把它写成一个过程如下面的代码:
Private Sub DrawRealLine(picX As PictureBox, TimeCountX As Integer, DataFromComX As Integer, DataFromComLastX As Integer)
If TimeCountX - 1 >0 Then
picX.Line (TimeCountX - 1, DataFromComLastX)-(TimeCountX, DataFromComX), vbWhite
End If
End Sub
有了三个过程就可以在图像框中画出一条实时的曲线了。
DrawRealLine()过程中的picX.Line (TimeCountX - 1, DataFromComLastX)-(TimeCountX, DataFromComX), vbWhite所画线的起始点和结束点都是以像素为单位的,这样以来如果不改变的话,画出来的线将是一个屏幕上像素相连的很密的曲线,通过调整line(x1,y1)-(x2,y2)
中的x的值,就可以画出分布密度不一样的曲线,这里为了在屏幕上能够看到不是很密的曲线我们把x乘以一个系数10,修改为:
picX.Line ((TimeCountX - 1) * 10, DataFromComLastX)-(TimeCountX * 10, DataFromComX), vbWhite
这比较容易在屏幕上看到稀疏的曲线。
由于是仅仅讲解如何画出实时的曲线,读者的计算机上未必有和串口相连的设备,这里用一个定时器控件来模拟从串口读过来的数据。在窗体上放入一个Timer控件,修改Timer控件的属性为:“Enable”该为True,“Interval”改为300。双击Timer控件在它的过程中,添加代码后如下:
Private Sub Timer1_Timer()
DataFromComLast = DataFromCom
Randomize
DataFromCom = 3000 * Rnd
TimeCount = TimeCount + 1
DrawRealLine Pic, TimeCount, DataFromCom, DataFromComLast
End Sub
这样在运行后就可以看到我们想要的实时曲线了,如下图:
图 2
下面是完整的代码:
Option Explicit
Dim DataFromCom As Integer '从串口读过来的实时值
Dim DataFromComLast As Integer '上次的串口值
Dim TimeCount As Integer
Private Sub Form_Load()
PicScale Pic '调整图像框的坐标系
PicMidleLine Pic '在图像框中画一条中线
End Sub
Private Sub PicScale(picX As PictureBox) '调整图像框的坐标系
picX.Scale (0, picX.ScaleHeight)-(picX.ScaleWidth, -picX.ScaleHeight)
End Sub
Private Sub PicMidleLine(picX As PictureBox) '在图像框中画一条中线
picX.Line (0, 0)-(picX.ScaleWidth, 0), vbGreen '画出中线
End Sub
Private Sub DrawRealLine(picX As PictureBox, TimeCountX As Integer, DataFromComX As Integer, DataFromComLastX As Integer)
If TimeCountX - 1 >0 Then
picX.Line ((TimeCountX - 1) * 10, DataFromComLastX)-(TimeCountX * 10, DataFromComX), vbWhite
End If
End Sub
Private Sub Timer1_Timer()
DataFromComLast = DataFromCom
Randomize
DataFromCom = 3000 * Rnd
TimeCount = TimeCount + 1
DrawRealLine Pic, TimeCount, DataFromCom, DataFromComLast '画出实时的曲线
End Sub
在VB中绘制实时曲线是比较难的,一般要应用第三方控件或是Windows API函数来完成,但是如果你对实时曲线的要求不是很高,只要能表示出当前的一般情况的话,我们可以直接应用VB提供给我们的空间来完成.
原则上讲,直接在Form里绘制曲线都是可以的,MSDN上面很多例程就是直接在Form里面绘制图形的,Form作为绘制图形的容器,不过一般应用中Form中不可避免的会有很多其他控件,所以我们选择PictureBox作为绘制曲线的容器.
实时曲线的绘制一般借助于Timer控件来完成,使用Timer控件,定期将串口或是其他仪器中监测到的数据送往PictureBox1,而曲线的绘制一般画成折线图,采用PictureBox1的Line方法绘制.具体实现如下:
1.选择需要显示的窗体Picture1,加入图片框Picture1,根据实际需要设置图片的大小并移到合适的位置,并在图片的外面画好量程----时间坐标系;然后加上Timer控件以及两个CommandButton,界面就基本设置好了.
2.建立坐标系,根据Picture1的大小和高度设置画出坐标系的X轴和Y轴:
Picture1 .ScaleMode = 1 ‘以VB的基本单位作为建立坐标轴以及绘制图形的单位
Picture1.Refresh
Picture1.CurrentX = Picture1.ScaleLeft +100
Picture1.CurrentY = Picture1.ScaleTop
Picture1.Print Picture1.ScaleHeight - 100
Picture1.Line(Picture1.ScaleLeft+100,Picture1.ScaleTop+100)-(Picture1.ScaleLeft+100, Picture1.ScaleHeight - 100)
Picture1.CurrentX = Picture1.ScaleLeft +100
Picture1.CurrentY = Picture1.ScaleHeight
Picture1.Print “(0,0)”
Picture1.Line (Picture1.ScaleLeft + 100, Picture1.ScaleHeight - 100)-(Picture1.ScaleWidth - 100, Picture1.ScaleHeight - 100)
Picture1.CurrentX = Picture1.ScaleWidth
Picture1.CurrentY = Picture1.ScaleHeight
Picture1.Print Picture1.ScaleWidth-100
Picture1.AutoRedraw = True ‘必要时,用存储在内存中的图象进行重绘
3.绘制曲线并保存,我们这里以正弦曲线作为绘制曲线的数据来源,具体应用是可以采用由串口或其他仪器采集得到的数据.首先我们绘制一条中线,然后在Timer控件的Time事件中绘制曲线:
Picture1.Line (Picture1.ScaleLeft, CInt(Picture1.ScaleHeight / 2))-(Picture1.ScaleWidth, CInt(Picture1.ScaleHeight / 2)) ‘绘制中线
Private Sub Timer1_Timer()
Dim y1 As Integer
y1 = CInt(Sin((x - Picture1.Left) / 20 / 180 * pi) * Picture1.ScaleHeight / 2)
y1 = CInt((Picture1.ScaleHeight + 1000) / 2) - y1
Picture1.Line (x, y)-(x + 20, y1)
x = x + 20
y = y1
If x >= Picture1.ScaleWidth Then
SavePicture Picture1.Image, "c:\sin.bmp" ‘保存图画,
Dim X(1 To 11) As Long: Dim Y(1 To 11) As LongPrivate Sub Command1_Click()
Dim X1 As Long: Dim Y1 As Long
Dim X2 As Long: Dim Y2 As Long
X1 = 0
Y1 = 2000
For i = 1 To 11
X2 = (3000 / 150) * X(i)
Y2 = 2000 - (2000 / 100) * Y(i)
Picture1.Line (X1, Y1)-(X2, Y2), vbRed
X1 = X2: Y1 = Y2
Next
End Sub
Private Sub Form_Load()
Picture1.Width = 3000
Picture1.Height = 2000
For i = 1 To 10
X(i) = CInt(150 * Rnd)
Y(i) = CInt(100 * Rnd)
Debug.Print "x=" &X(i) &" " &"y=" &Y(i)
Next
Dim minX As Long: Dim minY As Long
For i = 1 To 9
For j = i + 1 To 10
If X(i) >X(j) Then
minX = X(i): X(i) = X(j): X(j) = minX
End If
帮你写好了,可以运行,符合要求。如果你还有什么不明白的弯歼让或者想要工程文件改陪留个QQ吧。Dim x(1 To 40) As String, y(1 To 40) As String, Data(1 To 2) As String
Private Sub Command1_Click()
Dim i%
Picture1.DrawWidth = 5 '画点的大小
Open App.Path + "\data.txt" For Input As #1 '打开文件
Do While Not EOF(1)
i = i + 1
Line Input #1, Data(i) '按行读取数据,埋局共两行
Loop
Close 1
'把读到的第一行字符串中的有效数据存入到数组x里
For i = 1 To 40
x(i) = Mid(Data(1), 4 * i - 3, 3) '读取三个字节小数数据(其中逗号和小数点都算一个字节)
Next
'把读到的第二行字符串中的有效数据存入到数组y里
For i = 1 To 40
y(i) = Mid(Data(2), 4 * i - 3, 3)
Next
'逐一画点
For i = 1 To 40
Picture1.PSet (Val(x(i)), Val(y(i)))
Next
End Sub
Private Sub Form_Load()
Picture1.Scale (0, 12)-(10, 0) '设置Picture1的坐标左上角为(0, 12),右下角为(10, 0),由此可知左下角是(0,0)原点
End Sub
请参考~~~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)