属性改变时如何刷新GDI+创建的UserControl
How to refresh UserControl which create by GDI+ when property changes
首先,我的英语不好。
所以如果有语法错误,还请谅解..
我参考了here.
我用 2 个项目创建了一个简单的解决方案。第一个项目(class 库)包含一个通过 GDI+ 绘制 Tank 的自定义控件。第二个项目(windows 表格)是一个测试应用程序。
我想使用 Tank 作为控件,可以显示通过调用 Value 属性 设置的实时值。实现这个我有很多问题。大部分都解决了,但是有个问题
在第二个项目中,如果我开始 Form1
在 Form1 添加 Timer 并设置随机生成的值 属性 以在 timer_tick() 中显示实时值后,我必须在 Form1_Paint 中调用 tank1.Refresh() ().
有两张图片显示了这个问题。
在每一张照片中,
左边是与右边一样以相同方式创建(工作方式相同)的控件,在 Form1_Paint().
中未调用 .Refresh()
picture1
picture2
有没有更好的方法,比如只在 timer_tick() 中调用 Invalidate() 而不是在 Form_Paint() 中调用 tank.Refresh?
我看过一些解释 .Invalidate()、.Refresh()、.Update() 或推荐使用事件的问答,但我不知道哪种方式更好。
为什么当我在 Form1_Paint() 中调用 Invalidate() 时 tank1 没有重新绘制?
我希望有人能理解初学者的痛苦....
这是代码
public class Tank : UserControl
{
public Tank();
public float MAX { get; set; }
public float MIN { get; set; }
public float Value { get; set; }
protected override void Dispose(bool disposing);
protected override void OnPaint(PaintEventArgs e);
}
public partial class Form1 : Form
{
Random R = new Random();
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
tank1.Refresh();
//waterStorageBasin1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
tank1.Value = (float)(R.NextDouble() * 10);
waterStorageBasin1.Value = (float)(R.NextDouble() * 10);
label1.Text = Math.Round(tank1.Value, 2).ToString();
label2.Text = Math.Round(waterStorageBasin1.Value, 2).ToString();
//I want this way
//Invalidate();
}
}
Hans Passant 回答说 this.Invalidate() 会更好。
@HansPassant 感谢您的帮助!
public float Value
{
get
{
return _tankLevel_Value;
}
set
{
_tankLevel_Value = value;
this.Invalidate();
}
}
首先,我的英语不好。 所以如果有语法错误,还请谅解..
我参考了here.
我用 2 个项目创建了一个简单的解决方案。第一个项目(class 库)包含一个通过 GDI+ 绘制 Tank 的自定义控件。第二个项目(windows 表格)是一个测试应用程序。
我想使用 Tank 作为控件,可以显示通过调用 Value 属性 设置的实时值。实现这个我有很多问题。大部分都解决了,但是有个问题
在第二个项目中,如果我开始 Form1 在 Form1 添加 Timer 并设置随机生成的值 属性 以在 timer_tick() 中显示实时值后,我必须在 Form1_Paint 中调用 tank1.Refresh() ().
有两张图片显示了这个问题。 在每一张照片中, 左边是与右边一样以相同方式创建(工作方式相同)的控件,在 Form1_Paint().
中未调用 .Refresh()picture1
picture2
有没有更好的方法,比如只在 timer_tick() 中调用 Invalidate() 而不是在 Form_Paint() 中调用 tank.Refresh? 我看过一些解释 .Invalidate()、.Refresh()、.Update() 或推荐使用事件的问答,但我不知道哪种方式更好。
为什么当我在 Form1_Paint() 中调用 Invalidate() 时 tank1 没有重新绘制?
我希望有人能理解初学者的痛苦....
这是代码
public class Tank : UserControl
{
public Tank();
public float MAX { get; set; }
public float MIN { get; set; }
public float Value { get; set; }
protected override void Dispose(bool disposing);
protected override void OnPaint(PaintEventArgs e);
}
public partial class Form1 : Form
{
Random R = new Random();
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
tank1.Refresh();
//waterStorageBasin1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
tank1.Value = (float)(R.NextDouble() * 10);
waterStorageBasin1.Value = (float)(R.NextDouble() * 10);
label1.Text = Math.Round(tank1.Value, 2).ToString();
label2.Text = Math.Round(waterStorageBasin1.Value, 2).ToString();
//I want this way
//Invalidate();
}
}
Hans Passant 回答说 this.Invalidate() 会更好。
@HansPassant 感谢您的帮助!
public float Value
{
get
{
return _tankLevel_Value;
}
set
{
_tankLevel_Value = value;
this.Invalidate();
}
}