|
-
Jul 2nd, 2008, 07:09 AM
#1
Thread Starter
Member
VB.net Doughnut Piecharts
Hi,
Can someone tell me how to draw doughnut chart using vb.net gdi+ ?. The doughnut chart is similiar to pie chart (relative pie charts )
-
Jul 2nd, 2008, 07:41 AM
#2
Re: VB.net Doughnut Piecharts
A doughnut is simply a pie with the middle taken out, so that's exactly what you draw. You call DrawPie multiple times to draw a pie chart, then you call DrawPie the same number of times again with the same centre and angles but a smaller radius to "take out" the middle.
-
Jul 3rd, 2008, 01:36 AM
#3
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Thanks for your reply
but when I try to draw and color multiple pie with the same center and different radii. The one which I had drawn recently is overdrawing the existing. I want to remove that overlapping. How would I do that.Please let me know if you aren't clear about my doubt.
Last edited by saechira; Jul 3rd, 2008 at 02:22 AM.
-
Jul 3rd, 2008, 01:54 AM
#4
Addicted Member
Re: VB.net Doughnut Piecharts
Heres the code for making a pie chart based on 4 numbers, which colors them randomly. lol i made this for school
vb Code:
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. Friend WithEvents btnChart As System.Windows.Forms.Button Friend WithEvents lblInfo As System.Windows.Forms.Label Friend WithEvents tx1 As System.Windows.Forms.TextBox Friend WithEvents tx2 As System.Windows.Forms.TextBox Friend WithEvents tx3 As System.Windows.Forms.TextBox Friend WithEvents tx4 As System.Windows.Forms.TextBox Friend WithEvents lblPie As System.Windows.Forms.Label Friend WithEvents lblPercent As System.Windows.Forms.Label <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.btnChart = New System.Windows.Forms.Button Me.lblInfo = New System.Windows.Forms.Label Me.tx1 = New System.Windows.Forms.TextBox Me.tx2 = New System.Windows.Forms.TextBox Me.tx3 = New System.Windows.Forms.TextBox Me.tx4 = New System.Windows.Forms.TextBox Me.lblPie = New System.Windows.Forms.Label Me.lblPercent = New System.Windows.Forms.Label Me.SuspendLayout() ' 'btnChart ' Me.btnChart.BackColor = System.Drawing.Color.FromArgb(CType(255, Byte), CType(128, Byte), CType(128, Byte)) Me.btnChart.Location = New System.Drawing.Point(24, 104) Me.btnChart.Name = "btnChart" Me.btnChart.Size = New System.Drawing.Size(104, 24) Me.btnChart.TabIndex = 0 Me.btnChart.Text = "Chart" ' 'lblInfo ' Me.lblInfo.Location = New System.Drawing.Point(16, 24) Me.lblInfo.Name = "lblInfo" Me.lblInfo.Size = New System.Drawing.Size(96, 24) Me.lblInfo.TabIndex = 1 Me.lblInfo.Text = "Enter four values:" Me.lblInfo.TextAlign = System.Drawing.ContentAlignment.MiddleRight ' 'tx1 ' Me.tx1.Location = New System.Drawing.Point(128, 24) Me.tx1.Name = "tx1" Me.tx1.Size = New System.Drawing.Size(112, 20) Me.tx1.TabIndex = 2 Me.tx1.Text = "10" ' 'tx2 ' Me.tx2.Location = New System.Drawing.Point(248, 24) Me.tx2.Name = "tx2" Me.tx2.Size = New System.Drawing.Size(112, 20) Me.tx2.TabIndex = 3 Me.tx2.Text = "20" ' 'tx3 ' Me.tx3.Location = New System.Drawing.Point(368, 24) Me.tx3.Name = "tx3" Me.tx3.Size = New System.Drawing.Size(112, 20) Me.tx3.TabIndex = 4 Me.tx3.Text = "30" ' 'tx4 ' Me.tx4.Location = New System.Drawing.Point(488, 24) Me.tx4.Name = "tx4" Me.tx4.Size = New System.Drawing.Size(112, 20) Me.tx4.TabIndex = 5 Me.tx4.Text = "40" ' 'lblPie ' Me.lblPie.Location = New System.Drawing.Point(248, 80) Me.lblPie.Name = "lblPie" Me.lblPie.Size = New System.Drawing.Size(301, 301) Me.lblPie.TabIndex = 6 ' 'lblPercent ' Me.lblPercent.Location = New System.Drawing.Point(128, 56) Me.lblPercent.Name = "lblPercent" Me.lblPercent.Size = New System.Drawing.Size(472, 16) Me.lblPercent.TabIndex = 7 ' 'Form1 ' Me.AcceptButton = Me.btnChart Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(616, 405) Me.Controls.Add(Me.lblPercent) Me.Controls.Add(Me.lblPie) Me.Controls.Add(Me.tx4) Me.Controls.Add(Me.tx3) Me.Controls.Add(Me.tx2) Me.Controls.Add(Me.tx1) Me.Controls.Add(Me.lblInfo) Me.Controls.Add(Me.btnChart) Me.MaximizeBox = False Me.MaximumSize = New System.Drawing.Size(624, 432) Me.MinimumSize = New System.Drawing.Size(624, 432) Me.Name = "Form1" Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen Me.Text = "Pie Chart" Me.ResumeLayout(False) End Sub #End Region Private Sub btnChart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChart.Click If IsNumeric(tx1.Text) = False Or IsNumeric(tx2.Text) = False Or IsNumeric(tx3.Text) = False Or IsNumeric(tx4.Text) = False Then MessageBox.Show("Please only choose numbers", "Idiot Alert!") Exit Sub End If Dim Chart As Graphics = Me.lblPie.CreateGraphics Chart.Clear(Color.FromKnownColor(KnownColor.Control)) Dim pBlack As New Pen(Color.Black, 2) 'store brushes in an array for ease in a loop Dim intSum As Integer = Int(tx1.Text) + Int(tx2.Text) + Int(tx3.Text) + Int(tx4.Text) Dim intPercent() As Decimal = {(tx1.Text / intSum), (tx2.Text / intSum), (tx3.Text / intSum), (tx4.Text / intSum)} lblPercent.Text = "" Chart.DrawEllipse(pBlack, 0, 0, 300, 300) Dim intCount As Integer Dim intNext As Decimal = 0 Randomize() For intCount = 0 To 3 Dim randBrush As New SolidBrush(Color.FromArgb(CType(Rnd() * 255, Byte), CType(Rnd() * 255, Byte), CType(Rnd() * 255, Byte))) Chart.FillPie(randBrush, 0, 0, 300, 300, intNext, (intPercent(intCount) * 360)) intNext = intNext + (intPercent(intCount) * 360) lblPercent.Text = lblPercent.Text & Math.Round(intPercent(intCount) * 100, 2) & "% " & " " Next End Sub End Class
-
Jul 3rd, 2008, 02:32 AM
#5
Thread Starter
Member
Re: VB.net Doughnut Piecharts
I want to draw a doughchart on picturebox control of the form.
-
Jul 3rd, 2008, 02:37 AM
#6
Addicted Member
Re: VB.net Doughnut Piecharts
So just declare a new graphics class on the PictureBox and use that general code, but at the end, tell it to paint a circle that is the same color of your form's background to achieve the doughnut chart effect.
-
Jul 3rd, 2008, 07:23 AM
#7
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Yep. As I mentioned relative (multiple layer doughnuts). using the above method I could do it for single doughnut.How about a doughnut like the one in this link. It need not be exploded. Slicing with spaces is not required. I am really struck up here.
http://dotnetcharts.com/gallery/gall...uctname=Charts
Last edited by saechira; Jul 3rd, 2008 at 11:45 PM.
-
Jul 3rd, 2008, 02:08 PM
#8
Addicted Member
Re: VB.net Doughnut Piecharts
Well you can use the code I gave you to get the general process of drawing elliptical objects based on a numeric value and its percentage in the total, and using that;
1) Make it draw starting from the outermost doughnut.
2) Each time a doughnut layer is drawn, make it draw a circle that is filled with the background color of the form.
3) ??????
4) PROFIT!
Lol, but on a serious note, do you get what I'm saying and how to do everything?
-
Jul 4th, 2008, 12:20 AM
#9
Thread Starter
Member
Re: VB.net Doughnut Piecharts
yes what you have ssaid is true.
But my requirement goes like this.
In my application I cannot start always with the outermost doughnut (pie). I have 2 doughnut pies. I need to draw it dynamically. Sometimes I may need to color the inner pie. Later when I need to color the outer pie then its overdrawing the innerpie. To avoid that I have to repaint the innercircle (the one which has been overdrawn, with the same color and sweep angles). How would I do that.
Determing the angles while drawing doughnut is possible, but repainting the existing circle (the clip) is difficult. can I capture the inner pie into clip before drawing the outer pie.
-
Jul 4th, 2008, 01:12 AM
#10
Re: VB.net Doughnut Piecharts
 Originally Posted by saechira
