在WPF中按键时向下移动形状

时间:2013-10-28 19:10:18

标签: c# wpf multithreading transform keydown

我想在用户按住键的同时在窗口中移动形状。 我是新手,所以我尝试了这种方法,但我不能改变circle.RederTransform来自我的新线程,因为它属于不同的线程。应该怎么做?

    public partial class MainWindow : Window
    {
        private Matrix transformationMatrix = Matrix.Identity;
        private Thread myThread = null;
        private bool isGoing = false;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            isGoing = true;
            myThread = new Thread(HandleMyThread);
            myThread.Start();
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            isGoing = false;
        }

        private void HandleMyThread(object obj)
        {
            while(isGoing)
            {
                transformationMatrix.Translate(10, 0);
                circle.RenderTransform = new MatrixTransform(transformationMatrix);
                Thread.Sleep(50);
            }
        }

    }

2 个答案:

答案 0 :(得分:1)

在WPF中,您希望将System.Windows.Threading.DispatcherTimer类用于UI线程安全计时器。

以下是一个例子:

public partial class MainWindow : Window
{
    private DispatcherTimer _timer;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnContentRendered(EventArgs e)
    {
        base.OnContentRendered(e);

        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromMilliseconds(50);
        _timer.Tick += timer_Tick;

    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        _timer.Start();
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        _timer.Stop();
    }

    private void timer_Tick(object sender, EventArgs e)
    {
        transform.X += 2;
        transform.Y += 2;
    }
}

答案 1 :(得分:0)

你可以通过使用Invoke来做到这一点......但是有更好的方法可以做你想做的事。

首先,每次处理KeyDown时创建一个线程都是低效的...并且可能导致问题......因为创建和安排Thread可能需要一段时间......因此延迟你的“事物”移动。

此外,您可能会因为存在多个线程而陷入困境。例如,假设有人反复按下并释放密钥....在这种情况下,“旧”线程仍然可以继续运行......因为isGoing标志是真的....换句话说,同步很差。

private void HandleMyThread(object obj)
{
    Action action = new Action( ()=>
    {
        transformationMatrix.Translate(10, 0);
        circle.RenderTransform = new MatrixTransform(transformationMatrix);
    };

    while(isGoing)
    {
        this.Dispatcher.Invoke(DispatcherPriority.Normal, action);
        Thread.Sleep(50);
    }
}