我正在使用Windows Forms。长期以来,pictureBox.Invalidate();
函数可以使屏幕重新绘制。但是现在它不起作用了,我不确定原因。
this.worldBox = new System.Windows.Forms.PictureBox();
this.worldBox.BackColor = System.Drawing.SystemColors.Control;
this.worldBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.worldBox.Location = new System.Drawing.Point(170, 82);
this.worldBox.Name = "worldBox";
this.worldBox.Size = new System.Drawing.Size(261, 250);
this.worldBox.TabIndex = 0;
this.worldBox.TabStop = false;
this.worldBox.MouseMove += new
System.Windows.Forms.MouseEventHandler(this.worldBox_MouseMove);
this.worldBox.MouseDown += new
System.Windows.Forms.MouseEventHandler(this.worldBox_MouseDown);
this.worldBox.MouseUp += new
System.Windows.Forms.MouseEventHandler(this.worldBox_MouseUp);
在我的代码中调用以适当地绘制世界:
view.DrawWorldBox(worldBox, canvas, gameEngine.GameObjectManager.Controllers,
selectedGameObjects, LevelEditorUtils.PREVIEWS);
View.DrawWorldBox:
public void DrawWorldBox(PictureBox worldBox,
Panel canvas,
ICollection<IGameObjectController> controllers,
ICollection<IGameObjectController> selectedGameObjects,
IDictionary<string, Image> previews)
{
int left = Math.Abs(worldBox.Location.X);
int top = Math.Abs(worldBox.Location.Y);
Rectangle screenRect = new Rectangle(left, top, canvas.Width,
canvas.Height);
IDictionary<float, ICollection<IGameObjectController>> layers =
LevelEditorUtils.LayersOfControllers(controllers);
IOrderedEnumerable<KeyValuePair<float,
ICollection<IGameObjectController>>> sortedLayers
= from item in layers
orderby item.Key descending
select item;
using (Graphics g = Graphics.FromImage(worldBox.Image))
{
foreach (KeyValuePair<float, ICollection<IGameObjectController>>
kv in sortedLayers)
{
foreach (IGameObjectController controller in kv.Value)
{
// ...
float scale = controller.View.Scale;
float width = controller.View.Width;
float height = controller.View.Height;
Rectangle controllerRect = new
Rectangle((int)controller.Model.Position.X,
(int)controller.Model.Position.Y,
(int)(width * scale),
(int)(height * scale));
// cull objects that aren't intersecting with the canvas
if (controllerRect.IntersectsWith(screenRect))
{
Image img = previews[controller.Model.HumanReadableName];
g.DrawImage(img, controllerRect);
}
if (selectedGameObjects.Contains(controller))
{
selectionRectangles.Add(controllerRect);
}
}
}
foreach (Rectangle rect in selectionRectangles)
{
g.DrawRectangle(drawingPen, rect);
}
selectionRectangles.Clear();
}
worldBox.Invalidate();
}
我在这里可能做错了什么?
Refresh
与Invalidate/Update
得到了相同的行为。这使我感到困扰,因为我曾经非常肯定我观察到过不同。于是我用反编译工具打开它,发现Control.Refresh
方法实际上是先执行一个Invalidate
,再执行一个Update
。然后我恍然大悟:Refresh
方法是“虚拟的”。所以有时候它无法正常工作,是因为控件的作者重写了它并弄乱了它。Refresh
方法应该在大多数情况下能够正常工作,但如果它不能正常工作,通常可以通过显式地调用Invalidate/Update
方法来修复它。 - AaronaughtInvalidate
和Refresh
(或Invalidate/Update
)之间的区别,只需在窗体上添加一个文本框,在事件处理程序中编写textBox1.BackColor = Color.Red
,然后是Invalidate
,接着是Thread.Sleep(1000)
- 你会发现更新直到事件处理程序执行完毕才会发生。如果你正在进行长时间运行的操作并且没有使用BackgroundWorker
或工作线程,你需要通过这种方式“强制”更新。 - Aaronaught