请大家原谅我的无知,因为我最近才开始使用 C#。我只是有一个关于 Windows 图表控件的问题,因为我遇到了一个相当愚蠢的问题。
我有一个程序,其中有一些报告,其中包括漂亮的窗口图表来表示一些数据。但是,我一直将这些图表保存到文件中以供各种用途,只需使用类似这样的东西:
chart2.SaveImage(保存文件名, ChartImageFormat.Png);
我的第一个问题在于,我不确定如何将其保存为更高分辨率,而不在保存之前先增加图表控件的大小。如果能有一个质量合理的图像就好了。
第二个问题是当我确实增加图表控件的大小时,可用的操作似乎只能增加实际图表的大小,而不能增加标签或文本的大小。如果我可以手动更改所有这些,这将不是问题,这就是我对条形图所做的,但有一条线我无法弄清楚如何使其变粗:饼图上的标签线。我在下图中画了一个箭头:
http://www.bolinger.ca/chart.png
因此,当图表增加到合理的分辨率时,由于没有增加到适当的相对大小,这条线几乎看不见。我觉得应该有办法改变它,但不知道会是什么。
再次请原谅我的无知。如果这两个问题中的任何一个都能得到解决,那么我就可以高枕无忧了,因为我知道这些饼图看起来不错。谢谢!
在表单上创建/复制hidden(可见 = false)图表对象。您甚至可以将其“顶部”和“左侧”属性设置为脱离表单。将此控件设置为非常高的宽度和高度(即 2100 x 1500)...根据您的规格填充并格式化它。请务必增加字体大小等。然后从隐藏图表中调用 SaveImage() 或 DrawToBitmap()...
当您保存此文件时,对于大多数文字处理、桌面酒吧、打印等来说,它基本上具有足够高的分辨率。例如,2100 x 1500 @ 300 dpi = 7" x 5" 用于打印...
在您的应用程序中,您还可以缩小或打印它:缩小“增加”分辨率,使图像变得更清晰。放大会使图像变得模糊或模糊。
我不得不依赖这种技术,因为它是从 .Net 图表控件获取高分辨率图表以进行打印或保存的最一致的方法...这是一个经典的作弊,但它有效:)
例如:
private void cmdHidden_Click(object sender, EventArgs e) {
System.Windows.Forms.DataVisualization.Charting.Title chtTitle =
new System.Windows.Forms.DataVisualization.Charting.Title();
System.Drawing.Font chtFont = new System.Drawing.Font("Arial", 42);
string[] seriesArray = { "A", "B", "C" };
int[] pointsArray = { 1, 7, 4 };
chart1.Visible = false;
chart1.Width = 2100;
chart1.Height = 1500;
chart1.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.Bright;
chtTitle.Font = chtFont;
chtTitle.Text = "Demographics Comparison";
chart1.Titles.Add(chtTitle);
chart1.Series.Clear();
// populate chart
for (int i = 0; i < seriesArray.Length; i++) {
Series series = chart1.Series.Add(seriesArray[i]);
series.Label = seriesArray[i].ToString();
series.Font = new System.Drawing.Font("Arial", 24);
series.ShadowOffset = 5;
series.Points.Add(pointsArray[i]);
}
// save from the chart object itself
chart1.SaveImage(@"C:\Temp\HiddenChart.png", ChartImageFormat.Png);
// save to a bitmap
Bitmap bmp = new Bitmap(2100, 1500);
chart1.DrawToBitmap(bmp, new Rectangle(0, 0, 2100, 1500));
bmp.Save(@"C:\Temp\HiddenChart2.png");
}
这是我制作的一个类,用于制作更大的图表,保存它,然后恢复图表。非常适合我的目的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Chart;
using System.Drawing.Imaging;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms;
namespace Simple_Grapher
{
class saveQualityChartImage
{
Chart theChart;
System.Drawing.Font oldFont1 = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
System.Drawing.Font oldFont2 = new System.Drawing.Font("Trebuchet MS", 15F, System.Drawing.FontStyle.Bold);
System.Drawing.Font oldFont3 = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
System.Drawing.Font oldLegendFont = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
int oldLineWidth1;
int oldLineWidth2;
int oldLineWidth3;
int oldLineWidth4;
int oldWidth;
int oldHeight;
public saveQualityChartImage(Chart inputChart)
{
if (!(inputChart.Series.Count > 0))
{
return;
}
theChart = inputChart;
if (inputChart.Titles.Count > 0)
{
oldFont1 = inputChart.Titles[0].Font;
}
oldFont2 = inputChart.ChartAreas[0].AxisX.LabelStyle.Font;
oldFont3 = inputChart.ChartAreas[0].AxisX.TitleFont;
if (theChart.Legends.Count > 0)
{
oldLegendFont = theChart.Legends["Legend"].Font;
}
oldLineWidth1 = theChart.ChartAreas[0].AxisX.LineWidth;
oldLineWidth2 = theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth;
oldLineWidth3 = theChart.Series[0].BorderWidth;
oldLineWidth4 = theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth;
oldWidth = theChart.Width;
oldHeight = theChart.Height;
saveimage();
}
public void saveimage()
{
theChart.Visible = false;
System.Drawing.Font chtFont = new System.Drawing.Font("Trebuchet MS", 35F, System.Drawing.FontStyle.Bold);
System.Drawing.Font smallFont = new System.Drawing.Font("Trebuchet MS", 15F, System.Drawing.FontStyle.Bold);
if (theChart.Titles.Count > 0)
{
theChart.Titles[0].Font = chtFont;
}
theChart.ChartAreas[0].AxisX.TitleFont = chtFont;
theChart.ChartAreas[0].AxisX.LineWidth = 3;
theChart.ChartAreas[0].AxisX.MajorGrid.LineWidth = 3;
theChart.ChartAreas[0].AxisX.LabelStyle.Font = smallFont;
theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth = 3;
theChart.ChartAreas[0].AxisY.TitleFont = chtFont;
theChart.ChartAreas[0].AxisY.LineWidth = 3;
theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth = 3;
theChart.ChartAreas[0].AxisY.LabelStyle.Font = smallFont;
theChart.ChartAreas[0].AxisY.MajorTickMark.LineWidth = 3;
if (theChart.Legends.Count > 0)
{
theChart.Legends["Legend"].Font = smallFont;
}
foreach (Series series in theChart.Series)
{
series.BorderWidth = 3;
}
theChart.Width = 1800;
theChart.Height = 1200;
SaveFileDialog save = new SaveFileDialog();
save.DefaultExt = ".png";
if (save.ShowDialog() == DialogResult.OK)
{
theChart.SaveImage(save.FileName, ChartImageFormat.Png);
}
resetOldValues();
}
private void resetOldValues()
{
if (theChart.Titles.Count > 0)
{
theChart.Titles[0].Font = oldFont1;
}
theChart.ChartAreas[0].AxisX.TitleFont = oldFont3;
theChart.ChartAreas[0].AxisX.LineWidth = oldLineWidth1;
theChart.ChartAreas[0].AxisX.MajorGrid.LineWidth = oldLineWidth4;
theChart.ChartAreas[0].AxisX.LabelStyle.Font = oldFont2;
theChart.ChartAreas[0].AxisX.MajorTickMark.LineWidth = oldLineWidth2;
theChart.ChartAreas[0].AxisY.TitleFont = oldFont3;
theChart.ChartAreas[0].AxisY.LineWidth = oldLineWidth1;
theChart.ChartAreas[0].AxisY.MajorGrid.LineWidth = oldLineWidth4;
theChart.ChartAreas[0].AxisY.LabelStyle.Font = oldFont2;
theChart.ChartAreas[0].AxisY.MajorTickMark.LineWidth = oldLineWidth2;
if (theChart.Legends.Count > 0)
{
theChart.Legends["Legend"].Font = oldLegendFont;
}
foreach (Series series in theChart.Series)
{
series.BorderWidth = oldLineWidth3;
}
theChart.Width = oldWidth;
theChart.Height = oldHeight;
theChart.Visible = true;
}
}
}
尝试设置
chart2.RenderTransform = new ScaleTransform(10,10)
并保存。这也会让你的线条变得更大。
我将把它添加为一个类,以将图表保存为图像,因为我在这里找到的大多数示例都使用 System.Windows.Forms。这使用 System.Web.UI.DataVisualization.Charting。如果您尝试将此页面上的示例应用于 Web 服务器,则两者之间存在一些细微的差异,这些差异会引发错误。此外,许多其他 SO 问题/示例都没有使用 IEnumerable 数据源。
这里的数据源只是一个以 AsEnumerable() 返回的普通 DataTable(例如 return dt.AsEnumerable();)。
标题和图例也已添加到保存的图像中。
这是从一个数据源生成两张图像。压力和温度图表。下面的压力图是此代码的实际输出。
public static void ChartToImage(Certification.Chart chartData, string hashId, string orderId, string chartNo, string multiChart = "0")
{
string filepath = System.Web.Hosting.HostingEnvironment.MapPath("~/docs/");
string fileNamePress = filepath + chartData.HashId + "p.png";
string fileNameTemp = filepath + chartData.HashId + "t.png";
System.Web.UI.DataVisualization.Charting.Chart chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
System.Web.UI.DataVisualization.Charting.Title cht1Title = new
System.Web.UI.DataVisualization.Charting.Title();
System.Drawing.Font cht1Font = new System.Drawing.Font("Arial", 18);
System.Web.UI.DataVisualization.Charting.Legend cht1Legend = new
System.Web.UI.DataVisualization.Charting.Legend();
System.Drawing.Font cht1LegendFont = new System.Drawing.Font("Arial", 18);
System.Collections.IEnumerable enumerableTable = ChartDAL.ChartIEList(hashId);
System.DateTime x = new System.DateTime(2008, 11, 21);
var chartArea1 = new System.Web.UI.DataVisualization.Charting.ChartArea();
chart1.ChartAreas.Add(chartArea1);
chart1.DataSource = enumerableTable;
chart1.Series.Add("Series1");
chart1.Series["Series1"].ChartType = SeriesChartType.Spline;
chart1.Series["Series1"].XValueType = ChartValueType.Time;
chart1.Series["Series1"].Points.AddXY(x.ToUniversalTime(), "tstamp");
chart1.Series["Series1"].XValueMember = "tstamp";
chart1.Series["Series1"].YValueMembers = "pressure";
chart1.Series["Series1"].IsValueShownAsLabel = false;
chart1.Series["Series1"].Name = "PSI"; // Normally PSI. In the future, pull pressure testing unit from enumerableTable;
cht1Title.Font = cht1Font;
cht1Title.Text = "Pressure Chart"; // In future, pull job number/chart number from database;
chart1.Titles.Add(cht1Title);
cht1Legend.Font = cht1Font;
chart1.Legends.Add(cht1Legend); // chart1.Series["Series1"].Name;
chart1.Width = 900;
chart1.Height = 400;
chart1.DataBind();
chart1.SaveImage(fileNamePress, ChartImageFormat.Png);
System.Web.UI.DataVisualization.Charting.Chart chart2 = new System.Web.UI.DataVisualization.Charting.Chart();
System.Web.UI.DataVisualization.Charting.Title cht2Title = new
System.Web.UI.DataVisualization.Charting.Title();
System.Drawing.Font cht2Font = new System.Drawing.Font("Arial", 18);
System.Web.UI.DataVisualization.Charting.Legend cht2Legend = new
System.Web.UI.DataVisualization.Charting.Legend();
System.Drawing.Font cht2LegendFont = new System.Drawing.Font("Arial", 18);
var chartArea2 = new System.Web.UI.DataVisualization.Charting.ChartArea();
chart2.ChartAreas.Add(chartArea2);
chart2.DataSource = enumerableTable;
chart2.Series.Add("Series1");
chart2.Series["Series1"].ChartType = SeriesChartType.Spline;
chart2.Series["Series1"].XValueType = ChartValueType.Time;
chart2.Series["Series1"].Points.AddXY(x.ToUniversalTime(), "tstamp");
chart2.Series["Series1"].XValueMember = "tstamp";
chart2.Series["Series1"].YValueMembers = "temperature";
chart2.Series["Series1"].IsValueShownAsLabel = false;
chart2.Series["Series1"].Name = "Celsius"; // Normally Celsius. In the future, pull temperature testing unit from enumerableTable;
cht2Title.Font = cht2Font;
cht2Title.Text = "Temperature Chart"; // In future, pull job number/chart number from database;
chart2.Titles.Add(cht2Title);
cht2Legend.Font = cht2Font;
chart2.Legends.Add(cht2Legend); // chart2.Series["Series1"].Name;
chart2.Width = 900;
chart2.Height = 400;
chart2.DataBind();
chart1.SaveImage(fileNamePress, ChartImageFormat.Png);
chart2.SaveImage(fileNameTemp, ChartImageFormat.Png);
}