C# C语言中的动态图像#

C# C语言中的动态图像#,c#,image,C#,Image,我需要写一个代码,在点击一个按钮后将图片1移动到屏幕顶部。Picture1到达屏幕顶部20个像素后,屏幕必须变为不可见,并使picture2可见。这是我的错误代码: private void button1_Click(object sender, EventArgs e) { int b = pictureBox1.Top; for (int i = b; i < 20; i--) { pictureBox1.Top = i; S

我需要写一个代码,在点击一个按钮后将图片1移动到屏幕顶部。Picture1到达屏幕顶部20个像素后,屏幕必须变为不可见,并使picture2可见。这是我的错误代码:

private void button1_Click(object sender, EventArgs e)
{
    int b = pictureBox1.Top;

    for (int i = b; i < 20; i--)
    {
        pictureBox1.Top = i;
        System.Threading.Thread.Sleep(20);
    }

    if (pictureBox1.Top < 20)
    {
        pictureBox1.Visible = false;
        pictureBox2.Visible = true;
    }
}
private void按钮1\u单击(对象发送者,事件参数e)
{
int b=pictureBox1.Top;
对于(int i=b;i<20;i--)
{
pictureBox1.Top=i;
系统线程线程睡眠(20);
}
如果(图B1.Top<20)
{
pictureBox1.Visible=false;
pictureBox2.Visible=true;
}
}

有什么办法可以解决吗?

在完成
pictureBox1.Top
作业后,请拨打:

this.Invalidate();
this.Refresh();

假设您正在使用WinForms。

在完成
pictureBox1.Top
分配后,请调用:

this.Invalidate();
this.Refresh();
假设您正在使用WinForms。

这似乎是错误的:

for (int i = b; i < 20; i--)
{
    pictureBox1.Top = i;
    System.Threading.Thread.Sleep(20);
}
总而言之,以下应该可以工作(我还稍微修改了代码以使其更清晰):


上面代码的问题是它阻塞了UI。为了保持它的响应性,我将使用如下计时器:

private void button1_Click(object sender, EventArgs e)
{    
    // Create a threaded timer
    System.Timers.Timer animationTimer = new System.Timers.Timer();
    animationTimer.Interval = 20;
    animationTimer.AutoReset = false; // Only one Ping! We'll activate it if necessary
    animationTimer.Elapsed += new ElapsedEventHandler(AnimationStep);
    animationTimer.Start();

    // Disable the button also, because we don't want another timer instance to
    // interfere with our running animation
    button1.Enabled = false;
}
然后,创建计时器触发时调用的事件:

private void AnimationStep(object source, ElapsedEventArgs e)
{
    // The following code needs to be executed in the context of the UI thread.
    // We need to use this.Invoke in Forms or this.Dispatcher.Invoke in WPF
    this.Invoke((Action)delegate()
    {
        // Move picture. Note that we don't need to update the display here
        // because the UI thread gets time to do its work while the timer waits
        // to fire below
        if (pictureBox1.Top > 20)
            pictureBox1.Top--;

        // Show other picture maybe. I use <= here because initially, the
        // position of the picture box may already smaller than 20.
        if (pictureBox1.Top <= 20)
        {
            pictureBox1.Visible = false;
            pictureBox2.Visible = true;
        }

        // Or let the timer fire again if we still need to animate
        else
        {
            (source as System.Timers.Timer).Start();
        }
    }
}
private void AnimationStep(对象源,ElapsedEventArgs e)
{
//以下代码需要在UI线程的上下文中执行。
//我们需要在表单中使用this.Invoke或在WPF中使用this.Dispatcher.Invoke
调用((操作)委托()
{
//移动图片。请注意,我们不需要更新此处的显示
//因为UI线程在计时器等待时有时间完成其工作
//在下面开火
如果(图1.Top>20)
图1.Top--;
//可能会显示其他图片。我使用这似乎是错误的:

for (int i = b; i < 20; i--)
{
    pictureBox1.Top = i;
    System.Threading.Thread.Sleep(20);
}
总而言之,以下应该可以工作(我还稍微修改了代码以使其更清晰):


上述代码的问题在于它会阻塞UI。为了保持其响应性,我将使用一个计时器,如下所示:

private void button1_Click(object sender, EventArgs e)
{    
    // Create a threaded timer
    System.Timers.Timer animationTimer = new System.Timers.Timer();
    animationTimer.Interval = 20;
    animationTimer.AutoReset = false; // Only one Ping! We'll activate it if necessary
    animationTimer.Elapsed += new ElapsedEventHandler(AnimationStep);
    animationTimer.Start();

    // Disable the button also, because we don't want another timer instance to
    // interfere with our running animation
    button1.Enabled = false;
}
然后,创建计时器触发时调用的事件:

private void AnimationStep(object source, ElapsedEventArgs e)
{
    // The following code needs to be executed in the context of the UI thread.
    // We need to use this.Invoke in Forms or this.Dispatcher.Invoke in WPF
    this.Invoke((Action)delegate()
    {
        // Move picture. Note that we don't need to update the display here
        // because the UI thread gets time to do its work while the timer waits
        // to fire below
        if (pictureBox1.Top > 20)
            pictureBox1.Top--;

        // Show other picture maybe. I use <= here because initially, the
        // position of the picture box may already smaller than 20.
        if (pictureBox1.Top <= 20)
        {
            pictureBox1.Visible = false;
            pictureBox2.Visible = true;
        }

        // Or let the timer fire again if we still need to animate
        else
        {
            (source as System.Timers.Timer).Start();
        }
    }
}
private void AnimationStep(对象源,ElapsedEventArgs e)
{
//以下代码需要在UI线程的上下文中执行。
//我们需要在表单中使用this.Invoke或在WPF中使用this.Dispatcher.Invoke
调用((操作)委托()
{
//移动图片。请注意,我们不需要更新此处的显示
//因为UI线程在计时器等待时有时间完成其工作
//在下面开火
如果(图1.Top>20)
图1.Top--;

//可能显示其他图片。我使用如果最初
b
大于20怎么办?循环不会运行,因为循环中的条件是
I<20
。因为循环没有运行,所以不会发生任何事情

考虑更改循环中的条件。在减少
Top
-属性时,您可能希望图片向上移动。假设最初pictureBox1的顶部为40。以下代码将起作用:

while(pictureBox1.Top >= 20)
{
    pictureBox1.Top--;
    System.Threading.Thread.Sleep(20);
    Invalidate();
    Refresh();
}
由于Top现在小于20,因此可以省略if语句,只需调用:

pictureBox1.Visible = false;
pictureBox2.Visible = true;
完整代码:

while(pictureBox1.Top >= 20)
{
    pictureBox1.Top--;
    System.Threading.Thread.Sleep(20);
    Invalidate();
    Refresh();
}

pictureBox1.Visible = false;
pictureBox2.Visible = true;

如果最初
b
大于20会怎样?循环不会运行,因为循环中的条件是
i<20
。因为循环没有运行,所以不会发生任何事情

考虑更改循环中的条件。在减少
Top
-属性时,您可能希望图片向上移动。假设最初pictureBox1的顶部为40。以下代码将起作用:

while(pictureBox1.Top >= 20)
{
    pictureBox1.Top--;
    System.Threading.Thread.Sleep(20);
    Invalidate();
    Refresh();
}
由于Top现在小于20,因此可以省略if语句,只需调用:

pictureBox1.Visible = false;
pictureBox2.Visible = true;
完整代码:

while(pictureBox1.Top >= 20)
{
    pictureBox1.Top--;
    System.Threading.Thread.Sleep(20);
    Invalidate();
    Refresh();
}

pictureBox1.Visible = false;
pictureBox2.Visible = true;


它的哪一部分是错误的?与您期望它的行为相比,它现在的行为如何?它没有错误,只是不起作用。我单击按钮后什么也没有发生。您是否已将代码作为调试过程的一部分进行了检查?到目前为止,任何人都无法猜测。甚至可能根本没有启动此事件处理程序。请验证当它被启动时,然后通过步骤检查所有整数的值等。当你调用<代码>睡眠< /代码>时,GUI没有机会更新布局,因为线程被阻塞。考虑创建另一个线程来移动图片,或者使用一个定时器。它是错误的?与您期望的行为相比,它现在的行为如何?它没有错误,只是不起作用。我单击按钮后什么也没有发生。您是否在调试过程中逐步完成了代码?到目前为止,任何人都在猜测。甚至可能根本没有启动此事件处理程序。请验证它是否正在启动当你调用<代码>睡眠>代码时,GUI没有机会更新布局,因为线程被阻塞了。考虑创建另一个线程来移动图片,或者使用一个定时器。@ DeaMAC,如果你减去循环变量,它们是不可接受的。ried操作代码。Sleep语句使UI响应非常慢,但一旦睡眠完成,图片将立即更新。@jac整个循环使UI无法响应。这不是我怎么做的,而是他的代码。是的,因为我需要将其移动到顶部,我需要I>=20。如果需要,我真的不需要。谢谢你的帮助st answer。@Noterezeck我将用一种不阻塞UI的方法更新我的答案。给我几分钟时间写下来。不是downvoter,而是我尝试了操作代码。Sleep语句使UI响应非常慢,但图片将在睡眠完成后立即更新。@jac整个循环使UI无法响应nd.这不是我怎么做的,但这是他的代码。是的,因为我需要把它移到顶部,所以我需要我>=20。如果需要的话,我真的不需要。谢谢你的快速回答。@Noterezeck我会用一种方法更新我的答案,而不需要