AdvancedHMI Software
General Category => Support Questions => Topic started by: andyandy26 on February 11, 2015, 05:22:00 AM
-
UGH
So I've been using the trend chart and found myself to be hating it's default look...
All I want to do is change the background colour and the line colour however I can't find the setting to change the line colour and the backColour doesn't make a difference...
Is it even possible? Maybe I should have a deeper look at its coding...
-
The BasicTrendChart is truly just a Basic chart.If you want a Chart with more capabilities, you can use the Chart found on the Data group of the Toolbox along with the DataSubscriber. Here a couple threads discussing it's use:
http://advancedhmi.com/forum/index.php?topic=226.msg775#msg775
http://advancedhmi.com/forum/index.php?topic=606.msg2701#msg2701
-
Here is another forum thread discussing the use of Chart:
http://sourceforge.net/p/advancedhmi/discussion/875091/thread/a2bce815/
-
Maybe is it possible to modify your BasicTrendChart?
Since it inherits the basicchart... (mind you I really am a rookie at VB and could be completely wrong)
is there somewhere in the code of the component that specifies the look that it has been given?
I know that I've tried creating charts before, with a bit of success but they caused the program to lag horribly... I recently lost that project file to corruption and am in the process of rebuilding it with your new version... many new features are very helpful. :)
so since it is just a branch off of the basic chart is it possible to modify how it looks when it is ported through?
Thanks for helping
-
Yes, you can extend the BasicTrendChart by inheriting it into a new class then overriding the Paint event. This does require a bit of knowledge of GDI+ and creating classes. Here is the framework to help get started on modifying the BasicTrendChart:
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
e.Graphics.FillRectangle(New SolidBrush(Color.White), 0, 0, Me.Width, Me.Height)
Dim MaxValue As Int16
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 1)
Try
'* Keep traclk of the maximum value for the Y Axis value draw at the end
If Points(index) > MaxValue Then
MaxValue = Points(index)
End If
'* calculate the x and y coordinates based on the Points collection
Dim StartPixel As New Point(x1, y1)
Dim EndPixel As New Point(x2, y2)
e.Graphics.DrawLine(System.Drawing.Pens.Blue, StartPixel, EndPixel)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(MaxValue.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
End Class
-
Hate to continue bothering you, however (your coding ability is excellent btw) it tells me that the points x1,x2,y1,y2 variables haven't been declared in the collection. the error sates that they may be inaccessible due to its protection level
As a result, I tried just initializing the variables however they aren't being populated and thus no line appears. it does however recognize the value and assigns the max y to it.
:(
-
That code is not complete, but more of a starting point. You would need to replace the x1, y1, x2, and y2 with calculations to go from the values in the Points collection to the pixel position on the chart. So let's make this a little easier and make the Y Axis max a fixed value by creating a property:
Private m_YAxisMaximum as integer
Public Propety YAxisMaximum as Integer
Get
Return m_YAxisMaximum
End Get
Set (value as integer)
m_YAxisMaximum =value
end Set
End Property
So now create variables and calculate their values
Dim x1,y1 as Integer
Dim x2, y2 as integer
x1=convert.ToInt32((Me.width/Points.Count) * index)
y1=Convert.ToInt32(Me.Height/m_YaxisMaximum)*Points(index))
x2=convert.ToInt32((Me.width/Points.Count) * index+1)
y1=Convert.ToInt32(Me.Height/m_YaxisMaximum)*Points(index+1))
-
So putting that all together:
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
e.Graphics.FillRectangle(New SolidBrush(Color.White), 0, 0, Me.Width, Me.Height)
Dim x1,y1 as Integer
Dim x2, y2 as integer
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 2)
Try
'* calculate the x and y coordinates based on the Points collection
x1=convert.ToInt32((Me.width/Points.Count) * index)
y1=Convert.ToInt32(Me.Height/m_YaxisMaximum)*Points(index))
x2=convert.ToInt32((Me.width/Points.Count) * index+1)
y1=Convert.ToInt32(Me.Height/m_YaxisMaximum)*Points(index+1))
Dim StartPixel As New Point(x1, y1)
Dim EndPixel As New Point(x2, y2)
e.Graphics.DrawLine(System.Drawing.Pens.Blue, StartPixel, EndPixel)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(MaxValue.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
End Class
-
hmm, the graph shows and I've made a few tweaks to make it work :P
however the line is only appearing at the top of the chart, appearing as a line that gradually fills from left to right...
I'm truly stumped, no idea why this is happening.
This is my code:
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
e.Graphics.FillRectangle(New SolidBrush(BackColour), 0, 0, Me.Width, Me.Height)
Dim x1, y1 As Integer
Dim x2, y2 As Integer
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 2)
Try
'* calculate the x and y coordinates based on the Points collection
x1 = convert.ToInt32((Me.width / Points.Count) * index)
y1 = Convert.ToInt32(Me.Height / m_YAxisMaximum) * Points(index)
x2 = Convert.ToInt32((Me.Width / Points.Count) * (index + 1))
y2 = Convert.ToInt32(Me.Height / m_YAxisMaximum) * Points(index + 1)
'*^ this was y1
Dim StartPixel As New Point(x1, y1)
Dim EndPixel As New Point(x2, y2)
e.Graphics.DrawLine(System.Drawing.Pens.Yellow, StartPixel, EndPixel)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(m_YAxisMaximum.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
'* ^^^^^^^^^^^^^^^ this was MaxValue
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
Private m_YAxisMaximum As Integer
Public Property YAxisMaximum As Integer
Get
Return m_YAxisMaximum
End Get
Set(value As Integer)
m_YAxisMaximum = value
End Set
End Property
Private _BackColour As Drawing.Color = Drawing.Color.Green
Public Property BackColour() As Drawing.Color
Get
Return _BackColour
End Get
Set(ByVal value As Drawing.Color)
_BackColour = value
End Set
End Property
End Class
-
Be sure your maximum Y value has something other than 0:
Private m_YAxisMaximum As Integer=32767
-
well I'd set the max y value to 1700
my PLC is giving ~1250 (seen in a digital panel meter)
same PLCAddressValue... weird results :/
-
Just thought I might post a pic of the problem:
The left is the one utilizing the new code and the one on the right is the default trendchart
-
I think the problem is here:
y1 = Convert.ToInt32(Me.Height / m_YAxisMaximum) * Points(index)
This should be
y1 = Convert.ToInt32((Me.Height / m_YAxisMaximum) * Points(index))
The same with y2
-
Yhippee! after a bit more help (thanks) and some tinkering, it now works!
Thanks Archie for your help, not only for helping to make it work but also expanding my ability.
Now I know how to add my own properties and such :)
now just to wrap my head around classes and their methods interaction... maybe one day I may be as talented as you! :P
For any peeps who may want it, here is the final code:
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
e.Graphics.FillRectangle(New SolidBrush(BackColour), 0, 0, Me.Width, Me.Height)
Dim x1, y1 As Integer
Dim x2, y2 As Integer
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 2)
Try
'* calculate the x and y coordinates based on the Points collection
x1 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * index)
y1 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index) - YMinimum))
x2 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * (index + 1))
y2 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index + 1) - YMinimum))
'*^ this was y1
Dim StartPixel As New Point(x1, y1)
Dim EndPixel As New Point(x2, y2)
'e.Graphics.DrawLine(System.Drawing.Pens.Yellow, StartPixel, EndPixel)
e.Graphics.DrawLine(System.Drawing.Pens.Yellow, x1, y1, x2, y2)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(YMaximum.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
'* ^^^^^^^^^^^^^^^ this was MaxValue
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
Private _BackColour As Drawing.Color = Drawing.Color.Green
Public Property BackColour() As Drawing.Color
Get
Return _BackColour
End Get
Set(ByVal value As Drawing.Color)
_BackColour = value
End Set
End Property
End Class
Enjoy!
-
Thanks for sharing!!
Yhippee! after a bit more help (thanks) and some tinkering, it now works!
Thanks Archie for your help, not only for helping to make it work but also expanding my ability.
Now I know how to add my own properties and such :)
now just to wrap my head around classes and their methods interaction... maybe one day I may be as talented as you! :P
For any peeps who may want it, here is the final code:
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
e.Graphics.FillRectangle(New SolidBrush(BackColour), 0, 0, Me.Width, Me.Height)
Dim x1, y1 As Integer
Dim x2, y2 As Integer
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 2)
Try
'* calculate the x and y coordinates based on the Points collection
x1 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * index)
y1 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index) - YMinimum))
x2 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * (index + 1))
y2 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index + 1) - YMinimum))
'*^ this was y1
Dim StartPixel As New Point(x1, y1)
Dim EndPixel As New Point(x2, y2)
'e.Graphics.DrawLine(System.Drawing.Pens.Yellow, StartPixel, EndPixel)
e.Graphics.DrawLine(System.Drawing.Pens.Yellow, x1, y1, x2, y2)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(YMaximum.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
'* ^^^^^^^^^^^^^^^ this was MaxValue
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
Private _BackColour As Drawing.Color = Drawing.Color.Green
Public Property BackColour() As Drawing.Color
Get
Return _BackColour
End Get
Set(ByVal value As Drawing.Color)
_BackColour = value
End Set
End Property
End Class
Enjoy!
-
Thanks for sharing.
I have tweaked it a bit more with original BackColor, DoubleBuffering and 3 new properties (DrawRightToLeft, GraphLineColor and GraphLineThickness) and here is the code:
Imports System
Imports System.ComponentModel
Public Class BasicTrendChartEx
Inherits BasicTrendChart
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
'* Fill in the background color
Me.DoubleBuffered = True 'Reduce or eliminate flicker
e.Graphics.FillRectangle(New SolidBrush(BackColor), 0, 0, Me.Width, Me.Height)
Dim x1, y1 As Integer
Dim x2, y2 As Integer
'* Draw the line connecting the points
If Points.Count > 1 Then
Dim index As Integer = 0
While index < (Points.Count - 2)
Try
'* calculate the x and y coordinates based on the Points collection
If DrawRightToLeft = True Then
x1 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * index)
x2 = Me.Width - Convert.ToInt32((Me.Width / MaxPoints) * (index + 1))
Else
x1 = Convert.ToInt32((Me.Width / MaxPoints) * index)
x2 = Convert.ToInt32((Me.Width / MaxPoints) * (index + 1))
'*^ this was y1
End If
y1 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index) - YMinimum))
y2 = Me.Height - Convert.ToInt32((Me.Height / (YMaximum - YMinimum)) * (Points(index + 1) - YMinimum))
e.Graphics.DrawLine(New Pen(GraphLineColor, GraphLineThickness), x1, y1, x2, y2)
Catch ex As Exception
Dim dbg = 0
End Try
index += 1
End While
e.Graphics.DrawString(Now.ToString("dd-MMM-yy HH:mm:ss"), New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, Me.Width - 116, Me.Height - 16)
e.Graphics.DrawString(Points.Last.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, Me.Width - 40, 0)
End If
'* Draw the Axis
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, 0, 0, Me.Height)
e.Graphics.DrawLine(System.Drawing.Pens.White, 0, Me.Height - 1, Me.Width, Me.Height - 1)
e.Graphics.DrawString(YMaximum.ToString, New Drawing.Font("Arial", 10.0!), System.Drawing.Brushes.White, 0.0!, 0.0!)
'* ^^^^^^^^^^^^^^^ this was MaxValue
e.Graphics.DrawString(YMinimum.ToString, New Drawing.Font("Arial", 10), System.Drawing.Brushes.White, 0, Me.Height - 16)
End Sub
Public Property DrawRightToLeft As Boolean = False
<DefaultValue(GetType(Color), "Black")> _
Public Overridable Shadows Property BackColor() As Color
Get
Return MyBase.BackColor
End Get
Set(ByVal value As Color)
MyBase.BackColor = value
Refresh()
End Set
End Property
Private _GraphLineColor As Drawing.Color = Drawing.Color.Blue
Public Property GraphLineColor() As Drawing.Color
Get
Return _GraphLineColor
End Get
Set(ByVal value As Drawing.Color)
_GraphLineColor = value
End Set
End Property
Private _gLineThickness As Single = 1
Public Property GraphLineThickness() As Single
Get
Return _gLineThickness
End Get
Set(ByVal value As Single)
If Not IsNumeric(value) Then
MsgBox("Valid values are numbers 1 to 3!")
_gLineThickness = 1
Exit Property
Else
If (value > 3) OrElse (value < 1) Then
MsgBox("Valid values are numbers 1 to 3!")
_gLineThickness = 1
Exit Property
End If
End If
_gLineThickness = value
End Set
End Property
End Class
It also shows Date/Time and the last Value.