3 回答
TA贡献1772条经验 获得超5个赞
private List<Panel> _panels = new List<Panel>(); //class level list to track the panels
private void button2_Click(object sender, EventArgs e)
{
//create a new panel when the button is clicked
var p = new Panel();
p.Size = new Size(10, 10);
p.Location = new Point(10, DateTime.Now.Second * (this.Height / 60)); //"random" Y so they don't pile up
p.BackColor = Color.Green;
this.Controls.Add(p); //add panel to form
_panels.Add(p); //add panel to list
timer1.Enabled = true; //animate
}
private void timer1_Tick(object sender, EventArgs e)
{
for (int i = _panels.Count - 1; i >= 0; i--) //use a backwards int indexed loop because we are potentially removing items from the list.
{ //Working backwards is the easiest way to not have to fiddle the index upon removal
var p = _panels[i]; //temp reference to a panel in the list, not related to 'var p' in the button click
p.Left += 25; //move it
if (p.Left > this.Width) //panel that is off screen?
_panels.RemoveAt(i); //stop moving it then
}
if (_panels.Count == 0) //no more panels to move?
timer1.Stop(); //stop the timer
}
this.Controls如果您不再使用不可见的面板,您应该考虑实现一些逻辑,将其从集合中删除。
TA贡献1786条经验 获得超11个赞
这是我写的一个简单的例子,这里我使用 1 个计时器来处理所有面板,如果你想让它更平滑,使运动增量更小(从 25 到更低)并增加计时器的滴答率,你也可以尝试单独为每个面板使用一个计时器,但在我看来这有点过分了。
编辑:如果您想要真正精确的定位和动画,则需要使用更精确的双精度移动,并舍入为动画本身的整数,请使用 DateTime.Now 来非常精确地确定给定时间内行驶的距离,计时器不会t 确定距离,它只更新位置:
public partial class MainForm : Form
{
// X directional speed in pixels per second
const int XSpeed = 400;
private List<AnimationPanel> _panels = new List<AnimationPanel>();
public MainForm()
{
InitializeComponent();
}
private void OnButtonStartClick(object sender, System.EventArgs e)
{
AnimationPanel newPanel = new AnimationPanel
{
Bounds = new Rectangle(10, 10, 50, 50),
BorderStyle = BorderStyle.FixedSingle,
};
_panels.Add(newPanel);
Controls.Add(newPanel);
newPanel.StartBounds = newPanel.Bounds;
newPanel.StartTime = DateTime.Now;
_timer.Enabled = true;
}
private void OnTimerTick(object sender, System.EventArgs e)
{
for (int i = _panels.Count - 1; i >= 0; i--)
{
AnimationPanel currentPanel = _panels[i];
DateTime startTime = currentPanel.StartTime;
int xDelta = (int)Math.Round((DateTime.Now - startTime).TotalSeconds * XSpeed, 0);
Point newLocation = new Point(currentPanel.StartBounds.X + xDelta, currentPanel.StartBounds.Y);
// Check before or after collision (in this example before replacing the AnimationPanel)
if (newLocation.X > this.Width)
{
// I chose to remove after it reaches the edge, do whatever you want
_panels.RemoveAt(i);
Controls.Remove(currentPanel);
}
else
{
currentPanel.Location = newLocation;
}
}
if (_panels.Count == 0)
{
_timer.Enabled = false;
}
}
private class AnimationPanel : Panel
{
public Rectangle StartBounds { get; set; }
public DateTime StartTime { get; set; }
}
}
TA贡献1820条经验 获得超9个赞
您可以使用如下代码创建面板:
// init properties
var newPanel = new Panel
{
Name="Panel1",
BackColor = Color.Green,
Location = new Point(0, 0), // set the starting point
Width = 100, Height = 100
};
Controls.Add(newPanel);
- 3 回答
- 0 关注
- 110 浏览
添加回答
举报