【问题标题】:Move shape while key is down in WPF在 WPF 中按下键时移动形状
【发布时间】:2013-10-28 19:10:18
【问题描述】:

我想在用户按住某个键时在窗口中移动一个形状。 我是新手,所以我尝试了这种方法,但我无法从我的新线程中更改 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);
            }
        }

    }

【问题讨论】:

    标签: c# wpf multithreading transform keydown


    【解决方案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;
        }
    }
    

    【讨论】:

      【解决方案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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        • 2019-07-21
        • 2014-06-28
        • 1970-01-01
        • 2010-10-05
        相关资源
        最近更新 更多