[DELPHI] Odświeżanie Label

0

Witam, mam taki oto kodzik:

w Timerze
======== 
Label_StatusBar.Update; //mam wrażenie że trochę pomogło, ale błąd pojawia się nadal tylko że rzadziej.
if not (Label_StatusBar.Kind.Color=RGB(255,255,255)) then Label_StatusBar.Kind.Color:=Label_StatusBar.Kind.Color+RGB(10,10,10);
if not (Label_StatusBar.Shadow.Color=RGB(0,0,0)) then Label_StatusBar.Shadow.Color:=Label_StatusBar.Shadow.Color-RGB(5,5,5);
if (Label_StatusBar.Kind.Color=RGB(255,255,255)) and (Label_StatusBar.Shadow.Color=RGB(0,0,0)) then Animation_StatusBar.Enabled:=False;
 
w OnEnter
=========
Label_StatusBar.Visible:=False;
Label_StatusBar.Kind.Color:=RGB(85,85,85);
Label_StatusBar.Shadow.Color:=RGB(85,85,85);
Label_StatusBar.Visible:=True;
Refresh_StatusBar.Enabled:=True; //to jest ten timer powyżej.

I teraz kilka słów wyjaśnień. Label_StatusBar to taki podrasowany label, który potrafi rzucać cień. Poprzez Kind zmieniam kolor samego napisu a przez Shadow kolor cienia.
Chcę osiągnąć taki efekt, że po najechaniu myszą w odpowiednie miejsce wyłoni się napis, ale nie w ten sposób że po prostu się pojawi, lecz coś na kształt animacji (jakby blending). Zrobiłem więc że w chwili najechania nań myszą, zmienia mu się kolor na taki jak ma tło programu (czyli w RGB 85,85,85), a potem timer stopniowo przywraca mu właściwą, barwę (255,255,255 - biały, dla napisu i 0,0,0 - czarny, dla cienia. Timer ma ustawioną szybkość na 25 milisekund. Dla cienia przeskakuje o 5 jednostek, a dla napisu o 10, bo akurat od 85 do 255 jest 170, czyli 2 razy więcej niż dla cienia który musi pokonać drogę od 85 do 0. Dlatego też napis musi zmieniać barwę 2x szybciej by była właściwa synchronizacja). Efekt jest bardzo ładny i wygląda dokładnie tak jak chciałem, ale niestety pojawia się pewien problem. Co jakiś czas (nie zawsze), podczas animacji napis na chwilę znika całkowicie a potem znów się pojawia (dosłownie na ułamek sekundy, ale jest to widoczne), a później animacja leci dalej już normalnie. Podejrzewam że jest to jakiś repaint czy refresh labela, ale nie wiem jak z tym walczyć... Co można zrobić?

PS. Ten komponent DoubleBuffer nie obsługuje.

0

Timer ma minimalny interwał zdaje się 100 ms i nie nadaje się do takich zastosowań. Weź jakiś wątek, pętla, sleep i TickCount.
A to ze znikaniem najpewniej zniwelujesz Application.ProcessMessages, o ile dobrze oprogramujesz :)

0

Może się nie nadaje, ale działa ;) A Application.ProcessMessages użyłem już wcześniej - nie pomogło... A timer z tego co widzę działa w rozpiętości 1-1000 MS, i obsługuje wszystkie te wartości.

0

W Delphi 7 Timer jeszcze mial minimalny interval 100, można było ustawić mniej, ale i tak z tego
co się orientuje kod będzie się wykonywał co 100 milisekund, więc lepszym rozwiązaniem według
mnie jest zastosowanie wątku, w ktorym odstęp czasu, na pewno może być mniejszy niż 100 ms.

0

A ja wam powtarzam - mylicie się ;) Pobawcie się ustawieniami interwału, czy to 1, 25, 100 czy 200 - za każdym razem widać różnicę (zauważalna gołym okiem). Z resztą nie o to chodzi, potrzebuję usunąć to migotanie, z timerem nie ma problemów.

2

Gościu, jak wiesz lepiej, to po co pytasz?
Mówimy Ci, że timer nie działa częściej niż z interwałem 100ms. Jak zrobisz 5 ms, to on i tak będzie działał w okolicy 100ms.
Zrób to w osobnym wątku tak, jak napisałem wyżej.

