对齐左右垂直轴
Align left and right vertical axes
我有一个线系列连接到左边的垂直轴,另一个连接到右边的垂直轴。如何在两个轴上对齐 Ticks
和 Grids
?
原始状态:
如您所见,垂直轴的网格线位于不同的位置。我想如果我在两边设置相同数量的刻度,它可以对齐网格。我使用此代码:
private void AlignAxes()
{
if (tChart1.Axes.Left.CalcIncrement != 0)
{
var ticksNum = (tChart1.Axes.Left.Maximum - tChart1.Axes.Left.Minimum) /
tChart1.Axes.Left.CalcIncrement;
tChart1.Axes.Right.Increment =
(tChart1.Axes.Right.Maximum - tChart1.Axes.Right.Minimum) / ticksNum;
}
}
但它没有按预期工作:
我想要这样的东西:
但显然具有正确计算和对齐的值。
解释:
我尝试了几乎所有可以想象到的方法并找到了解决方案(尽我所能)。结果至少对我来说已经足够好了。
我尝试的每项计算都不是 100% 有效。如果标签是自动创建的,则 Axis.Labels.Items
没有项目。最后我发现有名字为 labelPos
的 private ArrayList
并且在标签应该去的地方有矩形。所以我必须使用 System.Reflection
来获取这个列表。然后从这个矩形的位置计算另一个 y 轴上的值并将它们作为自定义标签插入。
代码:
private bool _redrawAgain = false;
private void AlignAxes()
{
if (_redrawAgain)
{
_redrawAgain = false;
}
else
{
_redrawAgain = true;
var tmpl = new AxisLabels(tChart1.Axes.Left);
var privateField = tmpl.GetType().GetField("labelPos",
BindingFlags.NonPublic | BindingFlags.Instance);
var labelPos = (ArrayList)privateField.GetValue(tChart1.Axes.Left.Labels);
tChart1.Axes.Right.Labels.Items.Clear();
for (var i = 0; i < labelPos.Count; i++)
{
var rect = (Rectangle)labelPos[i];
tChart1.Axes.Right.Labels.Items.Add(
tChart1.Axes.Right.CalcPosPoint(rect.Y + (rect.Height / 2)));
}
tChart1.Axes.Right.Grid.DrawEvery = tChart1.Axes.Left.Grid.DrawEvery;
tChart1.Refresh();
}
}
我从 TChart.AfterDraw
事件中调用 AlignAxes();
,所以我必须再次刷新图表,但如果不从我尝试过的任何图表事件中刷新,我就无法正常工作。
此代码在运行时切换轴时也有效,即使左轴上没有任何内容,因为它只是从右轴清除自定义标签并让库关心标签。
结果:
我唯一没能解决的是 MinimumOffset
和 MaximumOffset
,但我认为它在 TeeChart 库中被破坏了。我将两个轴上的两个偏移量都设置为 10,并且在显示图表时它们会正确显示,但是在缩放或滚动后,右轴上的标签会随着偏移量消失而左轴上的标签会消失,就好像有偏移量一样设置为 0。您可以在 x 轴附近的两个 y 轴上的图像上看到这种奇怪的行为 - 在左轴上有标签的直线上,右轴上没有标签。
更新:
我也想要轴标题,所以我不得不像这样更新代码:
private void AlignAxes(Graphics3D g)
{
if (_redrawAgain)
{
_redrawAgain = false;
}
else
{
_redrawAgain = true;
var tmpl = new AxisLabels(tChart1.Axes.Left);
var privateField = tmpl.GetType().GetField("labelPos",
BindingFlags.NonPublic | BindingFlags.Instance);
var labels = (ArrayList)privateField.GetValue(tChart1.Axes.Left.Labels);
tChart1.Axes.Right.Labels.Items.Clear();
var gratestWidth = 0;
for (var i = 0; i < labels.Count; i++)
{
var rect = (Rectangle)labels[i];
tChart1.Axes.Right.Labels.Items.Add(
tChart1.Axes.Right.CalcPosPoint(rect.Y + (rect.Height / 2)));
var width = g.MeasureString(tChart1.Axes.Right.Labels.Font,
tChart1.Axes.Right.Labels.Items
[tChart1.Axes.Right.Labels.Items.Count - 1].
Value.ToString(
tChart1.Axes.Right.Labels.ValueFormat)).
ToSize().Width;
if (width > gratestWidth)
{
gratestWidth = width;
}
}
if (labels.Count > 0)
{
tChart1.Axes.Right.Labels.CustomSize = gratestWidth + 10;
}
else
{
tChart1.Axes.Right.Labels.CustomSize = 0;
}
tChart1.Axes.Right.Grid.DrawEvery = tChart1.Axes.Left.Grid.DrawEvery;
tChart1.Refresh();
}
}
我不得不自己计算标签的宽度,否则会再次刷新图表。
我有一个线系列连接到左边的垂直轴,另一个连接到右边的垂直轴。如何在两个轴上对齐 Ticks
和 Grids
?
原始状态:
如您所见,垂直轴的网格线位于不同的位置。我想如果我在两边设置相同数量的刻度,它可以对齐网格。我使用此代码:
private void AlignAxes()
{
if (tChart1.Axes.Left.CalcIncrement != 0)
{
var ticksNum = (tChart1.Axes.Left.Maximum - tChart1.Axes.Left.Minimum) /
tChart1.Axes.Left.CalcIncrement;
tChart1.Axes.Right.Increment =
(tChart1.Axes.Right.Maximum - tChart1.Axes.Right.Minimum) / ticksNum;
}
}
但它没有按预期工作:
我想要这样的东西:
但显然具有正确计算和对齐的值。
解释:
我尝试了几乎所有可以想象到的方法并找到了解决方案(尽我所能)。结果至少对我来说已经足够好了。
我尝试的每项计算都不是 100% 有效。如果标签是自动创建的,则 Axis.Labels.Items
没有项目。最后我发现有名字为 labelPos
的 private ArrayList
并且在标签应该去的地方有矩形。所以我必须使用 System.Reflection
来获取这个列表。然后从这个矩形的位置计算另一个 y 轴上的值并将它们作为自定义标签插入。
代码:
private bool _redrawAgain = false;
private void AlignAxes()
{
if (_redrawAgain)
{
_redrawAgain = false;
}
else
{
_redrawAgain = true;
var tmpl = new AxisLabels(tChart1.Axes.Left);
var privateField = tmpl.GetType().GetField("labelPos",
BindingFlags.NonPublic | BindingFlags.Instance);
var labelPos = (ArrayList)privateField.GetValue(tChart1.Axes.Left.Labels);
tChart1.Axes.Right.Labels.Items.Clear();
for (var i = 0; i < labelPos.Count; i++)
{
var rect = (Rectangle)labelPos[i];
tChart1.Axes.Right.Labels.Items.Add(
tChart1.Axes.Right.CalcPosPoint(rect.Y + (rect.Height / 2)));
}
tChart1.Axes.Right.Grid.DrawEvery = tChart1.Axes.Left.Grid.DrawEvery;
tChart1.Refresh();
}
}
我从 TChart.AfterDraw
事件中调用 AlignAxes();
,所以我必须再次刷新图表,但如果不从我尝试过的任何图表事件中刷新,我就无法正常工作。
此代码在运行时切换轴时也有效,即使左轴上没有任何内容,因为它只是从右轴清除自定义标签并让库关心标签。
结果:
我唯一没能解决的是 MinimumOffset
和 MaximumOffset
,但我认为它在 TeeChart 库中被破坏了。我将两个轴上的两个偏移量都设置为 10,并且在显示图表时它们会正确显示,但是在缩放或滚动后,右轴上的标签会随着偏移量消失而左轴上的标签会消失,就好像有偏移量一样设置为 0。您可以在 x 轴附近的两个 y 轴上的图像上看到这种奇怪的行为 - 在左轴上有标签的直线上,右轴上没有标签。
更新:
我也想要轴标题,所以我不得不像这样更新代码:
private void AlignAxes(Graphics3D g)
{
if (_redrawAgain)
{
_redrawAgain = false;
}
else
{
_redrawAgain = true;
var tmpl = new AxisLabels(tChart1.Axes.Left);
var privateField = tmpl.GetType().GetField("labelPos",
BindingFlags.NonPublic | BindingFlags.Instance);
var labels = (ArrayList)privateField.GetValue(tChart1.Axes.Left.Labels);
tChart1.Axes.Right.Labels.Items.Clear();
var gratestWidth = 0;
for (var i = 0; i < labels.Count; i++)
{
var rect = (Rectangle)labels[i];
tChart1.Axes.Right.Labels.Items.Add(
tChart1.Axes.Right.CalcPosPoint(rect.Y + (rect.Height / 2)));
var width = g.MeasureString(tChart1.Axes.Right.Labels.Font,
tChart1.Axes.Right.Labels.Items
[tChart1.Axes.Right.Labels.Items.Count - 1].
Value.ToString(
tChart1.Axes.Right.Labels.ValueFormat)).
ToSize().Width;
if (width > gratestWidth)
{
gratestWidth = width;
}
}
if (labels.Count > 0)
{
tChart1.Axes.Right.Labels.CustomSize = gratestWidth + 10;
}
else
{
tChart1.Axes.Right.Labels.CustomSize = 0;
}
tChart1.Axes.Right.Grid.DrawEvery = tChart1.Axes.Left.Grid.DrawEvery;
tChart1.Refresh();
}
}
我不得不自己计算标签的宽度,否则会再次刷新图表。