在 WPF 中按下键时移动形状

本文关键字:移动 WPF | 更新日期: 2023-09-27 18:37:22

我想在用户按住某个键时移动窗口中的形状。我是新手,所以我尝试了这种方法,但我无法改变圆圈。从我的新线程重新转换,因为它属于不同的线程。应该怎么做?

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

在 WPF 中按下键时移动形状

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

您可能只需使用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);
    }
}