Как увеличить числовую метку при нажатой кнопке мыши? - PullRequest
0 голосов
/ 07 февраля 2019

C # Повторный вызов функции для автоматического увеличения значения метки

Это программа WPF.На нем есть метка (minuteTimerLabel), которая отображает двузначное число, начиная с 00, 01, 02 и т. Д. До 99. Мне нужны две функции из этой метки.Во-первых, когда левая кнопка мыши поднимается на ярлыке (имитируя щелчок), число увеличивается на 1. Я смог реализовать это.Но у меня есть проблема со второй функцией.

    private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        while(true)
        {
            if (timerMinute == 99)
            {
                return;
            }
            timerMinute += 1;
            minuteTimerLabel.Content = String.Format("{0:00}", timerMinute);
            Thread.Sleep(250);
        }
    }

Когда левая кнопка мыши удерживается на ярлыке в течение нескольких секунд, число должно увеличиваться автоматически по одному.timerMinute - это глобальная переменная типа int.С моим текущим кодом вся программа блокируется и ничего не работает.Когда я удаляю while (true), число увеличивается только один раз при нажатии мыши вниз.Если я отпущу мышь и нажму снова, она будет работать, но снова только один раз.

Ответы [ 4 ]

0 голосов
/ 07 февраля 2019

Чтобы избежать блокировки пользовательского интерфейса, вам нужно использовать некоторую форму асинхронного кодирования.Я бы предложил использовать Microsoft Reactive Framework.

NuGet "System.Reactive.Windows.Threading", чтобы получить биты и добавить using System.Reactive.Linq; в начало вашего кода.

Тогда вы можетесделать это:

    private IDisposable _subscription = null;

    private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _subscription =
            Observable
                .Interval(TimeSpan.FromMilliseconds(250.0))
                .Select(x => String.Format("{0:00}", x))
                .ObserveOnDispatcher()
                .Subscribe(x => MinuteTimerLabel.Content = x);
    }

    private void MinuteTimerLabel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _subscription.Dispose();
    }

Это супер просто и супер чисто.


private IDisposable _subscription = null;

private int _counter = 0;

private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    _subscription =
        Observable
            .Interval(TimeSpan.FromMilliseconds(250.0))
            .Select(x => String.Format("{0:00}", x))
            .ObserveOnDispatcher()
            .Subscribe(x => MinuteTimerLabel.Content = _counter++ % 100);
}

private void MinuteTimerLabel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    _subscription.Dispose();
}
0 голосов
/ 07 февраля 2019

Попробуйте следующий код:

Код будет выполняться в другом потоке, разблокируя Main Thread.

private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    new Thread(Timer).Start();
}

private void Timer() {
    while(true)
    {
        if (timerMinute == 99)
        {
            return;
        }
        timerMinute += 1;
        minuteTimerLabel.Content = String.Format("{0:00}", timerMinute);
        Thread.Sleep(250);
    }
}
0 голосов
/ 07 февраля 2019

Хорошо подходит для CancellationToken и Async Await Pattern

private CancellationTokenSource _cs;
private int _timerMinute =0;

private async void Label1_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   _cs?.Cancel();
   _cs?.Dispose();
   _cs = new CancellationTokenSource();
   try
   {
      while (!_cs.Token.IsCancellationRequested)
      {
         await Task.Delay(200, _cs.Token);

         Label1.Content = $"{++_timerMinute:00}";
      }
   }
   catch (OperationCanceledException) {}
}

private void Label1_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   _cs?.Cancel();
   _cs?.Dispose();
}

Также, если вы хотите быть хитрым, вы можете прибавить в весе, чем больше мышь вниз,изменение задержки

0 голосов
/ 07 февраля 2019

Вам необходимо привязать пару событий в этом случае, PreviewMouseDown и PreviewMouseUp.Затем вычислите различное время и увеличьте значение метки на тиках / сек.

Как это

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        PreviewMouseDown += Window3_PreviewMouseDown;
        PreviewMouseUp += Window3_PreviewMouseUp;
    }

    DateTime mouseDown;
    private void Window3_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        mouseDown = DateTime.Now;
    }

    private void Window3_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        var seconds = DateTime.Now.Subtract( mouseDown ).Seconds;

        //Condition code goes here..
        minuteTimerLabel.Content = seconds;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...