C# 图表:在时间图中将布尔标志显示为填充矩形(而不是直线)

C# 图表:在时间图中将布尔标志显示为填充矩形(而不是直线),c#,winforms,charts,flags,C#,Winforms,Charts,Flags,我在WinForms中使用C#图表,使用“线”图表类型实时绘制各种变量。这对于模拟值很有效,但对于开/关标志来说并不理想。 我想将多个标志绘制为水平条,当值为“1”时填充,当值为“0”时清除。 在我从头开始编写解决方案之前,您对我如何利用“图表”对象的任何特性来更有效地实现这一点有何建议 编辑:我正在玩区域类型,它似乎很有前途。 编辑2:这不起作用,因为区域类型中的区域总是从图表的底部开始,隐藏其他行。我现在正在尝试范围列类型,有几种方法可以解决这个问题。StackedBars,AreaCh

我在WinForms中使用C#图表,使用“线”图表类型实时绘制各种变量。这对于模拟值很有效,但对于开/关标志来说并不理想。

我想将多个标志绘制为水平条,当值为“1”时填充,当值为“0”时清除。

在我从头开始编写解决方案之前,您对我如何利用“图表”对象的任何特性来更有效地实现这一点有何建议

编辑:我正在玩区域类型,它似乎很有前途。
编辑2:这不起作用,因为区域类型中的区域总是从图表的底部开始,隐藏其他行。我现在正在尝试范围列类型,有几种方法可以解决这个问题。
StackedBars
AreaChart
注释
,但我认为最简单的方法是使用
LineChartType

第一个问题是:如何创建间隙?最简单的方法是将它们绘制为线,但使用
颜色。透明
。因此,我们不使用标志值作为y值,而是使用它来设置颜色

所以我们可以使用这样的函数:

void AddFlagLine(Chart chart, int series, int flag, int x)
{
    Series s = chart.Series[series];
    int px = s.Points.AddXY(x, series);
    s.Points[px].Color = s.Color;
    if (px > 0) s.Points[px - 1].Color = flag == 1 ? s.Color : Color.Transparent;
}
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
    Graphics g = e.ChartGraphics.Graphics;
    Axis ax = chart.ChartAreas[0].AxisX;
    Axis ay = chart.ChartAreas[0].AxisY;

    for (int si = 0; si < chart.Series.Count; si++ )
    {
        Series s = chart.Series[si];
        for (int pi = 1; pi < s.Points.Count - 1; pi++)
        {
            DataPoint dp = s.Points[pi];
            int y = (int) ay.ValueToPixelPosition(dp.YValues[0]+1);       ///*1*
            int x0 = (int)ax.ValueToPixelPosition(ax.Minimum);
            int x1 = (int)ax.ValueToPixelPosition(s.Points[pi-1].XValue); ///*2*
            int x2 = (int)ax.ValueToPixelPosition(dp.XValue);
            x1 = Math.Max(x1, x0);
            x2 = Math.Max(x2, x0);

            using (Pen pen = new Pen(dp.Color, 40)                        ///*3*
            { StartCap = System.Drawing.Drawing2D.LineCap.Flat,
                EndCap = System.Drawing.Drawing2D.LineCap.Flat })
            {
                g.DrawLine(pen, x1, y, x2, y);
            }
        }
    }
它采用
系列的索引
,并使用
标志
确定颜色;请注意,线段的颜色由端点的颜色控制

因此,如果您想让线从新点开始,以获得其标志颜色,则需要在添加下一个时设置它

这很简单,对于厚度为1-10的线条来说效果很好。但是如果你想要更大的宽度,事情会变得有点难看

圆顶开始变得越来越大,直到它们真正接触,或多或少地缩小了间隙

不幸的是,似乎无法控制线条的大写样式。有许多样式,包括
DashStyles
,但不是这一个。因此,我们必须求助于所有者绘图。这对于折线图来说相当简单。以下是一个示例:

xxxPaint事件如下所示:

void AddFlagLine(Chart chart, int series, int flag, int x)
{
    Series s = chart.Series[series];
    int px = s.Points.AddXY(x, series);
    s.Points[px].Color = s.Color;
    if (px > 0) s.Points[px - 1].Color = flag == 1 ? s.Color : Color.Transparent;
}
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
    Graphics g = e.ChartGraphics.Graphics;
    Axis ax = chart.ChartAreas[0].AxisX;
    Axis ay = chart.ChartAreas[0].AxisY;

    for (int si = 0; si < chart.Series.Count; si++ )
    {
        Series s = chart.Series[si];
        for (int pi = 1; pi < s.Points.Count - 1; pi++)
        {
            DataPoint dp = s.Points[pi];
            int y = (int) ay.ValueToPixelPosition(dp.YValues[0]+1);       ///*1*
            int x0 = (int)ax.ValueToPixelPosition(ax.Minimum);
            int x1 = (int)ax.ValueToPixelPosition(s.Points[pi-1].XValue); ///*2*
            int x2 = (int)ax.ValueToPixelPosition(dp.XValue);
            x1 = Math.Max(x1, x0);
            x2 = Math.Max(x2, x0);

            using (Pen pen = new Pen(dp.Color, 40)                        ///*3*
            { StartCap = System.Drawing.Drawing2D.LineCap.Flat,
                EndCap = System.Drawing.Drawing2D.LineCap.Flat })
            {
                g.DrawLine(pen, x1, y, x2, y);
            }
        }
    }
