为了账号安全,请及时绑定邮箱和手机立即绑定

如何动态创建移动面板

如何动态创建移动面板

C#
www说 2023-08-13 10:11:45
我目前正在 x 轴上创建一个由按钮触发的移动面板,winform它工作得很好,但现在我想在每次单击按钮时添加多个面板。问题是我通过工具箱创建了面板并将其附加在 a 上timer_tick event,我相信这只能完成一次,所以我的计划是创建一个动态面板和计时器不知道它是否是正确的方法。这是我的代码   private void button2_Click(object sender, EventArgs e)     {            start();     }     private void start(){        timer1.Enabled = true;    }    private void timer1_Tick(object sender, EventArgs e )    {        panel_1.BackColor = Color.Green;        int x = panel_1.Location.X;        int y = panel_1.Location.Y;        panel_1.Location = new Point(x + 25, y);        xy_text.Text = x + ","+ y;        if (x > this.Width)        {            timer1.Stop();        }    }
查看完整描述

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如果您不再使用不可见的面板,您应该考虑实现一些逻辑,将其从集合中删除。


查看完整回答
反对 回复 2023-08-13
?
Qyouu

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; }

    }

}


查看完整回答
反对 回复 2023-08-13
?
慕妹3146593

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);


查看完整回答
反对 回复 2023-08-13
  • 3 回答
  • 0 关注
  • 80 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信