C#添加Label控件后Paint事件绑定的DrawGrid持续触发如何解决
问题成因
- 重复添加控件触发重绘:你当前的
DrawLabels方法每次执行都会调用Controls.Add()把两个Label重复加入窗体控件集合,每次添加子控件的操作都会触发父窗体的Paint事件,进而调用DrawGrid方法。如果你的NewGame方法会被多次调用(比如点击新游戏按钮触发),就会反复执行Controls.Add(),持续触发重绘。 - 调试代码加剧死循环:你在
DrawGrid中加入了MessageBox.Show()调试代码,弹窗会遮挡窗体,关闭弹窗时窗体需要重新绘制被遮挡的区域,会再次触发Paint事件,形成「重绘→弹窗→关弹窗→重绘」的无限循环。 - 资源使用不规范:你在
DrawGrid里每次循环都new Pen(Brushes.Black),未释放的GDI资源也可能导致额外的重绘或性能问题。
解决方法
- 控件仅添加一次:将Label的初始化和
Controls.Add()逻辑移到窗体构造函数中,全局只执行一次,后续要更新标签内容只修改Text属性即可,不需要重复添加控件。 - 移除Paint事件中的弹窗逻辑:调试用
Debug.WriteLine()输出信息到IDE的输出窗口,不要用会触发重绘的MessageBox。 - 规范GDI资源使用:直接用系统内置的
Pens.Black绘制,避免手动创建Pen资源泄漏。 - 可选优化:开启窗体双缓冲减少重绘闪烁。
修改后的参考代码
Rectangle[,] rec = new Rectangle[6,6]; Label label_1 = new Label(); Label label_2 = new Label(); int grspel = 6; // 补充你省略的变量定义 int zwart = 0; int wit = 0; public Reversi() { ClientSize = new Size(500,425); BackColor = Color.DarkGreen; DoubleBuffered = true; // 开启双缓冲减少闪烁 // 标签初始化和添加仅执行一次 label_1.Location = new Point(20, 50); label_1.ForeColor = Color.White; // 避免深色背景下文字看不见 Controls.Add(label_1); label_2.Location = new Point(330, 50); label_2.ForeColor = Color.White; Controls.Add(label_2); Paint += DrawGrid; NewGame(); } public void NewGame() { // 为简洁起见,此处省略其余相关代码 for (int i = 0; i < grspel; i++) { for (int j = 0; j < grspel; j++) { rec[i, j] = new Rectangle(50 + i * 50, 100 + j * 50, 50, 50); } } UpdateLabels(); // 仅更新标签文本,不重复添加 } // 原DrawLabels改名为UpdateLabels,仅做文本更新 public void UpdateLabels() { label_1.Text = "Zwart: " + zwart; label_2.Text = "Wit: " + wit; } public void DrawGrid(object o, PaintEventArgs pea) { // 调试用Debug.WriteLine("test"),不要用MessageBox for (int i = 0; i < 6; i++) { for (int j = 0; j < 6; j++) { pea.Graphics.DrawRectangle(Pens.Black, rec[i,j]); } } }
内容的提问来源于stack exchange,提问作者Jiemie
相关产品推荐
相关产品推荐