private void chart_PostPaint(对象发送方,ChartPaintEventArgs e)
{
图形g=e.ChartGraphics.Graphics;
Axis ax=图表。图表区域[0]。AxisX;
ay轴=图表。图表区域[0]。Axis;
对于(int-si=0;si
请注意:

  • 1:我已经决定将序列上移1;这取决于您是否使用或关闭y轴标签,或者是否用自定义标签替换它们

  • 2:这里我们使用上一点的x位置

  • 3:请注意,与其硬编码40像素的宽度,您实际上应该决定计算的宽度。这是一个几乎填满该区域的示例:

    int宽度=(int)((Y.值像素位置(Y.最小值)- ay.ValueToPixelPosition(ay.Maximum))/(chart7.Series.Count+2)

您可以通过添加小于或大于2的值来填充更多或更少


我已经将所有的
边框宽度
都改为
0
,所以只有画好的线条才能显示出来。

有几种方法可以解决这个问题。
堆叠条形图
面积图
注释
,但我认为目前为止最简单的方法是使用
线形图类型

第一个问题是:如何创建间隙?最简单的方法是将它们绘制为线,但使用
颜色。透明
。因此,我们不使用标志值作为y值,而是使用它来设置颜色

所以我们可以使用这样的函数:

void AddFlagLine(Chart chart, int series, int flag, int x)
{
    Series s = chart.Series[series];
    int px = s.Points.AddXY(x, series);
    s.Points[px].Color = s.Color;
    if (px > 0) s.Points[px - 1].Color = flag == 1 ? s.Color : Color.Transparent;
}
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
    Graphics g = e.ChartGraphics.Graphics;
    Axis ax = chart.ChartAreas[0].AxisX;
    Axis ay = chart.ChartAreas[0].AxisY;

    for (int si = 0; si < chart.Series.Count; si++ )
    {
        Series s = chart.Series[si];
        for (int pi = 1; pi < s.Points.Count - 1; pi++)
        {
            DataPoint dp = s.Points[pi];
            int y = (int) ay.ValueToPixelPosition(dp.YValues[0]+1);       ///*1*
            int x0 = (int)ax.ValueToPixelPosition(ax.Minimum);
            int x1 = (int)ax.ValueToPixelPosition(s.Points[pi-1].XValue); ///*2*
            int x2 = (int)ax.ValueToPixelPosition(dp.XValue);
            x1 = Math.Max(x1, x0);
            x2 = Math.Max(x2, x0);

            using (Pen pen = new Pen(dp.Color, 40)                        ///*3*
            { StartCap = System.Drawing.Drawing2D.LineCap.Flat,
                EndCap = System.Drawing.Drawing2D.LineCap.Flat })
            {
                g.DrawLine(pen, x1, y, x2, y);
            }
        }
    }
它采用
系列的索引
,并使用
标志
确定颜色;请注意,线段的颜色由端点的颜色控制

因此,如果您想让线从新点开始,以获得其标志颜色,则需要在添加下一个时设置它

这很简单,对于厚度为1-10的线条来说效果很好。但是如果你想要更大的宽度,事情会变得有点难看

圆顶开始变得越来越大,直到它们真正接触,或多或少地缩小了间隙

不幸的是,似乎无法控制线条的大写样式。有许多样式,包括
DashStyles
,但不是这一个。因此,我们必须求助于所有者绘图。这对于折线图来说相当简单。以下是一个示例:

xxxPaint事件如下所示:

void AddFlagLine(Chart chart, int series, int flag, int x)
{
    Series s = chart.Series[series];
    int px = s.Points.AddXY(x, series);
    s.Points[px].Color = s.Color;
    if (px > 0) s.Points[px - 1].Color = flag == 1 ? s.Color : Color.Transparent;
}
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
    Graphics g = e.ChartGraphics.Graphics;
    Axis ax = chart.ChartAreas[0].AxisX;
    Axis ay = chart.ChartAreas[0].AxisY;

    for (int si = 0; si < chart.Series.Count; si++ )
    {
        Series s = chart.Series[si];
        for (int pi = 1; pi < s.Points.Count - 1; pi++)
        {
            DataPoint dp = s.Points[pi];
            int y = (int) ay.ValueToPixelPosition(dp.YValues[0]+1);       ///*1*
            int x0 = (int)ax.ValueToPixelPosition(ax.Minimum);
            int x1 = (int)ax.ValueToPixelPosition(s.Points[pi-1].XValue); ///*2*
            int x2 = (int)ax.ValueToPixelPosition(dp.XValue);
            x1 = Math.Max(x1, x0);
            x2 = Math.Max(x2, x0);

            using (Pen pen = new Pen(dp.Color, 40)                        ///*3*
            { StartCap = System.Drawing.Drawing2D.LineCap.Flat,
                EndCap = System.Drawing.Drawing2D.LineCap.Flat })
            {
                g.DrawLine(pen, x1, y, x2, y);
            }
        }
    }
private void chart_PostPaint(对象发送方,ChartPaintEventArgs e)
{
图形g=e.ChartGraphics.Graphics;
Axis ax=图表。图表区域[0]。AxisX;
ay轴=图表。图表区域[0]。Axis;
对于(int-si=0;si