Przytrzymany przycisk

0

Witam.

W mojej aplikacji ( window form ) mam przycisk który zwiększa pewną liczbę co naciśnięcie. Chciałbym również aby w przypadku przytrzymania przycisku zmienna się zwiększała do momentu jego puszczenia. Tego jednak nie potrafię zrobić. Mam boolowska zmienną odzwierciedlająca stan przycisku. Próbowałem w momencie wciśnięcia przycisku zwiększać zmienną do momentu jego wyciśnięcia w pętli while. Program się zapętla bo nie dochodzi do zdarzenie puszczenia przycisku. Jak spowodować przerwanie pętli, sprawdzenie stanu przycisku i w razie braku zmiany powrócić do pętli? Lub może mój sposób jest zły? Jest jakieś inne rozwiązanie problem?
Mam też drugie pytanie odnośnie tego problemu. Jak się domyślam w takiej pętli zmienna zwiększała by się bardzo szybko. Jak spowolnić ten proces bez haltowania wątku?

Z góry dziękuję za pomoc. Pozdrawiam

0

Tworzysz nowy watek, ktory startujesz w momencie wcisniecia przycisku, a zatrzymujesz w momencie puszczenia. W samym watku dajesz sleep i tam mozesz zdecydowac jak szybko wartosc bedzie sie zwiekszala (np. co pol sekundy).

pozdrawiam
johny

0

johny, to raczej nie zadziała, bo odpalenie wątku "zmrozi" wątek formatki, tak, że przycisk nie będzie się chciał "odcisnąć", przynajmniej tak było wczoraj jak napisałem to na szybko. Jeśli źle mówie to mnie popraw i pokaż kod, bo sam jestem ciekaw.

0
    public partial class Form1 : Form
    {
        int o = 0;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            o++;
            label1.Text = o.ToString();
            timer1.Enabled = false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            o++;
            label1.Text = o.ToString();
        }


        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            timer1.Enabled = true;
        }
    }

u mnie działa, jeśli oto chodziło..

0

To timer, mi chodziło o "rdzenny" wątek.

0
Lukke napisał(a)

To timer, mi chodziło o "rdzenny" wątek.

Dlatego pisalem o nowym watku :) Osobny dla formatki, osobny do zwiekszania.

pozdrawiam
johny

0

To tak robiłem i on właśnie zmrażał formatkę, weź napisz mi tu kod, bo może ja głupi jestem :)

0
Lukke napisał(a)

To tak robiłem i on właśnie zmrażał formatkę, weź napisz mi tu kod, bo może ja głupi jestem :)

Na formatce Label o nazwie CountLabel, przycisk o nazwie CountButton i zdarzeniach onMouseDown, onMouseUp:

		private Thread CountThread;
		private bool ThreadRunning = true;
		private int Count = 0;
		
		delegate void UpdateCount();
		
		private void UpdateLabel()
		{
			CountLabel.Text = (++Count).ToString();
		}
		
		private void CountWork()
		{
			while(ThreadRunning)
			{
				Invoke(new UpdateCount(UpdateLabel));
				Thread.Sleep(1000);
			}
		}
		
		
		void CountButtonMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(CountThread == null)
				ThreadRunning = true;
			CountThread = new Thread(new ThreadStart(CountWork));
			CountThread.Start();
		}
		
		void CountButtonMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			ThreadRunning = false;
			CountThread = null;
		}

pozdrawiam
johny

0

Mea maxima culpa, błąd był w tym, że głupio zrobiłem ten wątek (for(;;) i zatrzymywałem go i startowałem :D) - pisanie takich rzeczy o 5 nad ranem jednak mija się z celem. Dzięki za ten przykład, greengrassowi na pewno się przyda :)

0
johny_bravo napisał(a)
				
		void CountButtonMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			ThreadRunning = false;
			CountThread = null;
		}

A co sie dzieje z wątkiem przy Twoim MouseUp? Sam sie jakoś kończy? Nie trzeba .Abort() robić? Pytam bo napisałem tak jak Ty ale właśnie z tym .Abort(). Zbędne to jest?

0
greengrass napisał(a)

A co sie dzieje z wątkiem przy Twoim MouseUp? Sam sie jakoś kończy? Nie trzeba .Abort() robić? Pytam bo napisałem tak jak Ty ale właśnie z tym .Abort(). Zbędne to jest?

Konczy sie sam, bo petla dziala poki ThreadRunning == true. Abort i wszelkie takie metody przerywania watku sa malo skuteczne i malo pewne, bo nie wiadomo w jakim stanie jest watek w trakcie wywolania czegos takiego. Ja osobiscie wole, zeby watek skonczyl sie 'naturalnie', a nie brutalnie, zwlaszcza jezeli watek jest bardziej skomplikowany - wtedy moglibysmy przerwac go w polowie zestawu instrukcji - czyli cos zrobil, a czegos nie...

pozdrawiam
johny

0
johny_bravo napisał(a)

Konczy sie sam, bo petla dziala poki ThreadRunning == true.

Wnioskuje z tego, że wątek się kończy w momencie wyjścia z funkcji podanej przy inicjalizacji? Zostaje po nim jakiś ślad czy już się można o niego nie martwić?

0
greengrass napisał(a)

Wnioskuje z tego, że wątek się kończy w momencie wyjścia z funkcji podanej przy inicjalizacji? Zostaje po nim jakiś ślad czy już się można o niego nie martwić?

Tak, watek to w zasadzie tylko ta jedna metoda. Jak sie skonczy to mozna sie o niego juz nie martwic. Oczywiscie moment wyjscia z metody nie jest taki oczywisty, bo w momencie ustawiania ThreadRunning metoda moze byc w dowolnym miejscu petli - w tym wypadku maksymalny czas opoznienia to ok. 1s, bo tyle trwa jeden obieg petli. Dlatego warto byloby jakos sprawdzac czy w momencie MouseDown watek na pewno sie zakonczyl, ale moj przyklad nie to mial na wzgledzie. Zreszta to latwo sprawdzic - sprobuj szybko naciskac przycisk a predkosc zwiekszania wartosci powinna wzrosnac. Jesli chcesz ominac ten problem, to mozesz np. stworzyc klase reprezentujaca ten watek ze skladowa Running - wtedy kazdy watek bedzie sie odnosil do wlasnej skladowej i kazdy bedzie sie konczyl zawsze.

pozdrawiam
johny

1 użytkowników online, w tym zalogowanych: 0, gości: 1