In my application I cannot start always with the outermost doughnut
Yes, you can. When you use GDI+ you have to redraw everything on each Paint event anyway. All you have to do is make sure that each graph is within the one drawn before it. If you only want to draw the inner graph then you just draw that. If you then want to add the outer graph you simply add it to the list of graphs to draw before the existing graph. In your Paint event handler you'll loop through all the graphs to draw and you'll draw them outer to inner.
-
Jul 4th, 2008, 02:11 AM
#11
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Got u ..To draw the outer pie : I should add the outer pie to the list of existing pies. But would the contents of the inner circle(sweep angles, colors..) be retained. How would I repaint the circles without lossing any content. As I am new to .Net, I dont know how to repaint(). I apologize for the ignorance.
>If you then want to add the outer graph you simply add it to the list of
>graphs to draw before the existing graph.
-
Jul 4th, 2008, 03:47 AM
#12
Re: VB.net Doughnut Piecharts
Here are some classes you will find useful:
Code:
Public Class DoughnutChartPart
Private _colour As Color
Private _text As String
Private _value As Single
Public Property Colour() As Color
Get
Return Me._colour
End Get
Set(ByVal value As Color)
Me._colour = value
End Set
End Property
Public Property Text() As String
Get
Return Me._text
End Get
Set(ByVal value As String)
Me._text = value
End Set
End Property
Public Property Value() As Single
Get
Return Me._value
End Get
Set(ByVal value As Single)
Me._value = value
End Set
End Property
Public Sub New()
End Sub
Public Sub New(ByVal color As Color, _
ByVal text As String, _
ByVal value As Single)
Me._colour = color
Me._text = text
Me._value = value
End Sub
End Class
Code:
Public Class DoughnutChartPartCollection
Inherits System.Collections.ObjectModel.Collection(Of DoughnutChartPart)
End Class
Code:
Public Class DoughnutChart
Private Const FULL_CIRCLE As Single = 360.0F
Private Const DEGREES_TO_RADIANS As Single = Math.PI / 180.0F
Private Const RADIANS_TO_DEGREES As Single = 1 / DEGREES_TO_RADIANS
Private _centre As Point
Private _innerRadius As Single
Private _outerRadius As Single
Private _parts As New DoughnutChartPartCollection
Private _startAngle As Single
Private _sweepAngle As Single
Public Property Centre() As Point
Get
Return Me._centre
End Get
Set(ByVal value As Point)
Me._centre = value
End Set
End Property
Public Property InnerRadius() As Single
Get
Return Me._innerRadius
End Get
Set(ByVal value As Single)
If value < 0.0 Then
Throw New ArgumentException("The inner radius cannot be less than zero.")
End If
If value > Me.OuterRadius Then
Throw New ArgumentException("The inner radius cannot be greater than the outer radius.")
End If
Me._innerRadius = value
End Set
End Property
Public Property OuterRadius() As Single
Get
Return Me._outerRadius
End Get
Set(ByVal value As Single)
If value < 0.0 Then
Throw New ArgumentException("The outer radius cannot be less than zero.")
End If
If value < Me.InnerRadius Then
Throw New ArgumentException("The outer radius cannot be less than the inner radius.")
End If
Me._outerRadius = value
End Set
End Property
Public ReadOnly Property Parts() As DoughnutChartPartCollection
Get
Return Me._parts
End Get
End Property
Public Property StartAngle() As Single
Get
Return Me._startAngle
End Get
Set(ByVal value As Single)
value = value Mod FULL_CIRCLE
If value < 0.0 Then
value = FULL_CIRCLE + value
End If
'The angle is now guaranteed to be in the range 0.0 <= value < 360.0.
Me._startAngle = value
End Set
End Property
Public Property SweepAngle() As Single
Get
Return Me._sweepAngle
End Get
Set(ByVal value As Single)
If value < 0.0 OrElse value > FULL_CIRCLE Then
Throw New ArgumentOutOfRangeException("The sweep cannot be less than zero and must be less than 360.")
End If
Me._sweepAngle = value
End Set
End Property
Public Sub New(ByVal outerRadius As Single, _
ByVal innerRadius As Single)
Me.New(outerRadius, _
innerRadius, _
Point.Empty)
End Sub
Public Sub New(ByVal outerRadius As Single, _
ByVal innerRadius As Single, _
ByVal centre As Point, _
ByVal ParamArray parts As DoughnutChartPart())
Me.New(outerRadius, _
innerRadius, _
centre, _
0.0, _
FULL_CIRCLE, _
parts)
End Sub
Public Sub New(ByVal outerRadius As Single, _
ByVal innerRadius As Single, _
ByVal centre As Point, _
ByVal startAngle As Single, _
ByVal sweepAngle As Single, _
ByVal ParamArray parts As DoughnutChartPart())
Me.OuterRadius = outerRadius
Me.InnerRadius = innerRadius
Me.Centre = centre
Me.StartAngle = startAngle
Me.SweepAngle = sweepAngle
For Each part As DoughnutChartPart In parts
Me.Parts.Add(part)
Next
End Sub
Public Sub Draw(ByVal g As Graphics, ByVal backColor As Color)
Dim totalValue As Single = 0.0F
Dim part As DoughnutChartPart
'Sum the values.
For Each part In Me.Parts
totalValue += part.Value
Next
Dim sweepAngle As Single = Me.SweepAngle
Dim sweepAngles As New Dictionary(Of DoughnutChartPart, Single)
'Determine the sweep angles of the parts.
For Each part In Me.Parts
sweepAngles.Add(part, sweepAngle * part.Value / totalValue)
Next
Dim startAngle As Single = Me.StartAngle
Dim centre As Point = Me.Centre
Dim outerRadius As Single = Me.OuterRadius
Dim outerDiameter As Single = 2 * outerRadius
For Each part In Me.Parts
sweepAngle = sweepAngles(part)
Using brush As New SolidBrush(part.Colour)
g.FillPie(brush, _
centre.X - outerRadius, _
centre.Y - outerRadius, _
outerDiameter, _
outerDiameter, _
startAngle, _
sweepAngle)
End Using
startAngle += sweepAngle
Next
Dim innerRadius As Single = Me.InnerRadius
Dim innerDiameter As Single = 2 * innerRadius
Using brush As New SolidBrush(backColor)
g.FillEllipse(brush, _
centre.X - innerRadius, _
centre.Y - innerRadius, _
innerDiameter, _
innerDiameter)
End Using
End Sub
End Class
Create a new Windows Forms project and add those classes to it. Now add the following code to your form:
Code:
Private doughnut As DoughnutChart
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
Me.doughnut = New DoughnutChart(200, _
150, _
New Point(200, 200), _
New DoughnutChartPart(Color.Red, "Red", 10), _
New DoughnutChartPart(Color.Green, "Green", 20), _
New DoughnutChartPart(Color.Blue, "Blue", 30))
End Sub
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles Me.Paint
Me.doughnut.Draw(e.Graphics, Me.BackColor)
End Sub
Now run the project and BEHOLD!
Now change the code in the form to this:
Code:
Private doughnuts As New List(Of DoughnutChart)
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
Me.doughnuts.Add(New DoughnutChart(200, _
150, _
New Point(200, 200), _
New DoughnutChartPart(Color.Red, "Red", 10), _
New DoughnutChartPart(Color.Green, "Green", 20), _
New DoughnutChartPart(Color.Blue, "Blue", 30)))
Me.doughnuts.Add(New DoughnutChart(100, _
50, _
New Point(200, 200), _
45, _
270, _
New DoughnutChartPart(Color.Cyan, "Cyan", 40), _
New DoughnutChartPart(Color.Magenta, "Magenta", 50), _
New DoughnutChartPart(Color.Yellow, "Yellow", 60)))
End Sub
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles Me.Paint
For Each doughnut As DoughnutChart In Me.doughnuts
doughnut.Draw(e.Graphics, Me.BackColor)
Next
End Sub
Now run the project and BEHOLD again. I'll leave it up to you to make any improvements that are required, including drawing the text on each part. Just remember that the items in the List are drawn from first index to last, so they must be in order from outer to inner.
Last edited by jmcilhinney; Jul 4th, 2008 at 03:50 AM.
-
Jul 5th, 2008, 09:06 AM
#13
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Isn't there any way to capture the existing inner circle into clip instead of redrawing the inner circle part by part. please Correct me if I am wrong. Does n't the vb.net automatically capture the existing the graphics and redraw similiar on repaint()
-
Jul 5th, 2008, 09:49 AM
#14
Re: VB.net Doughnut Piecharts
you could invalidate a specific part of your form, i suppose..
-
Jul 5th, 2008, 02:03 PM
#15
Thread Starter
Member
Re: VB.net Doughnut Piecharts
In case of drawing the inner circle pie (filling the inner pie parts)
where should I mention that first redraw the outer pie and then only draw the inner pie(fill in the pie).Is it in the Invalidated() event of picture box ? If so how do I ensure that while redrawing the pies their parts (sweep angles) are retained ? Are the parts (sweep angles)retained automatically. If it is automatically retained how would I add parts to the inner pie?
The following is the sample code which I have written. Hope it is easy to understand
Code:
Imports System.Drawing
Public Class Form1
Dim r As Region
Dim g As Graphics
Dim mypen As Pen = Pens.Beige
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
r = Me.PictureBox1.Region()
MessageBox.Show("In F paint")
mypen = New Pen(Color.CornflowerBlue)
g.DrawEllipse(Pens.OrangeRed, 50, 50, 50, 50)
g.DrawEllipse(Pens.OrangeRed, 25, 25, 100, 100)
mypen = Pens.Red
g.FillPie(Brushes.Blue, 25, 25, 100, 100, 0, 45)
g.FillPie(Brushes.Red, 50, 50, 50, 50, 0, 45)
End Sub
Private Sub PictureBox1_Invalidated(ByVal sender As Object, ByVal e As System.Windows.Forms.InvalidateEventArgs) Handles PictureBox1.Invalidated
End Sub
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
MessageBox.Show("In PB paint")
mypen = Pens.Aqua
Me.Invalidate()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
g = PictureBox1.CreateGraphics
End Sub
End Class
-
Jul 5th, 2008, 07:57 PM
#16
Re: VB.net Doughnut Piecharts
You seem not to be getting this bit: EVERYTHING gets redrawn EVERY time. EVERY time the Paint event is raised you must execute code to draw EVERYTHING. That's the way it ALWAYS works. So, your Paint event handler draws EVERYTHING, then the system decides which parts of that actually get repainted to the screen based on your calls Invalidate. If you invalidate only a small rectangle in the top left corner of the form then the system will take the contents of that rectangle from your drawing and paint it to the screen.
Now, the whole point of my creating those classes is so that they contain, and therefore retain, all the data about the objects they represent. You set the sweep angle of a chart once and it stays that value all the time, until you set the SweepAngle property to a different value.
All the parts of a chart are stored in its Parts collection property. If you want to add a part to a chart you simply create a new DoughnutChartPart object and then call the Add method of the chart's Parts collection, e.g.
vb.net Code:
myChart.Parts.Add(New DoughnutChartPart(Color.Pink, "Pink", 45))
You would then call Invalidate and Update to force the area containing that chart to redraw and it would automatically update itself to accommodate the new part.
Let's go back to my second example, with the two charts. Try adding two Buttons to your form and then add this code:
Code:
Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button1.Click
'Add a part to the outer chart.
Me.AddPart(Me.doughnuts(0), Color.Orange, 40)
End Sub
Private Sub Button2_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button2.Click
'Add a part to the inner chart.
Me.AddPart(Me.doughnuts(1), Color.Purple, 70)
End Sub
Private Sub AddPart(ByVal chart As DoughnutChart, _
ByVal color As Color, _
ByVal value As Integer)
'Add a new part.
chart.Parts.Add(New DoughnutChartPart(color, _
color.ToString(), _
value))
Dim centre As Point = chart.Centre
Dim radius As Integer = CInt(Math.Ceiling(chart.OuterRadius))
Dim diameter As Integer = 2 * radius
'Redraw the chart to display the new part.
Me.Invalidate(New Rectangle(centre.X - radius, _
centre.Y - radius, _
diameter, _
diameter))
Me.Update()
End Sub
Now run the project again and see that the charts look the same as before. Now click the Button1 and see that the new part gets added to the outer chart. The same start angle and sweep angle are used because they are stored in the chart itself and have not been changed. The area that gets repainted is the smallest rectangle that contains the outer chart.
Now click Button2 and see that a new part gets added to the inner chart. Again, the same start and sweep angle are used because they are part of the chart. This time the area that gets repainted in the smallest rectangle that contains the inner chart. As such, much of the outer chart will not be repainted because it is not within that area.
Your Paint event handler still draws the entire outer chart though. It's not for you to decide what to draw. You just draw everything. The system then decides what part of that drawing gets painted to the screen. It's that last step that is the slow part so it's that last step that has to be tightly controlled to pass as little data as possible.
If you wanted to make the repaint even more efficient you could pass a Region when calling Invalidate instead of a Rectangle. You would create that Region from a GraphicsPath and you'd create the GraphicsPath from a circle. You could even then remove a smaller circle from the graphicsPath to create a doughnut shaped Region. That would be the absolute smallest area possible to repaint that contained your doughnut chart. While it's more complex, and therefore slower, to calculate that doughnut-shaped Region than it is to just use a Rectangle, it's faster to paint just the pixels in that area to the screen, so overall it's still more efficient to do it that way. I'll leave that to you as an exercise.
-
Jul 7th, 2008, 03:37 AM
#17
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Hi
In this below code
I have 3 circle
the innermost circle say circle1
the 2nd inner most circle circle2
the outermost circle circle3 (just default empty circle)
whenever I draw circle2 I have to redraw circle1
whenever I draw circle3 I have to redraw both circle2 and circle1 in that order.
When I draw circle3 the problem is to retain the parts of circle2 (circle 1 is an empty circle with no pie parts)
Every time a new pie part is added to the circle2 I save it in a collection
In case of drawing circle3
I draw circle 3 first then for I redraw the circle2 by retrieving the color,start,sweep angle attributes of the circle2. After drawing circle2 I draw circle1.
But it gives an unexpected result. This functions partially.I hope the logic is right but the implementation is going wrong somewhere. Still certain part on circle1 and circle2 is overdrawn while drawing circle3.
Please let me know where Am I going wrong. I just added hardcoded it to add 1 pie part for circle2 and another pie part for circle3
Code:
Public Class Form1
Dim myPen As Pen = Pens.Brown 'New a Pen object
Dim part As DoughnutChartPart
Dim parts As DoughnutChartPartCollection
Dim g As Graphics
Dim chk As Boolean = False
Dim colors As Color
Dim startAngle As Single
Dim sweepAngle As Single
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
parts = New DoughnutChartPartCollection
g = Me.PictureBox1.CreateGraphics()
End Sub
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
Me.Invalidate()
End Sub
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
g.DrawEllipse(myPen, 50, 50, 50, 50)
g.DrawEllipse(myPen, 38, 38, 75, 75)
g.DrawEllipse(myPen, 25, 25, 100, 100)
DrawInner()
DrawOuter()
End Sub
Private Sub DrawInner()
'MessageBox.Show("Inner")
If chk = False Then
part = New DoughnutChartPart(Color.Red, 0, 45)
g.DrawPie(New Pen(Color.Red), 38, 38, 75, 75, 0, 45)
parts.Add(part)
Else
'MessageBox.Show(parts.Count.ToString)
g.DrawPie(New Pen(Control.DefaultBackColor), 38, 38, 75, 75, 0, 360.0F)
g.DrawEllipse(myPen, 38, 38, 75, 75)
For Each part In Me.parts
g.DrawPie(New Pen(part.Colour), 38, 38, 75, 75, part.Start, part.Sweep)
'MessageBox.Show(part.Colour.ToString)
' MessageBox.Show(part.Start.ToString)
'MessageBox.Show(part.Sweep.ToString)
Next
End If
g.DrawPie(New Pen(Control.DefaultBackColor), 50, 50, 50, 50, 0, 360.0F)
g.DrawEllipse(myPen, 50, 50, 50, 50)
End Sub
Private Sub DrawOuter()
' MessageBox.Show("Outer")
g.DrawPie(Pens.Black, 25, 25, 100, 100, 0, 60)
chk = True
DrawInner()
chk = False
End Sub
End Class
Public Class DoughnutChartPart
Private _colour As Color
Private _text As String
Private _value As Single
Private _start As Single
Private _sweep As Single
Public Property Colour() As Color
Get
Return Me._colour
End Get
Set(ByVal value As Color)
Me._colour = value
End Set
End Property
Public Property Text() As String
Get
Return Me._text
End Get
Set(ByVal value As String)
Me._text = value
End Set
End Property
Public Property Start() As Single
Get
Return Me._start
End Get
Set(ByVal value As Single)
If value < 0.0 Then
Me._start = 360 + value
Else
Me._start = value
End If
End Set
End Property
Public Property Sweep() As Single
Get
Return Me._sweep
End Get
Set(ByVal value As Single)
If value < 0.0 Then
Me._sweep = 360 + value
Else
Me._sweep = value
End If
End Set
End Property
Public Sub New()
End Sub
Public Sub New(ByVal color As Color, _
ByVal start As Single, ByVal sweep As Single)
Me._colour = color
Me._sweep = sweep
Me._start = start
End Sub
End Class
Public Class DoughnutChartPartCollection
Inherits System.Collections.ObjectModel.Collection(Of DoughnutChartPart)
End Class
-
Jul 11th, 2008, 11:25 AM
#18
Thread Starter
Member
Re: VB.net Doughnut Piecharts
Thanks to all especially jmcilhinney. It works
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|