在 VB.NET 上绘制采样图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25994162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Plotting sampling graph on VB.NET
提问by user50949
I am collecting data from an Arduino and transmit on Visual Basic through the serial port. Now I wanted to plot a graph with time vs electrical energy (unit kWh) - time along the x-axis and electrical energy along the y-axis. Usually I am getting data of the current from Arduino.
我正在从 Arduino 收集数据并通过串行端口在 Visual Basic 上传输。现在我想用时间与电能(单位kWh)绘制图表- 沿 x 轴的时间和沿 y 轴的电能。通常我从 Arduino 获取电流数据。
Now I wanted to learn how to start plotting the graph. I need a simple example explaining plotting a graph for sample. I tried some example code. It seems they are not working.
现在我想学习如何开始绘制图表。我需要一个简单的例子来解释为样本绘制图表。我尝试了一些示例代码。似乎他们没有工作。
How do I plot a graph time vs current read from serial? Once Visual Basic starts running, it should save data w.r.t system time and date.
如何绘制图形时间与从串行读取的电流?一旦 Visual Basic 开始运行,它应该保存系统时间和日期的数据。
Current code
当前代码
Imports System
Imports System.IO.Ports
Imports System.ComponentModel
Imports System.Threading
Imports System.Drawing
Public Class Form1
Dim myPort As Array
Dim Distance As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
myPort = IO.Ports.SerialPort.GetPortNames()
PortComboBox.Items.AddRange(myPort)
BaudComboBox.Items.Add(9600)
BaudComboBox.Items.Add(19200)
BaudComboBox.Items.Add(38400)
BaudComboBox.Items.Add(57600)
BaudComboBox.Items.Add(115200)
ConnectButton.Enabled = True
DisconnectButton.Enabled = False
End Sub
Private Sub ConnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectButton.Click
SerialPort1.PortName = PortComboBox.Text
SerialPort1.BaudRate = BaudComboBox.Text
SerialPort1.Open()
Timer1.Start()
'lblMessage.Text = PortComboBox.Text & " Connected."
ConnectButton.Enabled = False
DisconnectButton.Enabled = True
End Sub
Private Sub DisconnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DisconnectButton.Click
SerialPort1.Close()
DisconnectButton.Enabled = False
ConnectButton.Enabled = True
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Try
SerialPort1.Write("c")
System.Threading.Thread.Sleep(250)
Dim k As Double
Dim distance As String = SerialPort1.ReadLine()
k = CDbl(distance)
ListBoxSensor.Text = k
Catch ex As Exception
End Try
End Sub
Private Sub Relay_ON_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Relay_ON.Click
SerialPort1.Write("1")
End Sub
Private Sub Relay_Off_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Relay_Off.Click
SerialPort1.Write("0")
End Sub
End Class
回答by γηρ?σκω δ' αε? πολλ? διδασκ?με
Add a picturebox, a timer a button and a textbox:
Add a picturebox, a timer a button and a textbox:
PictureBox1 size = 768, 279
timer interval to 500
PictureBox1 size = 768, 279
定时器间隔到 500
Private img As Bitmap
Private imgClone As Bitmap
Private widthInterval As Integer
'the distance from the left side of picturebox where x axis starts
Private leftPad As Integer = 50
'the distance from the down side of picturebox where x axis is
Private downPad As Integer = 30
'the distance from the up side of picturebox where y axis ends
Private upPad As Integer = 50
'the distance from the right side of picturebox where x axis ends
Private rightPad As Integer = 80
Private rn As New Random
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
drawBack()
Timer1.Enabled = True
End Sub
Private Sub drawBack()
Static count As Boolean = False
Dim g As Graphics
'number of values in x axis e.g 1, 2, 3, ... representing time
Dim numX As Integer = 23
'number of values in y axis representing KW/h
Dim numY As Integer = 5
Dim stringFormat As New StringFormat()
'arreys to hold the text for both axies
Dim arrayTextX(numX), arrayTextY(numY - 1) As String
Dim i As Integer
'the distance from the right side of picturebox where x axis stops
Dim rightPad As Integer = 80
Dim brush As Brush = New SolidBrush(Color.FromArgb(245, 255, 255))
Dim pen As Pen = New Pen(Color.FromArgb(212, 212, 212), 1)
Dim height, x, y As Integer
'Run once
If count = True Then
Return
End If
count = True
stringFormat.Alignment = StringAlignment.Center
img = New Bitmap(PictureBox1.Width, PictureBox1.Height)
imgClone = New Bitmap(PictureBox1.Width, PictureBox1.Height)
g = Graphics.FromImage(img)
g.SmoothingMode = SmoothingMode.AntiAlias
g.Clear(Color.White)
'the distance in x axis between each value
widthInterval = CInt((PictureBox1.Width - leftPad - rightPad) / (numX + 1))
'the distance in y axis between each value
height = CInt((PictureBox1.Height - upPad - downPad) / (numY + 1))
'fill arrays with text
For i = 0 To numX - 1
arrayTextX(i) = (i + 1).ToString
Next
For i = 0 To numY - 1
arrayTextY(i) = ((i + 1) * height).ToString
Next
'fill background of graph with color
g.FillRectangle(brush, New Rectangle(leftPad, upPad, PictureBox1.Width - leftPad - rightPad + 1, _
PictureBox1.Height - downPad - upPad))
'vertical lines
x = leftPad
For i = 0 To numX - 1
x += widthInterval
g.DrawLine(pen, x, PictureBox1.Height - downPad, x, upPad)
g.DrawString(arrayTextX(i), New Font("Arial", 8), Brushes.Black, _
New Rectangle(x - 10, PictureBox1.Height - downPad + 3, 20, 20), stringFormat)
Next
'horizontal lines
stringFormat.Alignment = StringAlignment.Far
y = PictureBox1.Height - downPad
For i = 0 To numY - 1
y -= height
g.DrawLine(pen, leftPad, y, PictureBox1.Width - rightPad, y)
g.DrawString(arrayTextY(i), New Font("Arial", 8), Brushes.Black, _
New Rectangle(0, y - 6, leftPad - 5, 20), stringFormat)
Next
g.DrawString("KW/Hour", New Font("Arial", 8, FontStyle.Bold), Brushes.Black, _
New PointF(5, 5))
g.DrawString("Time", New Font("Arial", 8, FontStyle.Bold), Brushes.Black, _
New PointF(PictureBox1.Width - 50, PictureBox1.Height - 20))
'draws x axis
g.DrawLine(Pens.Black, New Point(leftPad, PictureBox1.Height - downPad), _
New Point(PictureBox1.Width - rightPad, PictureBox1.Height - downPad))
'draws y axis
g.DrawLine(Pens.Black, New Point(leftPad, PictureBox1.Height - downPad), _
New Point(leftPad, upPad))
g.Dispose()
PictureBox1.Image = img
imgClone = CType(img.Clone, Bitmap)
End Sub
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
Dim value, x As Integer
Dim g As Graphics
Dim pntEnd As Point
Static pnt As Point = New Point(-1, -1)
Static staticX As Integer = -1
Dim hour As Integer = DateTime.Now.Hour
Dim minute As Integer = DateTime.Now.Minute
Dim second As Integer = DateTime.Now.Second
second = minute * 60 + second
x = leftPad + hour * widthInterval + CInt(CDbl(widthInterval - 1) * CDbl(second) / 3600.0R)
If pnt.X >= 0 Then
'checks if the new points x coordinate is the same as the previous and returns
If x <= staticX Then
Return
End If
End If
GetValue(value)
pntEnd = New Point(x, PictureBox1.Height - value - downPad)
g = Graphics.FromImage(img)
g.SmoothingMode = SmoothingMode.AntiAlias
If pnt.X < 0 Then
g.DrawLine(Pens.Red, pntEnd, pntEnd)
Else
g.DrawLine(Pens.Red, pnt, pntEnd)
End If
g.Dispose()
pnt = pntEnd
staticX = x
PictureBox1.Invalidate()
End Sub
Private Sub GetValue(ByRef value As Integer)
'here you can take the value from arduino.
value = rn.Next(0, PictureBox1.Height - downPad - upPad) 'random value
End Sub
When you press Button1the graph starts.
当您按下Button1 时,图形开始。
Calculate width of graph (x axis)
计算图形的宽度(x 轴)
width = PictureBox1.Width - leftPad - rightPad
this widthis equivelant with 24h or 86400sec. So you should set the timer interval to
此宽度与 24 小时或 86400 秒相等。所以你应该将定时器间隔设置为
Timer1.Interval = CInt((86400 / width ) * 1000) 'in milliseconds
There is no need to be that because the tickfunction checks if the new point is the same as the previous. So set timer interval to 1 second.
没有必要这样做,因为tick函数会检查新点是否与前一个点相同。因此,将计时器间隔设置为 1 秒。

