x 轴上自定义标签的奇怪行为
Strange behaviour with custom labels on x axis
我对 x 轴上的自定义标签有疑问。如果我添加点 [10;1][20;2][30;3][40;4][50;5][60;6][70;7][80;8][90;9] 没有标签,x 轴如下所示:
如果我用标签 [10;1;A][20;2;B][30;3;C][40;4;D][50;5;E][60;6;F][70 ;7;G][80;8;H][90;9;I] 我明白了:
如果我将分数更改为 [100;1][200;2][300;3][400;4][500;5][600;6][700;7][800;8 ][900;9] 我得到:
如果我添加标签 [100;1;A][200;2;B][300;3;C][400;4;D][500;5;E][600;6;F][700;7 ;G][800;8;H][900;9;I] 我得到:
我尝试使用 Add(double x, double y, string text)
以及 DataSource
和 LabelMember
添加带有点的标签 - 两者的结果相同。如您所见,所有数字都显示在那里应该没有问题(在这两种情况下,标签数量实际上是可见数字的一半)。
正如您所看到的,根据数字之间的实际差异,可见的标签数量也不同——如果差异为 10,则显示 2 个标签和一些刻度,但如果差异为 100,则只有第一个标签没有任何其他标签标签甚至刻度。
如果差异为 1,我可以看到所有自定义标签(在此轴宽度上)。
对于这个例子,我使用了这个代码:
var serie = new Line(tChart1.Chart);
for (var i = 1; i < 10; i++)
{
serie.Add(i * 10, i, ((char)(64 + i)).ToString()); //points with labels
//serie.Add(i * 10, i); //points without labels
}
编辑
我尝试了 GetAxisLabels
事件,但它仅针对已显示的标签触发,因此如果我想显示更多标签,我将无法更改。
我还尝试手动将标签添加到底轴,但如果标签足够宽,它们就会开始重叠,所以我尝试了 here 中的代码,经过一些修改后它起作用了。不知何故。因为,它只有在我不使用缩放功能时才有效。而且我必须使用变焦,所以这对我不利。我试着做一些更多的修改,但对于这样的东西来说,这将是非常难看的代码...
我想建议您使用自定义标签,使用 GetAxisLabels 事件或将新项目添加到底部轴。
请参阅下面的两种方法:
GetAxisLabels 事件:
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Dock = DockStyle.Fill;
Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
rnd = new Random();
for (int i = 0; i < 10; i++)
{
line1.Add(i * 10, i); //points without labels
}
tChart1.GetAxisLabel += TChart1_GetAxisLabel;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
}
private void TChart1_GetAxisLabel(object sender, Steema.TeeChart.GetAxisLabelEventArgs e)
{
if (sender == tChart1.Axes.Bottom)
{
if (e.ValueIndex != -1)
{
e.LabelText = ((char)(64 + e.ValueIndex)).ToString();
}
}
}
将项目添加到底轴:
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Dock = DockStyle.Fill;
Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
rnd = new Random();
for (int i = 0; i < 10; i++)
{
line1.Add(i * 10, i); //points without labels
}
//tChart1.GetAxisLabel += TChart1_GetAxisLabel;
tChart1.Axes.Bottom.Labels.Items.Clear();
for (int i = 0; i < line1.Count; ++i)
{
tChart1.Axes.Bottom.Labels.Items.Add(line1.XValues[i], ((char)(64 + i)).ToString());
}
}
我终于找到了适合我需要的一切的解决方案。不完全如我所愿,但不知何故......
我只需要处理底轴,所以我从 johnk 中获取代码并根据需要进行更改。
我删除了与下一个标签的比较并改变了方式,我如何找到正确的标签索引。
TeeChart
有一些不愉快的问题(例如标签使用与我预期不同的 Font
- tChart1.Graphics3D.Font
而不是 axis.Labels.Font
- e.LabelValue
总是0).所以如果你想做一些改变,请记住这些问题。下面是我的,不完美但或多或少工作的解决方案:
限制
- 仅适用于水平轴。
- 仅适用于不同的标签文本。
- 有时显示的标签与未显示的标签数量不同。
特征
- 您可以使用缩放和平移功能。
- 标签之间更大 space(两侧 +3 像素)。
- 许多标签的网格线数量较少。
代码
辅助词典
//Label index and true, if the label is visible.
private Dictionary<int, bool> _visibleLabels = new Dictionary<int, bool>();
正在重置字典
private void TChart1_BeforeDrawAxes(object sender, Graphics3D g)
{
//Clear shown labels before showing axis.
_visibleLabels.Clear();
}
选择可见标签
private void GetAxisDrawLabel(object sender, GetAxisDrawLabelEventArgs e)
{
bool overlapPrv = false;
Axis axis = (Axis)sender;
//Get the size of the label text. We have to use tcharts font, not axis font.
SizeF currentSize = tChart1.Graphics3D.MeasureString(tChart1.Graphics3D.Font, e.Text);
Rectangle currentRect = new Rectangle(e.X - 3, e.Y, (int)currentSize.Width + 6, (int)currentSize.Height);
var index = FindLabel(tChart1.Axes.Bottom.Labels.Items, e.Text);
//Get the AxisLabelItem we are trying to draw.
AxisLabelItem currentLabel = axis.Labels.Items[index];
//If we set visible to false before GetAxisDrawLabel then set e.DrawLabel to false.
if (currentLabel.Visible == false)
{
_visibleLabels.Add(index, false);
e.DrawLabel = false;
}
//Get the previous visible label.
AxisLabelItem prev = null;
var prevPair = _visibleLabels.LastOrDefault(x => x.Value == true);
var prevIndex = -1;
if (prevPair.Value)
{
prevIndex = prevPair.Key;
tChart1.Axes.Bottom.Grid.DrawEvery = index - prevIndex;
}
else
{
//Current label is the first visible label.
_visibleLabels.Add(index, true);
e.DrawLabel = true;
return;
}
if (prevIndex >= 0)
{
prev = axis.Labels.Items[prevIndex];
}
//If this axis is horizontal then the concern is the width of the label.
//If there is no previous label, we draw this one.
//TODO implementation for the vertical.
if (axis.Horizontal == true && prev != null)
{
//if previous is visible we need to see if it will overlap with the current.
if (prev.Visible == true)
{
//Get the previous labels text size.
SizeF prevSize = tChart1.Graphics3D.MeasureString(tChart1.Graphics3D.Font, prev.Text);
//Get the previous label rectangle.
Rectangle prvRect = new Rectangle(
axis.CalcXPosValue(prev.Value) - 3, e.Y, (int)prevSize.Width + 6, (int)prevSize.Height);
//Set the overlapPrv flag by checking IntersectsWith
overlapPrv = currentRect.IntersectsWith(prvRect);
}
//if any overlap or if e.DrawLabel is false set e.DrawLabel to false.
if (overlapPrv || e.DrawLabel == false)
{
_visibleLabels.Add(index, false);
e.DrawLabel = false;
}
else
{
_visibleLabels.Add(index, true);
}
}
}
找到正确的标签索引
private static int FindLabel(AxisLabelsItems items, string labelText)
{
for (var i = 0; i < items.Count; i++)
{
if (items[i].Text == labelText)
{
return i;
}
}
return -1;
}
我对 x 轴上的自定义标签有疑问。如果我添加点 [10;1][20;2][30;3][40;4][50;5][60;6][70;7][80;8][90;9] 没有标签,x 轴如下所示:
如果我用标签 [10;1;A][20;2;B][30;3;C][40;4;D][50;5;E][60;6;F][70 ;7;G][80;8;H][90;9;I] 我明白了:
如果我将分数更改为 [100;1][200;2][300;3][400;4][500;5][600;6][700;7][800;8 ][900;9] 我得到:
如果我添加标签 [100;1;A][200;2;B][300;3;C][400;4;D][500;5;E][600;6;F][700;7 ;G][800;8;H][900;9;I] 我得到:
我尝试使用 Add(double x, double y, string text)
以及 DataSource
和 LabelMember
添加带有点的标签 - 两者的结果相同。如您所见,所有数字都显示在那里应该没有问题(在这两种情况下,标签数量实际上是可见数字的一半)。
正如您所看到的,根据数字之间的实际差异,可见的标签数量也不同——如果差异为 10,则显示 2 个标签和一些刻度,但如果差异为 100,则只有第一个标签没有任何其他标签标签甚至刻度。
如果差异为 1,我可以看到所有自定义标签(在此轴宽度上)。
对于这个例子,我使用了这个代码:
var serie = new Line(tChart1.Chart);
for (var i = 1; i < 10; i++)
{
serie.Add(i * 10, i, ((char)(64 + i)).ToString()); //points with labels
//serie.Add(i * 10, i); //points without labels
}
编辑
我尝试了 GetAxisLabels
事件,但它仅针对已显示的标签触发,因此如果我想显示更多标签,我将无法更改。
我还尝试手动将标签添加到底轴,但如果标签足够宽,它们就会开始重叠,所以我尝试了 here 中的代码,经过一些修改后它起作用了。不知何故。因为,它只有在我不使用缩放功能时才有效。而且我必须使用变焦,所以这对我不利。我试着做一些更多的修改,但对于这样的东西来说,这将是非常难看的代码...
我想建议您使用自定义标签,使用 GetAxisLabels 事件或将新项目添加到底部轴。
请参阅下面的两种方法:
GetAxisLabels 事件:
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Dock = DockStyle.Fill;
Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
rnd = new Random();
for (int i = 0; i < 10; i++)
{
line1.Add(i * 10, i); //points without labels
}
tChart1.GetAxisLabel += TChart1_GetAxisLabel;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
}
private void TChart1_GetAxisLabel(object sender, Steema.TeeChart.GetAxisLabelEventArgs e)
{
if (sender == tChart1.Axes.Bottom)
{
if (e.ValueIndex != -1)
{
e.LabelText = ((char)(64 + e.ValueIndex)).ToString();
}
}
}
将项目添加到底轴:
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Dock = DockStyle.Fill;
Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
rnd = new Random();
for (int i = 0; i < 10; i++)
{
line1.Add(i * 10, i); //points without labels
}
//tChart1.GetAxisLabel += TChart1_GetAxisLabel;
tChart1.Axes.Bottom.Labels.Items.Clear();
for (int i = 0; i < line1.Count; ++i)
{
tChart1.Axes.Bottom.Labels.Items.Add(line1.XValues[i], ((char)(64 + i)).ToString());
}
}
我终于找到了适合我需要的一切的解决方案。不完全如我所愿,但不知何故......
我只需要处理底轴,所以我从 johnk 中获取代码并根据需要进行更改。
我删除了与下一个标签的比较并改变了方式,我如何找到正确的标签索引。
TeeChart
有一些不愉快的问题(例如标签使用与我预期不同的 Font
- tChart1.Graphics3D.Font
而不是 axis.Labels.Font
- e.LabelValue
总是0).所以如果你想做一些改变,请记住这些问题。下面是我的,不完美但或多或少工作的解决方案:
限制
- 仅适用于水平轴。
- 仅适用于不同的标签文本。
- 有时显示的标签与未显示的标签数量不同。
特征
- 您可以使用缩放和平移功能。
- 标签之间更大 space(两侧 +3 像素)。
- 许多标签的网格线数量较少。
代码
辅助词典
//Label index and true, if the label is visible.
private Dictionary<int, bool> _visibleLabels = new Dictionary<int, bool>();
正在重置字典
private void TChart1_BeforeDrawAxes(object sender, Graphics3D g)
{
//Clear shown labels before showing axis.
_visibleLabels.Clear();
}
选择可见标签
private void GetAxisDrawLabel(object sender, GetAxisDrawLabelEventArgs e)
{
bool overlapPrv = false;
Axis axis = (Axis)sender;
//Get the size of the label text. We have to use tcharts font, not axis font.
SizeF currentSize = tChart1.Graphics3D.MeasureString(tChart1.Graphics3D.Font, e.Text);
Rectangle currentRect = new Rectangle(e.X - 3, e.Y, (int)currentSize.Width + 6, (int)currentSize.Height);
var index = FindLabel(tChart1.Axes.Bottom.Labels.Items, e.Text);
//Get the AxisLabelItem we are trying to draw.
AxisLabelItem currentLabel = axis.Labels.Items[index];
//If we set visible to false before GetAxisDrawLabel then set e.DrawLabel to false.
if (currentLabel.Visible == false)
{
_visibleLabels.Add(index, false);
e.DrawLabel = false;
}
//Get the previous visible label.
AxisLabelItem prev = null;
var prevPair = _visibleLabels.LastOrDefault(x => x.Value == true);
var prevIndex = -1;
if (prevPair.Value)
{
prevIndex = prevPair.Key;
tChart1.Axes.Bottom.Grid.DrawEvery = index - prevIndex;
}
else
{
//Current label is the first visible label.
_visibleLabels.Add(index, true);
e.DrawLabel = true;
return;
}
if (prevIndex >= 0)
{
prev = axis.Labels.Items[prevIndex];
}
//If this axis is horizontal then the concern is the width of the label.
//If there is no previous label, we draw this one.
//TODO implementation for the vertical.
if (axis.Horizontal == true && prev != null)
{
//if previous is visible we need to see if it will overlap with the current.
if (prev.Visible == true)
{
//Get the previous labels text size.
SizeF prevSize = tChart1.Graphics3D.MeasureString(tChart1.Graphics3D.Font, prev.Text);
//Get the previous label rectangle.
Rectangle prvRect = new Rectangle(
axis.CalcXPosValue(prev.Value) - 3, e.Y, (int)prevSize.Width + 6, (int)prevSize.Height);
//Set the overlapPrv flag by checking IntersectsWith
overlapPrv = currentRect.IntersectsWith(prvRect);
}
//if any overlap or if e.DrawLabel is false set e.DrawLabel to false.
if (overlapPrv || e.DrawLabel == false)
{
_visibleLabels.Add(index, false);
e.DrawLabel = false;
}
else
{
_visibleLabels.Add(index, true);
}
}
}
找到正确的标签索引
private static int FindLabel(AxisLabelsItems items, string labelText)
{
for (var i = 0; i < items.Count; i++)
{
if (items[i].Text == labelText)
{
return i;
}
}
return -1;
}