假想一个需求,有一个库存数据列表,包括库位,数量,需要在winform窗口下绘制这个列表,将每个库位绘制成一个小的长方形,上面写有库位,数量,当数量小于5时显示红色,5到10之间显示黄色,10以上显示绿色。
AutoScroll
属性设置为 true
,以便在库位数据过多时可以滚动查看。C#using System;
namespace WinFormsApp19
{
public partial class Form1 : Form
{
private List<InventoryItem> inventoryItems;
private System.Timers.Timer timer;
public Form1()
{
InitializeComponent();
InitializeInventoryItems(); // 初始化库存数据
panel1.Paint += new PaintEventHandler(panel1_Paint); // 订阅Paint事件
timer = new System.Timers.Timer();
timer.Interval = 500;
timer.Elapsed += Timer_Elapsed;
timer.Enabled = false;
}
private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
Random random = new Random();
int index = random.Next(0, 25);
inventoryItems[index].Quantity = random.Next(0, 15);
// 仅重绘发生变化的部分
Rectangle rect = GetItemRectangle(index);
panel1.Invalidate(rect);
}
private Rectangle GetItemRectangle(int index)
{
int xOffset = 10;
int yOffset = 10;
int width = 120;
int height = 80;
int padding = 10;
int row = index / 3;
int col = index % 3;
xOffset += col * (width + padding);
yOffset += row * (height + padding);
return new Rectangle(xOffset, yOffset, width, height);
}
private void InitializeInventoryItems()
{
inventoryItems = new List<InventoryItem>();
Random random = new Random();
for (int i = 0; i < 26; i++) // 生成26个库位数据(A-Z)
{
string location = ((char)(i + 65)).ToString();
int quantity = random.Next(0, 15);
inventoryItems.Add(new InventoryItem(location, quantity));
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
int xOffset = 10;
int yOffset = 10;
int width = 120;
int height = 80;
int padding = 10;
Graphics g = e.Graphics;
foreach (var item in inventoryItems)
{
// 设置颜色
Color fillColor;
if (item.Quantity < 5)
fillColor = Color.Red;
else if (item.Quantity >= 5 && item.Quantity <= 10)
fillColor = Color.Yellow;
else
fillColor = Color.Green;
// 绘制矩形
Rectangle rect = new Rectangle(xOffset, yOffset, width, height);
using (SolidBrush brush = new SolidBrush(fillColor))
{
g.FillRectangle(brush, rect);
}
g.DrawRectangle(Pens.Black, rect);
// 绘制文本
string text = $"{item.Location}\n{item.Quantity}";
TextRenderer.DrawText(g, text, this.Font, rect, Color.Black, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak);
// 更新坐标
yOffset += height + padding;
if (yOffset + height > panel1.ClientSize.Height) // 列表超出Panel高度时换列
{
yOffset = 10;
xOffset += width + padding;
}
}
}
public class InventoryItem
{
public string Location { get; set; }
public int Quantity { get; set; }
public InventoryItem(string location, int quantity)
{
Location = location;
Quantity = quantity;
}
}
private void Form1_Load(object sender, EventArgs e)
{
panel1.Invalidate(); // 强制重绘
}
private void btnStart_Click(object sender, EventArgs e)
{
timer.Enabled = true;
}
private void btnStop_Click(object sender, EventArgs e)
{
timer.Enabled = false;
}
}
}
DoubleBuffered
属性在某些控件(例如 Panel
)中并不是直接公开的,但它确实存在于基类 Control
中。我们可以通过创建一个派生类来启用双缓冲。
以下是实现双缓冲的改进代码示例:
BufferedPanel
类,继承自 Panel
,并在构造函数中设置双缓冲。BufferedPanel
替代默认的 Panel
控件。BufferedPanel
类C#public class BufferedPanel: Panel
{
public BufferedPanel()
{
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
}
}
本文作者:rick
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!