我遇到了一个小问题",我想创建一个如下图表:
所以基本上 系列1 =正常条形图。如果它在" time max"之前结束,则显示绿色。 (series2)Series 2 =系列1项目之上的DataPoint / Marker。
我正在努力解决这个问题......
我的代码:
MPI_Irecv
但这仅显示第一个系列的第二个系列,但第一个系列不再可见。系列2的制作者没有显示,但是栏是(尽管我将边界宽度设为0)。在我看来/我认为我只需要制作" bar" 2系列看不见,只显示系列2的标记点。
有什么想法吗?
更新
chart_TimeChart.Series.Clear();
string series_timeneeded = "Time Needed";
chart_TimeChart.Series.Add(series_timeneeded);
chart_TimeChart.Series[series_timeneeded]["PixelPointWidth"] = "5";
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Size = 10;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = true;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Enabled = true;
chart_TimeChart.Series[series_timeneeded].BorderWidth = 2;
chart_TimeChart.Series[series_timeneeded].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_timeneeded].YValueType = ChartValueType.Time;
chart_TimeChart.ChartAreas[0].AxisY.LabelStyle.Format = "HH:mm:ss";
chart_TimeChart.Series[series_timeneeded].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
chart_TimeChart.Series[series_timeneeded].Points.AddXY("item"+ " " + (i + 1).ToString(), DateTime.Now.Add(Timespans[i]));
}
chart_TimeChart.Series.Add(series_FinishTime);
chart_TimeChart.Series[series_FinishTime].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_FinishTime].BorderWidth = 0;
chart_TimeChart.Series[series_FinishTime].MarkerSize = 15;
chart_TimeChart.Series[series_FinishTime].MarkerStyle = MarkerStyle.Square;
chart_TimeChart.Series[series_FinishTime].MarkerColor = Color.Black;
chart_TimeChart.Series[series_FinishTime].YValueType = ChartValueType.DateTime;
chart_TimeChart.Series[series_FinishTime].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
DateTime YPosition = GetFinishTime(i);
chart_TimeChart.Series[series_FinishTime].Points.AddXY("item"+ " " +(i+1).ToString(), YPosition);
}
代码将显示为:
但我希望它看起来像这样:
答案 0 :(得分:3)
<强> !!请参阅下面的更新!!
如果您真的想要创建StckedBar图表,那么您的图表会出现两个问题:
你添加字符串,看起来很好,但根本不起作用。这是因为DataPoint.XValue
字段为double
,当您将string
添加到其中时,它会设置为0
!!您的字符串将复制到Label
,但会丢失。
所以需要来提供适用于x值的数字值。
StackedGroupName
的特殊属性,用于对应堆叠的系列进行分组。以下是如何使用它:
yourSeries1.SetCustomProperty("StackedGroupName", "Group1");
有关完整示例,请参阅this post!
它还显示了一种使用您选择的字符串值设置标签的方法..
这是实际StackedBar
图表的方法。您的解决方法可能有效,也可能无效。您可以尝试使颜色透明或等于图表的背景颜色;但它不会只是一个黑客,imo。
<强>更新强>
我想我误解了这个问题。从我看到你真的不想创建堆积图表。
相反,你要解决这些问题:
让我们解决每个问题:
Bars
,Columns
,然后有些列有一些名为DrawSideBySide
的特殊属性。默认设置为Auto
,其效果与True
相同。这通常很好,因为我们不希望条形图相互叠加,有效地隐藏了全部或部分重叠点。
但是我们确实希望他们共享相同的y位置,因此我们需要将属性设置为false
至少一个Series
;其他人(Auto
)将跟随..:
你可以这样做:
aSeries["DrawSideBySide"] = "false";
或者像这样:
aSeries.SetCustomProperty("DrawSideBySide", "false");
Series
;这很简单:aSeries.Color = Color.Transparent;
MarkerStyle
,所以我们需要使用自定义样式。为此,我们需要创建一个合适的位图,并将其作为NamedImage
添加到图表的Images
集合中。听起来比这复杂得多;但是MarkerImage
不会缩放,所以每当我们调整图表大小或添加/删除点时,我们都需要创建合适的大小。我暂时不理会这个并发症。
int pointCount = 10;
Bitmap bmp = new Bitmap(2, chart.ClientSize.Height / pointCount - 5);
using (Graphics g = Graphics.FromImage(bmp)) g.Clear(Color.Black);
NamedImage marker = new NamedImage("marker", bmp);
chart.Images.Clear(); // quick & dirty
chart.Images.Add(marker);
结果如下:
一些注意事项:
我建议对所有重复引用的图表元素使用变量,而不是一直使用索引引用。代码更少,更易于阅读,更易于维护,可能性能更佳。
由于您的代码要求可见数据点为红色或绿色,Legend
将无法显示良好的表示形式。有关绘制多色图例项的示例,请参阅here。
我使用了图表高度;建议不要这样做,因为可能有Titles
或Legends
或更多ChartAreas
;相反,你应该使用ChartArea
的高度,或更精确的InnerPlotPosition
的高度。您需要将百分比转换为像素。不太难,请参阅下文或here
或here了解更多示例!
标记应根据Resize
和AxisViewChanged
事件进行调整。把它放在一个很好的函数中(例如void setMarkerImage(Chart chart, Series s, string name, int width, Color c)
)总是一个好主意。
如果您需要重复调整标记图像的大小,您可能需要编写更好的代码来清除旧标记;这应该包括处理之前使用的Bitmap
..
以下是一个例子:
var oldni = chart.Images.FindByName("marker");
if (oldni != null)
{
oldni.Image.Dispose();
chart.Images.Remove(oldni);
oldni.Dispose();
}
RecalculateAxesScale
就是这样一个推动。计算合适标记高度的示例:
ChartArea ca = chart.ChartAreas[0];
ca.RecalculateAxesScale();
float cah = ca.Position.Height;
float iph = ca.InnerPlotPosition.Height;
float h = chart3.ClientSize.Height * cah / 100f * iph / 100f;
int mh = (int)(h / s.Points.Count);
(因为我们有Bars
x值沿垂直轴移动,反之亦然。)