c# - 如何根据图表栏大小更改 DataPoint 标签的颜色?
问题描述
System.Windows.Forms.DataVisualiation.Charting
我用 ChartType Bar添加了一个新的图表控件 ( )。根据要求,标签文本必须为白色并进入条形值。因此,我将BarLabelStyle=Right
对象设置为白色,并将其CustomProperties
设置为白色。请参阅下面的图片。DataPoint
LabelForeColor
第二个灰色条中的标签正确显示。
相反,第一个栏太小,白色文本显示在右侧但不可见。
但是,当条形太短时,标签文本位于条形之外,使用白色无法看到文本。有没有办法检查标签文本何时绘制在条形值之外,以便我可以更改颜色(例如黑色)?
谢谢。
解决方案
不幸MCChart
的是,几乎没有动态表达式的能力。
要解决您的问题,您可以..:
ForeColor
根据您的 y 值编码DataPoints
。无论是在您添加它们时,还是在循环所有点的函数中,无论何时调用它.. - 根据字体、轴范围和标签文本,这可能是您必须确定的一些阈值。
例子:
int p = yourSeries.Points.AddXY(...);
yourSeries.Points[p].LabelForeColor = yourSeries.Points[p].YValues[0] < threshold ?
Color.Black : Color.White;
- 或者你可以作弊一点;-)
您可以将 设置LabelBackColor
为与 相同的颜色Series
,即条形本身。以下是如何做到这一点:
要访问Series.Color
我们必须调用:
chart.ApplyPaletteColors();
现在我们可以设置
yourSeries.LabelForeColor = Color.White;
yourSeries.LabelBackColor = yourSeries.Color;
例子:
更新:
由于您不能使用作弊,因此您必须设置颜色。
挑战在于知道每个标签的文本需要多少空间与条有多少空间。前者可以测量 ( TextRenderer.MeasureString()
),后者可以从 y 轴 ( Axis.ValueToPixelPosition()
) 中提取。
这是执行此操作的功能;它比我希望的要复杂一些,主要是因为它试图通用..
void LabelColors(Chart chart, ChartArea ca, Series s)
{
if (chart.Series.Count <= 0 || chart.Series[0].Points.Count <= 0) return;
Axis ay = ca.AxisY;
// get the maximum & minimum values
double maxyv = ay.Maximum;
if (maxyv == double.NaN) maxyv = s.Points.Max(v => v.YValues[0]);
double minyv = s.Points.Min(v => v.YValues[0]);
// get the pixel positions of the minimum
int y0x = (int)ay.ValueToPixelPosition(0);
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
// pixel position of the bar right
int vx = (int)ay.ValueToPixelPosition(dp.YValues[0]);
// now we knowe the bar's width
int barWidth = vx - y0x;
// find out what the label text actauly is
string t = dp.LabelFormat != "" ?
String.Format(dp.LabelFormat, dp.YValues[0]) : dp.YValues[0].ToString();
string text = dp.Label != "" ? dp.Label : t;
// measure the (formatted) text
SizeF rect = TextRenderer.MeasureText(text, dp.Font);
Console.WriteLine(text);
dp.LabelForeColor = barWidth < rect.Width ? Color.Black : Color.White;
}
}
我可能使获取应该显示的文本的方式过于复杂;您当然可以决定是否可以简化您的案例。
注意:您必须调用此函数..
- 每当您的数据可能发生变化时
- 仅在图表的轴完成布局后(!)
前一点很明显,后一点不明显。这意味着您不能在添加积分后立即调用该函数!相反,您必须在以后的某个地方执行此操作,否则获取条形大小所需的轴功能将不起作用。
MSDN 说它只能在PaintXXX
事件中发生;我发现所有鼠标事件也有效,然后一些..
为了省钱,我会把它放在PostPaint
事件中:
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
LabelColors(chart, chart.ChartAreas[0], chart.Series[0]);
}
推荐阅读
- python-3.x - 使用 xlrd 读取 .xlsx 文件的格式信息
- python-3.x - 如何在scrapy中刮取具有特定标题的跨度?
- c++ - 为什么在 hdc 上绘图不立即更新窗口?
- ignite - 将缓存加载到 apache ignite 失败并出现异常
- twilio - Twilio 无效的访问令牌签名 (iOS - Swift)
- database - 具有多种类型的 AWS DynamoDB 索引属性
- assembly - aarch64 中的零寄存器“zr”本质上是接地的吗?
- mongodb - MongoDB 模型上的重复键错误,即使模型没有强制该值的唯一性
- html - 仅使用 CSS 替换 img 并且不能更改 HTML
- javascript - 似乎无法获得正确的操作顺序