Page 1 of 1
Fixed Height Bars with Alternating Marks Position
Posted: Sun Mar 15, 2009 7:09 am
by 9092401
Hey,
I'm trying to create a graph with a fixed height, where the bars value will determine the relative width.
Also I need the marks position and length alternating in position, having odd marks above the graph and even ones below the graph.
In order to make the width relative I tried using Steema.TeeChart.Styles.HorizBar but I got the marks horizontal as well.
see attached image of the intended graph look
The red braces & blue arrows are only for illustration purposes.
Cheers,
Elad
Posted: Mon Mar 16, 2009 12:44 pm
by 10050769
Hi qcrnd,
You coud use a similar code as next, for fix your issue:
InitializeChart
Code: Select all
private void InitializeChart()
{
Steema.TeeChart.Styles.HorizBar hbar = new Steema.TeeChart.Styles.HorizBar(tChart1.Chart);
hbar.FillSampleValues(4);
hbar.ColorEach = true;
hbar.MultiBar = Steema.TeeChart.Styles.MultiBars.SelfStack;
tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(tChart1_AfterDraw);
tChart1.MouseUp += new MouseEventHandler(tChart1_MouseUp);
tChart1.Draw();
}
AfterDraw Event
Code: Select all
void tChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
RepositionMarks(tChart1[0]);
}
Method RepositionMarks
Code: Select all
private void RepositionMarks(Steema.TeeChart.Styles.Series series)
{
Steema.TeeChart.Styles.SeriesMarks.Position pos;
series.Chart.AutoRepaint = false;
for (int i = 0; i < series.Count; i++)
{
pos = series.Marks.Positions[i];
pos.Custom = true;
series.Marks.Arrow.Width = 2;
series.Marks.Arrow.Color = Color.Black;
int tmpX = tChart1.Axes.Bottom.CalcXPosValue(series.XValues[i]);
int tmpHalfWidth = Convert.ToInt32(pos.Width/2);
if (i == 0)
{
pos.LeftTop.X = tmpX - Convert.ToInt32((tmpX - tChart1.Axes.Bottom.IStartPos)/2) - tmpHalfWidth;
}
else
{
pos.LeftTop.X = series.Marks.Positions[i - 1].LeftTop.X + tmpX - tChart1.Axes.Bottom.IStartPos;
}
pos.ArrowTo.X = pos.LeftTop.X + pos.Width / 2;
pos.ArrowFrom.X = pos.ArrowTo.X;
int tmp = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Height;
if (i % 2 == 0)
{
pos.LeftTop.Y += tmp;
pos.ArrowFrom.Y = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Bottom;
}
else
{
pos.LeftTop.Y -= tmp;
pos.ArrowFrom.Y = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Top;
}
pos.ArrowTo.Y = pos.LeftTop.Y;
}
series.Chart.AutoRepaint = true;
series.Chart.Invalidate();
}
I hope that you have been served my help
Thanks
Posted: Tue Mar 17, 2009 9:33 am
by 9092401
I'm still having some issues.
We build out chart differently, I'll try changing the adjustments to your code.
Thanks
Elad
-
Posted: Tue Mar 17, 2009 1:13 pm
by 9092401
I still encounter several problems:
1) I've tried correcting the positions and there are many offsets.
This is the chart is built:
Code: Select all
foreach (KeyValuePair<string, int> val in Values)
{
HorizBar bar = new HorizBar(tChart1.Chart);
bar.MultiBar = MultiBars.Stacked;
bar.Cursor = Cursors.Hand;
bar.BarHeightPercent = 100;
bar.DepthPercent = 50;
bar.Marks.Visible = true;
bar.Color = GetColor(val.Key);
bar.Add(val.Value, val.Key);
bar.Title = string.Format("{0} {1}", val.Value, val.Key);
}
}
tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);
2) Since the marks are visible on creation, causing the chart doesn't occupy all the area, having the right area empty.
3) tChart1.Draw() method should gets System.Drawing.Graphics as a parameter, so I cannot invoke it after creating the chart.
Can you assist?
Thanks
Elad
Posted: Wed Mar 18, 2009 12:53 pm
by 10050769
Hi Edal,
Please, could you send us a simple example project we can run "as-is" to reproduce the problem here?
You can either post your files at news://
www.steema.net/steema.public.attachments newsgroup or at our
upload page
Thanks,
File uploaded
Posted: Thu Mar 19, 2009 8:44 am
by 9092401
Hey Sandra,
I've uploaded the file, it is named "TChartSample.zip"
I added info in 1.txt file
Thanks
Elad
Posted: Fri Mar 20, 2009 3:38 pm
by narcis
Hi Elad,
Thanks for the example project. Compiling it with latest TeeChart for .NET v3 release available at the client area we could use tChart1.Draw() method. Could you please check if this solves the problem at your end? If it doesn't which is the exact problem you are having with marks positioning?
Thanks in advance.
Posted: Sun Mar 22, 2009 6:09 am
by 9092401
Thanks Narcis,
I will check the .Net V3.
Can you please also check regarding my two other questions, especially the reason the chart doesn't fill the entire tChart area becuase of the original marks position?
Thanks again
Elad
Posted: Mon Mar 23, 2009 2:47 pm
by narcis
Hi Elad,
Sure! Find below the answers to your questions:
2. Below you'll find modified code which works fine with your example:
Code: Select all
public ChartForm()
{
InitializeComponent();
CreateChart();
this.Resize += new EventHandler(ChartForm_Resize);
}
void ChartForm_Resize(object sender, EventArgs e)
{
tChart1.Draw();
}
private bool CreateChart()
{
IDictionary<string, int> valuesDict = new Dictionary<string, int>();
valuesDict.Add("opt A", 5);
valuesDict.Add("option B", 2);
valuesDict.Add("option CCC", 4);
valuesDict.Add("D", 8);
IDictionary<string, Color> colorsDict = new Dictionary<string, Color>();
colorsDict.Add("opt A", Color.AliceBlue);
colorsDict.Add("option B", Color.Chocolate);
colorsDict.Add("option CCC", Color.Gold);
colorsDict.Add("D", Color.SpringGreen);
tChart1.Dock = DockStyle.Fill;
tChart1.Series.Clear();
tChart1.Legend.Visible = false;
foreach (KeyValuePair<string, int> status in valuesDict)
{
// if there are no requirement with this status, don't add a series
// (if its in the end of the bar, its color is shown)
if (status.Value > 0)
{
HorizBar bar = new HorizBar(tChart1.Chart);
bar.MultiBar = MultiBars.Stacked;
bar.Cursor = Cursors.Hand;
bar.BarHeightPercent = 100;
bar.DepthPercent = 50;
bar.Marks.Visible = true; // 12345 false;
bar.Color = colorsDict[status.Key];
bar.Add(status.Value, status.Key);
bar.Title = string.Format("{0} {1}", status.Value, status.Key);
}
}
tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);
tChart1.Draw();
return true;
}
private void RepositionChartMarks(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
HorizBar series = null;
Steema.TeeChart.Styles.SeriesMarks.Position pos = new SeriesMarks.Position();
Steema.TeeChart.Styles.SeriesMarks.Position oldPos;
for (int i = 0; i < tChart1.Series.Count; i++)
{
series = (HorizBar)tChart1[i];
series.Chart.AutoRepaint = false;
series.Marks.Arrow.Width = 1;
series.Marks.Arrow.Color = System.Drawing.Color.Black;
oldPos = pos;
pos = series.Marks.Positions[0];
pos.Custom = true;
pos.LeftTop.X = series.BarBounds.Left + series.BarBounds.Width / 2 - pos.Width / 2;
pos.ArrowTo.X = pos.LeftTop.X + pos.Width / 2;
pos.ArrowFrom.X = pos.ArrowTo.X;
int tmp = Convert.ToInt32(series.BarBounds.Height / 3);
if (i % 2 == 1)
{
pos.ArrowFrom.Y = series.BarBounds.Bottom;
pos.LeftTop.Y = pos.ArrowFrom.Y + tmp;
}
else
{
pos.ArrowFrom.Y = series.BarBounds.Top;
pos.LeftTop.Y = pos.ArrowFrom.Y - tmp;
}
pos.ArrowTo.Y = pos.LeftTop.Y;
}
series.Chart.AutoRepaint = true;
series.Chart.Invalidate();
}
3. In v3 you can use it as can be seen in the code above. In v2 you can do this:
Posted: Tue Mar 24, 2009 2:47 pm
by 9092401
Thanks, it works great.
only problem I have is a empty space in the right of the chart, see attached image:
Instead of the chart taking the entire chart area width, it is behaving as if the default marks were in their default places thus reducing the actual bars width.
I tried changing the custom width but had no luck.
Any advice?
Thanks in advance
Elad
Posted: Tue Mar 24, 2009 4:17 pm
by narcis
Hi Elad,
In that case I'd use Annotation tools instead of series marks:
Code: Select all
public ChartForm()
{
InitializeComponent();
CreateChart();
this.Resize += new EventHandler(ChartForm_Resize);
}
void ChartForm_Resize(object sender, EventArgs e)
{
tChart1.Draw();
}
private Steema.TeeChart.Tools.Annotation[] annotations;
private bool CreateChart()
{
IDictionary<string, int> valuesDict = new Dictionary<string, int>();
valuesDict.Add("opt A", 5);
valuesDict.Add("option B", 2);
valuesDict.Add("option CCC", 4);
valuesDict.Add("D", 8);
IDictionary<string, Color> colorsDict = new Dictionary<string, Color>();
colorsDict.Add("opt A", Color.AliceBlue);
colorsDict.Add("option B", Color.Chocolate);
colorsDict.Add("option CCC", Color.Gold);
colorsDict.Add("D", Color.SpringGreen);
tChart1.Dock = DockStyle.Fill;
tChart1.Series.Clear();
tChart1.Legend.Visible = false;
foreach (KeyValuePair<string, int> status in valuesDict)
{
// if there are no requirement with this status, don't add a series
// (if its in the end of the bar, its color is shown)
if (status.Value > 0)
{
HorizBar bar = new HorizBar(tChart1.Chart);
bar.MultiBar = MultiBars.Stacked;
bar.Cursor = Cursors.Hand;
bar.BarHeightPercent = 100;
bar.DepthPercent = 50;
bar.Marks.Visible = false; // 12345 false;
bar.Color = colorsDict[status.Key];
bar.Add(status.Value, status.Key);
bar.Title = string.Format("{0} {1}", status.Value, status.Key);
}
}
annotations = new Steema.TeeChart.Tools.Annotation[tChart1.Series.Count];
for (int i = 0; i < tChart1.Series.Count; i++)
{
annotations[i] = new Steema.TeeChart.Tools.Annotation(tChart1.Chart);
annotations[i].Text = tChart1[i].Labels[0];
annotations[i].Callout.Arrow.Visible = true;
annotations[i].Callout.Arrow.Color = Color.Black;
annotations[i].Callout.Arrow.Width = 1;
}
tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);
tChart1.Draw();
return true;
}
private void RepositionChartMarks(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
HorizBar series = null;
Steema.TeeChart.Tools.Annotation a;
for (int i = 0; i < tChart1.Series.Count; i++)
{
series = (HorizBar)tChart1[i];
a = annotations[i];
a.Shape.CustomPosition = true;
a.Shape.Left = series.BarBounds.Left + series.BarBounds.Width / 2 - a.Width / 2;
a.Callout.XPosition = a.Shape.Left + a.Width / 2;
int tmp = Convert.ToInt32(series.BarBounds.Height / 3);
if (i % 2 == 1)
{
a.Callout.YPosition = series.BarBounds.Bottom;
a.Shape.Top = a.Callout.YPosition + tmp;
}
else
{
a.Callout.YPosition = series.BarBounds.Top;
a.Shape.Top = a.Callout.YPosition - tmp;
}
}
}
Posted: Wed Mar 25, 2009 11:32 am
by 9092401
Thanks a lot for all your help