接到一個(gè)需求,繪制一個(gè)水管線的圖片,這種管線可以有12種分段方法,最后將這12種分段方法合并后在一條水管線上展示,要求:
?、敝С址侄蔚膶傩哉故?;
⒉要求每個(gè)分段都能清晰展示,分段數(shù)在0(沒有分段)~100之間,水管線長度不定;
3、每個(gè)分段的屬性都有值,可以更改,使用XML存儲(chǔ);
4、不同材質(zhì)管線使用不同的背景;
5、根據(jù)不同的值,分段顯示不同的顏色;
6、支持鼠標(biāo)滾動(dòng)。
因?yàn)樾枰焖偻瓿?,時(shí)間緊,第一時(shí)間想到使用C#的GDI+,可是在支持熱點(diǎn)和放大與縮小時(shí)卡殼了,趕緊換了一種方法,制定一個(gè)自定義控件,在Panel上繪圖,支持拖動(dòng),放大與縮小,可是總是會(huì)出現(xiàn)這樣那樣的問題,也想使用SVG,可是擔(dān)心還是完不成,換成DataGridView,也算完成了,效果如下:
經(jīng)常在網(wǎng)上看到說在中國35歲以后就不能寫代碼了,感覺一個(gè)是熱愛不夠了,第二個(gè)可能是身體狀況也不允許了。在一般企業(yè)中,也沒有動(dòng)力去費(fèi)神像年輕時(shí)候完成一個(gè)程序,那個(gè)時(shí)候有沖勁和干勁,特別有耐心,希望得到別人的肯定與贊揚(yáng),現(xiàn)在50多歲了,沒有動(dòng)力了,想一想以前也是覺得可笑了。
這個(gè)完成后,自定義一個(gè)控件就可以使用了。
? 下面是完成的代碼:
定義:
private static ToolTip toolTip = new ToolTip();
// 定義一個(gè)List,用于存儲(chǔ)點(diǎn)的信息
List<float> Points = new List<float>() {0 };
int MinColWidth=48;//定義最小分段對(duì)應(yīng)的寬度
float pipelineLength;//定義管線長度
float RateF;//實(shí)際進(jìn)行計(jì)算的比例
初始化:
//初始化DataGridView
dataGridView1.ColumnHeadersVisible = false;//隱藏標(biāo)題欄
dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None;//取消分割線
//dataGridView1.ScrollBars = ScrollBars.Horizontal;
dataGridView1.ScrollBars = ScrollBars.None;//去掉滾動(dòng)條
dataGridView1.AllowUserToAddRows = false;//不允許用戶增加行
dataGridView1.AllowUserToDeleteRows = false;//不允許用戶刪除行
dataGridView1.AllowUserToResizeRows = false;//不允許用戶改變行高度
//dataGridView1.Columns.Add("Column1", "列1");
dataGridView1.RowTemplate.Height = 32;//設(shè)置行高度
//dataGridView1.Rows.Add();
//dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;
dataGridView1.AllowUserToResizeColumns = false;//不允許用戶改變欄寬度
dataGridView1.RowHeadersVisible = false;//隱藏最前面的選擇列
dataGridView1.Columns.Clear();//刪除所有的列
dataGridView1.Columns.Add("Column1", "列1");//添加一列
dataGridView1.Rows.Add();//添加一行
dataGridView1.Rows[0].ReadOnly = true;//設(shè)置第一行為只讀
dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;//設(shè)置行背景色
dataGridView1.Columns[0].Visible = false;//隱藏標(biāo)題欄
dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;// 設(shè)置編輯模式為EditProgrammatically
//注冊(cè)事件
dataGridView1.CellPainting += dataGridView1_CellPainting;//單元格渲染
dataGridView1.CellFormatting += dataGridView1_CellFormatting;
dataGridView1.MouseEnter += dataGridView1_MouseEnter;//鼠標(biāo)移入
dataGridView1.MouseLeave += dataGridView1_MouseLeave;//鼠標(biāo)離開
dataGridView1.MouseWheel += dataGridView1_MouseWheel;//鼠標(biāo)滾動(dòng)
dataGridView1.RowPrePaint+=dataGridView1_RowPrePaint;//行渲染
//List<float> P = new List<float>() { 12, 27, 41, 73, 89, 105, 119, 126, 138, 166, 192, 208, 255, 377, 410, 439 };
List<float> P = new List<float>() { 31, 25, 45,39, 73, 89, 115, 121 };
UpdatePoints(P, 138);
事件以及函數(shù)內(nèi)容:
void UpdatePoints(List<float> NewPoints,float NowDistance)
{
Points = NewPoints;
pipelineLength = NowDistance;
Points.Add(0);
Points.Add(pipelineLength);
Points.Sort();
//計(jì)算實(shí)際的換算比例
RateF = ((dataGridView1.Width - (Points.Count - 1) * 5) / pipelineLength);
textBox1.Text += "計(jì)算比例:" + RateF.ToString() + Environment.NewLine;
textBox1.Text += "管線長度:" + pipelineLength.ToString() + Environment.NewLine;
textBox1.Text += "顯示寬度:" + dataGridView1.Width.ToString() + Environment.NewLine;
//得到最小的分段
float MinSectionLength = CalculateMinDistance();
textBox1.Text += "最小分段:" + MinSectionLength.ToString() + Environment.NewLine;
if (MinSectionLength * RateF < MinColWidth)
{
//重新設(shè)定比例
RateF = MinColWidth / MinSectionLength;
}
textBox1.Text += "最后比例:" + RateF.ToString() + Environment.NewLine;
//更新DataGridView
//設(shè)置每一列的寬度
//foreach (int point in Points)
for(int i=1; i<Points.Count; i++)
{
float ColWidth = (Points[i] - Points[i - 1]) * RateF;
AddColumn(dataGridView1,"Section", (int)ColWidth, Color.Brown, Color.Cyan, Points[i - 1], Points[i]);//增加分段
if (i!=Points.Count-1)
{
AddColumn(dataGridView1, "Dot", 5, Color.Brown, Color.Blue, Points[i - 1], Points[i]);//增加點(diǎn)
}
}
}
// 動(dòng)態(tài)增加列
void AddColumn(DataGridView dataGridView, string StrType, int width, Color textColor, Color cellBackColor,float StartDot,float EndDot)
{
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
column.Width = width;
//column.HeaderText = text;
column.DefaultCellStyle.ForeColor = textColor;
column.DefaultCellStyle.BackColor = cellBackColor;
// 為每一列添加屬性
column.Tag = new ColumnProperty
{
SectionType = StrType,
StartPoint = StartDot,
EndPoint = EndDot,
Distance = EndDot - StartDot
};
dataGridView.Columns.Add(column);
// 獲取第一行
DataGridViewRow firstRow = dataGridView.Rows[0];
// 設(shè)置特定列的單元格屬性
//firstRow.Cells[column.Index].Value = text;
firstRow.Cells[column.Index].Style.BackColor = cellBackColor;
firstRow.Cells[column.Index].Style.ForeColor = Color.Red;
//dataGridView.Columns.Add(column);
}
class ColumnProperty
{
public int SectionIndex { get; set; } //分段序號(hào)
public string SectionType { get; set; } //類型
public float StartPoint { get; set; } //起點(diǎn)
public float EndPoint { get; set; } //終點(diǎn)
public float Distance { get; set; } //距離
public string Rule01 { get; set; } //
public string Rule02 { get; set; } //
public string Rule03 { get; set; } //
public string Rule04 { get; set; } //
public string Rule05 { get; set; } //
public string Rule06 { get; set; } //
public string Rule07 { get; set; } //
public string Rule08 { get; set; } //
public string Rule09 { get; set; } //
public string Rule10 { get; set; } //
public string Rule11 { get; set; } //
public string Rule12 { get; set; } //管理站隊(duì)
public float Pvalue { get; set; } //失效可能性
public float Cvalue { get; set; } //風(fēng)險(xiǎn)
public float Rvalue { get; set; } //后果
}
float CalculateMinDistance()
{
// 實(shí)現(xiàn)計(jì)算功能,計(jì)算相鄰兩個(gè)點(diǎn)之間的距離,得到最小值
List<float> segmentLengths = new List<float>();
for (int i = 0; i < Points.Count - 1; i++)
{
float segmentLength = Points[i + 1] - Points[i];
segmentLengths.Add(segmentLength);
}
float minSegmentLength = segmentLengths.Count > 0 ? segmentLengths.Min() : pipelineLength;
return FloatFormat(minSegmentLength);
}
private float FloatFormat(float f)
{
return (float)Math.Round(f, 2); ;
}
private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
// 判斷是否是水平滾動(dòng)
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
// 水平滾動(dòng)內(nèi)容
dataGridView1.HorizontalScrollingOffset = e.NewValue;
}
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
//{
// if (e.ColumnIndex % 2 == 0)
// {
// e.CellStyle.BackColor = Color.DarkGray;
// }
// else
// {
// e.CellStyle.BackColor = Color.LightGray;
// }
//}
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
//if (e.RowIndex >= 0 && e.ColumnIndex >= 0 && e.ColumnIndex % 2 == 0)
//{
// dataGridView1.Rows[e.RowIndex].DefaultCellStyle.SelectionBackColor = Color.Transparent;
// dataGridView1.Rows[e.RowIndex].DefaultCellStyle.SelectionForeColor = dataGridView1.DefaultCellStyle.ForeColor;
//}
}
private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
e.PaintParts &= ~DataGridViewPaintParts.Background;
if (e.RowIndex >= 0)
{
Image image = Image.FromFile("D:/CSharp/TestTreeview/WinFormsApp2/WinFormsApp2/image/TRQpipeline.jpg"); // 替換為實(shí)際的圖片路徑
Rectangle rect = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, dataGridView1.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - 1, e.RowBounds.Height - 1);
e.Graphics.DrawImage(image, rect);
}
}
private void dataGridView1_MouseEnter(object sender, EventArgs e)
{
dataGridView1.BorderStyle = BorderStyle.FixedSingle;
//dataGridView1.BorderColor = Color.Red;
}
private void dataGridView1_MouseLeave(object sender, EventArgs e)
{
dataGridView1.BorderStyle = BorderStyle.None;
}
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
//if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
//{
// // 設(shè)置單元格背景顏色
// e.CellStyle.BackColor = Color.Red;
// // 設(shè)置單元格背景色的透明度
// e.CellStyle.BackColor = Color.FromArgb(192, e.CellStyle.BackColor);
//}
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
if (e.ColumnIndex % 2 != 0)
{
// 設(shè)置偶數(shù)列單元格的前景色為半透明背景色
using (Brush brush = new SolidBrush(Color.FromArgb(0, Color.White)))
{
e.Graphics.FillRectangle(brush, e.CellBounds);
}
}
else
{
// 設(shè)置奇數(shù)列單元格的前景色為深灰色并覆蓋行背景色
using (Brush brush = new SolidBrush(Color.Black))
{
e.Graphics.FillRectangle(brush, e.CellBounds);
}
}
// 繪制單元格內(nèi)容
e.PaintContent(e.CellBounds);
e.Handled = true;
}
}
// 處理鼠標(biāo)滾輪事件
private void dataGridView1_MouseWheel(object sender, MouseEventArgs e)
{
int delta = e.Delta;
int newOffset = dataGridView1.HorizontalScrollingOffset - delta;
// 檢查滾動(dòng)范圍是否超出邊界
if (newOffset < 0)
{
newOffset = 0; // 將滾動(dòng)范圍限制在最左邊
}
else if (newOffset > GetHorizontalScrollingOffsetMax())
{
newOffset = GetHorizontalScrollingOffsetMax(); // 將滾動(dòng)范圍限制在最右邊
}
// 設(shè)置新的水平滾動(dòng)偏移量
dataGridView1.HorizontalScrollingOffset = newOffset;
}
private int GetHorizontalScrollingOffsetMax()
{
int maxOffset = 0;
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
maxOffset += column.Width;
}
maxOffset -= dataGridView1.ClientSize.Width;
return maxOffset;
}
private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex % 2 != 0)
{
DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
ColumnProperty properties = (ColumnProperty)row.Cells[e.ColumnIndex].OwningColumn.Tag;
string tooltip = $"Type: {properties.SectionType}\nStart Point: {properties.StartPoint}\nEnd Point: {properties.EndPoint}";
toolTip.SetToolTip(dataGridView1, tooltip);
}
else
{
string tooltip = "";
toolTip.SetToolTip(dataGridView1, tooltip);
}
}
private void dataGridView1_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
//判斷分段屬性如果是Section
if (e.RowIndex >= 0)
{
DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
ColumnProperty properties = (ColumnProperty)row.Cells[e.ColumnIndex].OwningColumn.Tag;
if (properties.SectionType == "Section")
{
MessageBox.Show(properties.StartPoint.ToString()+ "|"+properties.EndPoint.ToString());
}
}
}
功能是完成了,后面還需要完善細(xì)節(jié),就是屬性值的更新,主要是TreeView與XML內(nèi)容的同步,包括自動(dòng)計(jì)算。文章來源:http://www.zghlxwxcb.cn/news/detail-574002.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-574002.html
到了這里,關(guān)于C#使用DataGridView模擬繪圖的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!