我在元组列表列表中有一些数据。我的任务是从中制作热图。作为 C# 的新手,我在网上搜索并找到了一种通过在 DataGridView 中绘制元素来解决此任务的方法,但我不明白该怎么做。所以,我有一个Touples列表:
using SpikeDataPacket = List<Tuple<double, double>>;
Run Code Online (Sandbox Code Playgroud)
这是我在网格内加载数据的方式:
public HeatForm(List<SpikeDataPacket> list)
{
SpikeList = list;
InitializeComponent();
var bindstim = new BindingList<SpikeDataPacket>(SpikeList);
var stimsource = new BindingSource(bindstim, null);
heatMap.DataSource = stimsource;
}
Run Code Online (Sandbox Code Playgroud)
但这会在 DataGridView 中显示一个带有“容量”和“计数”的表,而不是数据。另外,我找到了计算颜色的方法,但不知道如何应用它:
private Color HeatMapColor(double value, double min, double max)
{
Color firstColour = Color.RoyalBlue;
Color secondColour = Color.LightSkyBlue;
// Example: Take the RGB
//135-206-250 // Light Sky Blue
// 65-105-225 // Royal Blue
// 70-101-25 // Delta
int rOffset = Math.Max(firstColour.R, secondColour.R);
int gOffset = Math.Max(firstColour.G, secondColour.G);
int bOffset = Math.Max(firstColour.B, secondColour.B);
int deltaR = Math.Abs(firstColour.R - secondColour.R);
int deltaG = Math.Abs(firstColour.G - secondColour.G);
int deltaB = Math.Abs(firstColour.B - secondColour.B);
double val = (value - min) / (max - min);
int r = rOffset - Convert.ToByte(deltaR * (1 - val));
int g = gOffset - Convert.ToByte(deltaG * (1 - val));
int b = bOffset - Convert.ToByte(deltaB * (1 - val));
return Color.FromArgb(255, r, g, b);
}
Run Code Online (Sandbox Code Playgroud)
先感谢您!
我想我会以不同的方式解决这个问题。
DataBinding
. 元组结构的列表列表和双Color
精度到 a 的映射都不适用于 well to DataBinding
。要将数据填充到 DataGridView DGV 中,我使用了一个简单的例程,它首先准备 DGV,然后绘制单元格:
void fillData()
{
int maxRow = data.Count;
int maxCol = data[0].Count;
double factor = 1.0;
DGV.RowHeadersVisible = false;
DGV.ColumnHeadersVisible = false;
DGV.AllowUserToAddRows = false;
DGV.AllowUserToOrderColumns = false;
DGV.CellBorderStyle = DataGridViewCellBorderStyle.None;
//..
int rowHeight = DGV.ClientSize.Height / maxRow - 1;
int colWidth = DGV.ClientSize.Width / maxCol - 1;
for (int c = 0; c < maxRow; c++) DGV.Columns.Add(c.ToString(), "");
for (int c = 0; c < maxRow; c++) DGV.Columns[c].Width = colWidth;
DGV.Rows.Add(maxRow);
for (int r = 0; r < maxRow; r++) DGV.Rows[r].Height = rowHeight;
List<Color> baseColors = new List<Color>(); // create a color list
baseColors.Add(Color.RoyalBlue);
baseColors.Add(Color.LightSkyBlue);
baseColors.Add(Color.LightGreen);
baseColors.Add(Color.Yellow);
baseColors.Add(Color.Orange);
baseColors.Add(Color.Red);
List<Color> colors = interpolateColors(baseColors, 1000);
for (int r = 0; r < maxRow; r++)
{
for (int c = 0; c < maxRow; c++)
{
DGV[r,c].Style.BackColor =
colors[ Convert.ToInt16( data[r][c].Item2 * factor)];
}
}
}
Run Code Online (Sandbox Code Playgroud)
您需要更改一些内容,尤其是基色和您想要获得的颜色数量,这取决于您的值以及从双精度值到整数索引的映射!
这是创建内插颜色列表的函数。它需要一些基色和长度 N 并返回 N 个插值颜色。这使得映射简单而灵活。
List<Color> interpolateColors(List<Color> stopColors, int count)
{
SortedDictionary<float, Color> gradient = new SortedDictionary<float, Color>();
for (int i = 0; i < stopColors.Count; i++)
gradient.Add(1f * i / (stopColors.Count-1), stopColors[i]);
List<Color> ColorList = new List<Color>();
using (Bitmap bmp = new Bitmap(count, 1))
using (Graphics G = Graphics.FromImage(bmp))
{
Rectangle bmpCRect = new Rectangle(Point.Empty, bmp.Size);
LinearGradientBrush br = new LinearGradientBrush
(bmpCRect, Color.Empty, Color.Empty, 0, false);
ColorBlend cb = new ColorBlend();
cb.Positions = new float[gradient.Count];
for (int i = 0; i < gradient.Count; i++)
cb.Positions[i] = gradient.ElementAt(i).Key;
cb.Colors = gradient.Values.ToArray();
br.InterpolationColors = cb;
G.FillRectangle(br, bmpCRect);
for (int i = 0; i < count; i++) ColorList.Add(bmp.GetPixel(i, 0));
br.Dispose();
}
return ColorList;
}
Run Code Online (Sandbox Code Playgroud)
我的测试数据是这样创建的:
List<List<Tuple<double,double>>> data = new List<List<Tuple<double,double>>>();
Random R = new Random();
void createData(int maxRow, int maxCol)
{
for (int c = 0; c < maxRow; c++)
{
data.Add(new List<Tuple<double, double>>());
for (int r = 0; r < maxRow; r++)
{
data[c].Add(new Tuple<double, double>(c, Math.Min(999, R.Next(r*c))));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我是这样用的:
private void Form1_Load(object sender, EventArgs e)
{
createData(40, 40);
fillData();
}
Run Code Online (Sandbox Code Playgroud)
这是一个(相当无聊的)截图:
获得所需的显示后,您可能需要决定使用 DataBinding
. 我相信,你将需要使用OwnerDrawing
的Cells
。一旦您在单元格中拥有值,您就可以像这样使用相同的映射:
private void DGV_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
Color theColor = .....
e.Graphics.Clear(colors[theColor]);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4557 次 |
最近记录: |