0

Zrozum, ja się nie chcę kłócić, ale Timer DZIAŁA także w interwałach poniżej 100 MS, ślepy nie jestem. Gołym okiem widać różnicę pomiędzy takim 18 49 czy 78, jak nie wierzysz to sprawdź sobie eksperymentalnie. WIDAĆ RÓŻNICĘ, CO ZNACZY ŻE POSZCZEGÓLNE INTERWAŁY W PRZEDZIALE 1-100 SĄ W PEŁNI OBSŁUGIWANE! (ustawiam sobie prędkość animacji i zwyczajnie widzę że się zmienia, dla 25 jest zupełnie inna niż dla 35, a jeszcze inna jest dla 105, więc D.Z.I.A.Ł.A). Chodzi mi jedynie i wyeliminowanie migotania, które pojawia się sporadycznie podczas wyświetlania animacji, i jestem na 99% pewien że nie ma ono nić wspólnego z timerem, lecz z odświeżaniem labela. Kapisz? Chodzi mi o to że nie wiem ja temu zaradzić (np. odświeżyć labela na chwilę przed wyświetleniem animacji, tak by w jej trakcie nie musiało do tego dochodzić). Od timera się odczepcie, bo to nie w nim jest problem, może to mało wydajne rozwiązanie, ale działa i mnie zadowala.

EDIT

Przeprowadziłem kilka testów, z których jasno wynika że Timer ma pewien minimalny interwał, ale bynajmniej nie 100, lecz 15 MS... Ten mały programik mojej roboty pomoże to zobrazować (spokojnie to nie żaden wirus czy trojan, przeskanujcie sobie):

http://rapidshare.com/files/430369744/TEST_TIMERA.rar

W Interval wrzucamy oczywiście interwał ruchu kropki, a w stoper szybkość licznika. Wciskamy start i odczytujemy wyniki. Wpisanie interwału z zakresu 1-15 daje zawsze taki sam wynik (w przypadku stopera także), ale już 16 i więcej MS daje wynik WYRAŹNIE inny niż wcześniejsze...

Mam nadzieję że to rozwieje wasze wątpliwości. Niemniej to nie na tym polega mój problem, Timer robi co do niego należy, problemem jest MIGOTANIE wywołane najprawdopodobniej odświeżaniem labela.

0

@Crow już dobrze, oddychaj, spokojnie... :) Ja generalnie już dawno nauczyłem się, że z Juhasem nie ma co dyskutować - on jak sobie coś do łba wbije to choćbyś mu to narysował, to i tak wie swoje.
A co do Twojego pytania to ustaw DoubleBuffered na True dla elementu, na którym leży labelka (ważne, jeśli label jest na panelu to trzeba ustawić DoubleBuffered właśnie dla panelu a nie dla formy!)

1
Misiekd napisał(a)

@Crow już dobrze, oddychaj, spokojnie... :) Ja generalnie już dawno nauczyłem się, że z Juhasem nie ma co dyskutować - on jak sobie coś do łba wbije to choćbyś mu to narysował, to i tak wie swoje.

Eat this:

The standard VCL TTimer component is a wrapper for the Windows API timer functions SetTimer and KillTimer. TTimer simplifies the processing of the WM_TIMER messages by converting them into OnTimer events. A timer based on WM_TIMER message processing cannot provide a resolution better than 10 milliseconds. And even when the timer interval is set to tens of milliseconds, the actual timer intervals are noticeably higher(...).

http://sergworks.wordpress.com/2010/04/06/a-better-timer-for-a-delphi-programmer/

Whatever you do, don't use TTimer! It sucks big-time because it's based on the Windows WM_TIMER message. This is low-priority, meaning that TTimer only guarantees worse than 55msec per update. If you set its interval to less than 55 msecs (e.g. 1000/30 = timer w/ 33 interval for 30fps), it won't always update that quickly, meaning that your animation gets jerky. I suspect this mistake is common(...)

http://www.pascalgamedevelopment.com/showthread.php?88-Implementing-a-Game-Loop-in-Delphi - 4ty post

