二维数组未在表单中绘制
Posted
技术标签:
【中文标题】二维数组未在表单中绘制【英文标题】:2D Array not being drawn in Form 【发布时间】:2022-01-11 17:19:43 【问题描述】:我正在用 C# 创建一个密室逃脱游戏。它由“Tiles”类(带有一个矩形实例变量)的 10x10 2D 数组组成,这些数组通过“Room”类的方法绘制到表单上。 Room 的构建涉及三种不同的方法:构建 2D 数组的“buildRoom”(在构造函数中调用)、设置入口和出口点的“setPoints”以及使用图形的“drawRoom”对象在窗体上绘制矩形。我最初在创建房间对象后在 Form1 中调用了这些方法,但是由于我已将其复制到新的 Form 类中,因此它不再起作用。该程序运行,添加图片并接受按键作为动作,但它只是不在表单上绘制。我尝试过单步执行该程序,但一切看起来都应该可以工作。任何帮助都将不胜感激。
这是设置Form,调用方法进行绘制的代码。
public void GameSetUp()
this.Height = 560;
this.Width = 535;
Room room1 = new Room();
room1.buildRoom();
room1.setPoints("room1");
this.Text = "Room 1";
//passing the form into the method
**room1.displayRoom(this);**
Character user = new Character();
StateManager.C = user;
StateManager.C.addCharacter(room1, this, "room1");
设置二维数组的代码:
public void buildRoom()
int xPos = 10;
int yPos = 10;
int width = 50;
int height = 50;
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++)
Tile t = new Tile();
t.rect = new Rectangle(xPos, yPos, width, height);
Board[x, y] = t;
yPos += height;
xPos += width;
yPos = 10;
在窗体上绘制矩形的代码:
public void displayRoom(Form f)
Graphics g = f.CreateGraphics();
Pen p = new Pen(Brushes.Black);
p.Width = 2;
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++)
g.DrawRectangle(p, Board[x,y].rect);
if(Board[x, y].getEntry())
g.FillRectangle(Brushes.Green, Board[x, y].rect);
else if (Board[x, y].getExit())
g.FillRectangle(Brushes.Red, Board[x, y].rect);
else if (Board[x, y].getProblem())
g.FillRectangle(Brushes.SaddleBrown, Board[x, y].rect);
else
g.FillRectangle(Brushes.Bisque, Board[x, y].rect);
【问题讨论】:
别忘了Dispose()
Graphics
对象。我认为您的问题是,您应该在 wm_paint 消息上绘制电路板。问题是,当您在构造函数上绘制并且窗口尚未显示时。你的图丢了。您可以对其进行测试,以在单击按钮时调用您的绘制方法。我建议使用位图进行绘制,在您的情况下,将位图分配给PictureBox.Image
。
【参考方案1】:
从这些代码 sn-ps 中,问题似乎并不明显。尝试debug您的代码。也许你提早了,例如当表单还不可见时?
另外,这不是绘制表格的正确方法。它是操作系统 (Windows),它决定何时必须绘制表单。例如。当您顶部的另一个表单被删除或当您从最小化状态恢复窗口时。
因此,您必须覆盖 OnPaint 并在那里进行绘制。当您想重绘时,您可以调用Invalidate()
(Form
和所有控件的方法)并让 Windows 决定何时重绘(即何时调用 OnPaint
)或调用 Refresh()
强制立即重绘。
protected override void OnPaint(PaintEventArgs e)
base.OnPaint(e); // Call the OnPaint method of the base class.
Graphics g = e.Graphics; // Do not create your own Graphics object.
using Pen p = new Pen(Brushes.Black); // A using var statement or a plain
// using statement must the pen.
p.Width = 2;
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++)
g.DrawRectangle(p, Board[x,y].rect);
if(Board[x, y].getEntry())
g.FillRectangle(Brushes.Green, Board[x, y].rect);
else if (Board[x, y].getExit())
g.FillRectangle(Brushes.Red, Board[x, y].rect);
else if (Board[x, y].getProblem())
g.FillRectangle(Brushes.SaddleBrown, Board[x, y].rect);
else
g.FillRectangle(Brushes.Bisque, Board[x, y].rect);
顺便说一句:你的代码看起来像 Java。在 C# 中,对方法和属性使用 PascalCase,在这种情况下,您可以对属性使用属性语法,而不是普通的 getXY 和 setXY 方法。
另见:
Disposing GDI Objects in C#. NET. Properties (C# Programming Guide) C# Coding Standards and Naming Conventions【讨论】:
以上是关于二维数组未在表单中绘制的主要内容,如果未能解决你的问题,请参考以下文章
用C++在Win32中用LoadImage()绘制HBITMAP的二维数组