You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Visual Studio中用C#实现Panel控件的缓慢移动效果?

Smooth Panel Animation for WinForms

Hey there! That instant jump definitely doesn't look polished—let's turn that into a nice, smooth slide animation. The issue with your current code is that you're setting the Top and Height properties directly, which updates the UI immediately. We need to break that change into tiny, incremental steps over time to create the illusion of fluid movement.

Here are two solid, easy-to-implement approaches for WinForms:

Option 1: Using a Timer (Classic WinForms Animation)

This is the traditional go-to for UI animations in WinForms. We'll use a System.Windows.Forms.Timer to nudge the panel's position and height in small chunks at regular intervals.

First, add a Timer to your form (drag it from the toolbox in the designer, or create it in code). Set its Interval to ~15ms—this controls smoothness: lower values mean smoother movement but more frequent UI updates.

Here's the updated code:

public partial class Form1 : Form
{
    // Store target values during animation
    private int _targetTop;
    private int _targetHeight;
    private const int AnimationStep = 5; // How much to move/resize per frame

    public Form1()
    {
        InitializeComponent();
        // Set up the animation timer
        animationTimer.Interval = 15;
        animationTimer.Tick += AnimationTimer_Tick;
        // Start with panel at btn1's position
        _ = MovePanelSmoothly(btn1);
    }

    private void AnimationTimer_Tick(object sender, EventArgs e)
    {
        bool animationDone = true;

        // Move panel toward target Top position
        if (Panel.Top < _targetTop)
        {
            Panel.Top += Math.Min(AnimationStep, _targetTop - Panel.Top);
            animationDone = false;
        }
        else if (Panel.Top > _targetTop)
        {
            Panel.Top -= Math.Min(AnimationStep, Panel.Top - _targetTop);
            animationDone = false;
        }

        // Resize panel toward target Height
        if (Panel.Height < _targetHeight)
        {
            Panel.Height += Math.Min(AnimationStep, _targetHeight - Panel.Height);
            animationDone = false;
        }
        else if (Panel.Height > _targetHeight)
        {
            Panel.Height -= Math.Min(AnimationStep, Panel.Height - _targetHeight);
            animationDone = false;
        }

        // Stop timer when we hit the target
        if (animationDone)
        {
            animationTimer.Stop();
            // Ensure we land exactly on target values
            Panel.Top = _targetTop;
            Panel.Height = _targetHeight;
        }
    }

    private void MovePanelSmoothly(Control targetControl)
    {
        // Cancel any ongoing animation first
        animationTimer.Stop();
        // Set new target values
        _targetTop = targetControl.Top;
        _targetHeight = targetControl.Height;
        // Start the animation
        animationTimer.Start();
    }

    private void btn1_Click(object sender, EventArgs e)
    {
        MovePanelSmoothly(btn1);
    }

    private void btn2_Click(object sender, EventArgs e)
    {
        MovePanelSmoothly(btn2);
    }

    private void btn3_Click(object sender, EventArgs e)
    {
        MovePanelSmoothly(btn3);
    }
}

Option 2: Using async/await (Cleaner, No Timer Required)

If you prefer a more modern approach without a timer, use async/await with Task.Delay to create a seamless animation loop:

public partial class Form1 : Form
{
    private const int AnimationStep = 5;
    private const int AnimationDelay = 15; // Milliseconds between each frame

    public Form1()
    {
        InitializeComponent();
        // Run initial animation safely
        _ = MovePanelSmoothly(btn1);
    }

    private async Task MovePanelSmoothly(Control targetControl)
    {
        int targetTop = targetControl.Top;
        int targetHeight = targetControl.Height;

        // Keep updating until we reach the target
        while (Panel.Top != targetTop || Panel.Height != targetHeight)
        {
            // Adjust Top position
            if (Panel.Top < targetTop)
                Panel.Top += Math.Min(AnimationStep, targetTop - Panel.Top);
            else if (Panel.Top > targetTop)
                Panel.Top -= Math.Min(AnimationStep, Panel.Top - targetTop);

            // Adjust Height
            if (Panel.Height < targetHeight)
                Panel.Height += Math.Min(AnimationStep, targetHeight - Panel.Height);
            else if (Panel.Height > targetHeight)
                Panel.Height -= Math.Min(AnimationStep, Panel.Height - targetHeight);

            // Pause briefly before next frame
            await Task.Delay(AnimationDelay);
        }
    }

    private async void btn1_Click(object sender, EventArgs e)
    {
        await MovePanelSmoothly(btn1);
    }

    private async void btn2_Click(object sender, EventArgs e)
    {
        await MovePanelSmoothly(btn2);
    }

    private async void btn3_Click(object sender, EventArgs e)
    {
        await MovePanelSmoothly(btn3);
    }
}

Quick Tips:

  • Tweak AnimationStep and AnimationDelay to adjust speed and smoothness: larger steps = faster movement, smaller delays = smoother animation.
  • Both approaches handle interruptions—if the user clicks another button mid-animation, the new target takes over right away.
  • In the async/await version, async void is acceptable for event handlers (a rare exception to the "avoid async void" rule).

内容的提问来源于stack exchange,提问作者Amr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 11:12:31