Windows timer messages also aren’t suited for timing beyond a few events. A high volume of timer messages can clog up your WinProc message queue, making your UI less responsive if you’re handling them in the main thread. WM_TIMER is also defined as a low-priority message, which means delivery is postponed until no higher priority messages are in your message queue. The delay between the expected firing of the event and when the WM_TIMER actually arrives also may make the timer unsuitable for your application due to its imprecision.

http://capnbry.net/blog/?p=44

Jak każdy wie TTimer jest niedokładny. Przy większym obciążeniu procesora słabnie. Po drugie zauważyłem, że na każdym komputerze działa z różną prędkością. Do pewnego czasu nie przeszkadzało mi to. Jak zacząłem robić możliwość gry przez Internet to różnica w prędkości Timera dała się we znaki.

http://forum.unit1.pl/lofiversion/index.php/t645.html

Mogę tak do jutra.
Podsumowując, jeśli Timer z takim interwałem Ci działa, nikt Ci nie zagwarantuje, że zadziała na innym kompie i/lub w innych warunkach. Z doświadczenia wiem, że w zwykłym timerze lepiej poniżej 100ms nie schodzić(przynajmniej jeśli chodzi o Windows XP, nie wiem, jak sprawa wygląda w innych systemach, ale podejrzewam, że w nowszych jest podobnie lub tak samo). Oczywiście dużo zależy też od procesora.

0

tak Juhas wiemy jaki jesteś mądry i wspaniały, Twoją figurę wystawimy jeszcze wspanialszą niż tą, którą postawili w Świebodzinie i będziemy ją czcić...
Po pierwsze to skoro pytaczowi wystarcza timer to co mu się na siłę wpierdalasz z textem jaki to ten timer jest zły i do d**y?? Po drugie pytanie wcale nie było o timer! Crow pyta co zrobić, żeby mu labelka nie migała. Kumasz czy ci rozrysować? Masz tendencję do odpowiadania nie na temat i trzymasz się tego jak rzep psiego ogona.
Zamiast tego czy chociaż spróbowałeś pomóc Crow'ie w jego problemie? - nie, wolisz dalej z uporem maniaka truć o timerze i jaki to on be...

0

Nie czytałem całego pytania, ale tak się zastanawiam, czy nie było by Ci lepiej malować po TPaintBox'ie ? Dodatkowo twórz sobie bitmapkę w pamięci - na niej malujesz a jak skończysz to ją podmieniasz. Timer może sobie gdzieś tam chodzić i zmieniać jakieś parametry które wpływają na to co malujesz. Cień - przynajmniej taki prosty - można zrobić banalnie - rysujesz szary tekst przesunięty w prawo i w dół o 1-2 px, a potem właściwy na swoim miejscu.

Pozdrawiam
b

0

Misiekd - dzięki, dokładnie o to mi chodziło. Zwyczajnie nie sądziłem że wystarczy wrzucić buforowanie dla komponentu pod labelem ;). Też właśnie widzę że Juhas jakiś nie kumaty, jak mu powtarzam że timer to nie problem a on nadal swoje ;D

b0bik - Odpada właśnie z powodu tego cienia. To nie jest taki prosty efekt, tylko rzekł bym profesjonalny (ładnie rozmyty, półprzezroczysty) i pochodzi z komponentu. Jak dla mnie za dużo roboty by to malować samodzielnie.

Juhas - tak się składa że testowane to było na 3 kompach (mocny Intel I7 pod Windows 7, starszy Athlon Core 2 na XP i dosyć stary lapek też na XP). Wszędzie działa tak samo (interwał 25 MS jak najbardziej obsługiwany), tyle tylko że na lapku za bardzo spowalnia procesor, dlatego też ustawiłem w opcjach że animacje można wyłączyć ;)

0

Mi zawsze label miga, gdy umieszczę go na pagecontrol i użyje komponentu XPMan. Pomoże to Form1.DoubleBuffered := True;

0

Przede wszystkim błędem jest sprawdzanie koloru i odwoływanie się w ten sposób do jego zmiany.
Lepszym rozwiązaniem jest zastosowanie zmiennej i to przez nią sprawdzać różnicę kolorów. Możesz też użyć właściwości Tag od tego labela.

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