Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 画布动画-不在循环中工作_C#_Wpf_Xaml - Fatal编程技术网

C# 画布动画-不在循环中工作

C# 画布动画-不在循环中工作,c#,wpf,xaml,C#,Wpf,Xaml,你好,我不能理解我的问题 private void StartReplay(object sender, RoutedEventArgs e) { for (int i = 0; i <= 40; i++) { if (leftCounter < 20) { leftCounter++; leftCounter2 = leftCoun

你好,我不能理解我的问题

private void StartReplay(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i <= 40; i++)
        {
            if (leftCounter < 20)
            {
                leftCounter++;
                leftCounter2 = leftCounter;
                Canvas.SetLeft(Kwadracik, leftCounter);
            }
            else
            {
                leftCounter2--;

                Canvas.SetLeft(Kwadracik, leftCounter2);
            }
        }
    }
private void StartReplay(对象发送方,路由目标)
{

对于(int i=0;i这是因为您可能正在从GUI线程调用StartReplay。线程处理仅在函数完成后继续。换句话说,在函数完成之前,GUI无法处理您的更改。当您在按钮单击处理程序(也是GUI线程)中放置更改时,您将退出函数,然后在GUI刷新之后cts改变了。这就是为什么第一种方法可以一点一点地工作

您可以做的是启动工作线程并在那里进行修改,或者因为这似乎是类似动画的行为,所以请使用计时器

更新: 例1:

Dispatchermer在调用线程中执行回调

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;


namespace CanvasAnimation
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        DispatcherTimer uiTimer;
        double directionDelta = 1.0;

        public MainWindow()
        {
            InitializeComponent();
            uiTimer = new DispatcherTimer(); //This timer is created on GUI thread.
            uiTimer.Tick += new EventHandler(uiTimerTick);
            uiTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000/25); // 25 ticks per second
            uiTimer.Start();
        }

        private void uiTimerTick(object sender, EventArgs e)
        {
            double currentLeft = Canvas.GetLeft(Kwadracik);

            if (currentLeft < 0)
            {
                directionDelta = 1.0;
            }
            else if (currentLeft > 80)
            {
                directionDelta = -1.0;
            }

            currentLeft += directionDelta;

            Canvas.SetLeft(Kwadracik, currentLeft);
        }
    }
}
使用系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Threading;
名称空间画布动画
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
调度员;
双向δ=1.0;
公共主窗口()
{
初始化组件();
uiTimer=new DispatcherTimer();//此计时器是在GUI线程上创建的。
uiTimer.Tick+=新事件处理程序(uiTimerTick);
uiTimer.Interval=新的时间跨度(0,0,0,0,1000/25);//每秒25次
uiTimer.Start();
}
私有void uiTimerTick(对象发送方,事件参数e)
{
double currentLeft=Canvas.GetLeft(Kwadracik);
如果(currentLeft<0)
{
方向δ=1.0;
}
否则如果(当前左>80)
{
方向增量=-1.0;
}
currentLeft+=方向增量;
Canvas.SetLeft(Kwadracik,currentLeft);
}
}
}
示例2:使用简单计时器

    using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace CanvasAnimation
{
    /// <summary>
    /// Interaction logic for WorkerTimer.xaml
    /// </summary>
    public partial class WorkerTimer : Window
    {
        Timer timer;
        double directionDelta = 1.0;

        public WorkerTimer()
        {
            InitializeComponent();
            timer = new Timer(this.timerTick, this, 0, 1000 / 25); // 25 fPS timer
        }

        protected void timerTick(Object stateInfo)
        {
            //This is not a GUI thread!!!!
            //So we need to Invoke delegate with Dispatcher
            this.Dispatcher.Invoke(new MoveCanvasDelegate(this.moveCanvas), null);
        }

        protected delegate void MoveCanvasDelegate();
        protected void moveCanvas()
        {
            //This function must be called on GUI thread!!!

            double currentLeft = Canvas.GetLeft(Kwadracik);

            if (currentLeft < 0)
            {
                directionDelta = 1.0;
            }
            else if (currentLeft > 80)
            {
                directionDelta = -1.0;
            }

            currentLeft += directionDelta;

            Canvas.SetLeft(Kwadracik, currentLeft);
        }
    }
}
使用系统;
使用系统线程;
使用System.Windows;
使用System.Windows.Controls;
名称空间画布动画
{
/// 
///WorkerTimer.xaml的交互逻辑
/// 
公共部分类WorkerTime:窗口
{
定时器;
双向δ=1.0;
公共工作人员()
{
初始化组件();
定时器=新定时器(this.timerTick,this,0,1000/25);//25 fPS定时器
}
受保护的void timerTick(对象状态信息)
{
//这不是GUI线程!!!!
//因此,我们需要使用Dispatcher调用委托
this.Dispatcher.Invoke(新的MoveCanvasDelegate(this.moveCanvas)),null;
}
受保护的委托void MoveCanvasDelegate();
受保护的void-moveCanvas()
{
//必须在GUI线程上调用此函数!!!
double currentLeft=Canvas.GetLeft(Kwadracik);
如果(currentLeft<0)
{
方向δ=1.0;
}
否则如果(当前左>80)
{
方向增量=-1.0;
}
currentLeft+=方向增量;
Canvas.SetLeft(Kwadracik,currentLeft);
}
}
}

同样的技术也适用于BackgroundWorker或其他非GUI线程。

是的,我正在从GUI启动它,因为我正在使用按钮。好的,你能告诉我如何在这种情况下使用计时器吗?我从来没有这样做过。我如何启动worker线程?我试图通过
任务将其置于任务中。运行
但我无法更新GUI,因为我遇到了该元素异常由其他线程拥有。有一个很好的Dispatchermer类,它在调用线程时执行回调。我将更新答案
    using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace CanvasAnimation
{
    /// <summary>
    /// Interaction logic for WorkerTimer.xaml
    /// </summary>
    public partial class WorkerTimer : Window
    {
        Timer timer;
        double directionDelta = 1.0;

        public WorkerTimer()
        {
            InitializeComponent();
            timer = new Timer(this.timerTick, this, 0, 1000 / 25); // 25 fPS timer
        }

        protected void timerTick(Object stateInfo)
        {
            //This is not a GUI thread!!!!
            //So we need to Invoke delegate with Dispatcher
            this.Dispatcher.Invoke(new MoveCanvasDelegate(this.moveCanvas), null);
        }

        protected delegate void MoveCanvasDelegate();
        protected void moveCanvas()
        {
            //This function must be called on GUI thread!!!

            double currentLeft = Canvas.GetLeft(Kwadracik);

            if (currentLeft < 0)
            {
                directionDelta = 1.0;
            }
            else if (currentLeft > 80)
            {
                directionDelta = -1.0;
            }

            currentLeft += directionDelta;

            Canvas.SetLeft(Kwadracik, currentLeft);
        }
    }
}