Forum » Pomoč in nasveti » Risanje upočasnjuje timer
Risanje upočasnjuje timer
Grizzly ::
Rabim en programerski nasvet. V okolju Visual Studio in programskem jeziku Visual C# proramiram neko aplikacijo (winform). Logika je takšna:
- ob loadanju forme preberem png sliko: Image i = Image.FromFile("png_datoteka");
- v intervalu 50ms se izvede funkcija komponente Timer ki osveži formo: this.Refresh();
- ob vsakem refreshu winforme se izriše png slika e.Graphics.DrawImage(i); in poleg tega se izvedejo še razne druge funkcije za risanje in izpisovanje teksta: FillRectangle, DrawString, DrawCircle, DrawLine itd.
Z vidika logike vse deluje kot mora. Je pa ena ovira: Risanje upočasnjuje timer oz. vpliva na vso ostalo kodo, ki sledi. Recimo da se slika png izriše v dimenzijah 800x600 px. Če timer prilagodim malo hitrejšemu procesorju (ki zmore to hitro opraviti), vse dela kot mora. Če pa to isto aplikacijo poženem na malo počasnejšem procesorju (recimo 5 let star računalnik), program dela 3-krat počasneje. Da bi se slika izrisala enako hitro tudi na počasnejšem procesorju, moram pomanjšat dimenzije slike. Tega pa ne bi rad, saj nočem, da je velikost elementov odvisna od hitrosti procesorja. Torej, pri isti velikosti slike bo en računalnik program izvajal neverjetno hitro, drugi morda ravno prav, tretji pa zelo počasi. Ta spremenljiva hitrost delovanja me moti.
Zanima me, kako pristopiti k temu? Se pravi, da hitrost izrisovanja slike (in vse kar sledi za tem) ne bo odvisna od hitrosti procesorja. Obstaja kakšna boljša rešitev, ki bo za vse procesorje približno enako zahtevna?
- ob loadanju forme preberem png sliko: Image i = Image.FromFile("png_datoteka");
- v intervalu 50ms se izvede funkcija komponente Timer ki osveži formo: this.Refresh();
- ob vsakem refreshu winforme se izriše png slika e.Graphics.DrawImage(i); in poleg tega se izvedejo še razne druge funkcije za risanje in izpisovanje teksta: FillRectangle, DrawString, DrawCircle, DrawLine itd.
Z vidika logike vse deluje kot mora. Je pa ena ovira: Risanje upočasnjuje timer oz. vpliva na vso ostalo kodo, ki sledi. Recimo da se slika png izriše v dimenzijah 800x600 px. Če timer prilagodim malo hitrejšemu procesorju (ki zmore to hitro opraviti), vse dela kot mora. Če pa to isto aplikacijo poženem na malo počasnejšem procesorju (recimo 5 let star računalnik), program dela 3-krat počasneje. Da bi se slika izrisala enako hitro tudi na počasnejšem procesorju, moram pomanjšat dimenzije slike. Tega pa ne bi rad, saj nočem, da je velikost elementov odvisna od hitrosti procesorja. Torej, pri isti velikosti slike bo en računalnik program izvajal neverjetno hitro, drugi morda ravno prav, tretji pa zelo počasi. Ta spremenljiva hitrost delovanja me moti.
Zanima me, kako pristopiti k temu? Se pravi, da hitrost izrisovanja slike (in vse kar sledi za tem) ne bo odvisna od hitrosti procesorja. Obstaja kakšna boljša rešitev, ki bo za vse procesorje približno enako zahtevna?
DamijanD ::
v čem je fora vsakih 50ms? A ne bi to mogel vezati na nek event pač, da se naredi refresh, ko je treba?
Grizzly ::
50ms je interval, v katerem lahko pride do spremembe. Vsakih 50ms se sproži Timer. Potem se izvede zaporedje nekih funkcij, ki preverijo stanje in v primeru spremembe se naredi še refresh. Tudi če se kdaj refresh ne naredi, se naredi najkasneje vsakih 200ms. Povprečno se v sekundi slika zamenja 5-krat... mogoče ne cela slika, ampak samo neka podrobnost in zato moram cel postopek izrisovanja ponavljat.
GupeM ::
Timer naj ti teče v ločenem threadu, ne v istem threadu, kot se slika izrisuje. Vendar, če računalnik ni sposoben izrisati slike v 50ms, se slika ne bo izrisala oz bo le ta pomanjkljiva. Zato moraš pred refreshom vedno preveriti, če se je prejšnji izris zaključil. Če da, začni risati znova in restartaj timer, če ne, samo restartaj timer.
Grizzly ::
Odločil sem se preizkusiti še malenkost drugačen pristop. Sedaj sem risanje nadomestil s PictureBox-i. Backround (katerega risanje je prej vzelo kar nekaj časa) je sedaj PictureBox in se ne spremeni - s tem nimam dela, razen če uporabnik spremeni nastavitev in je treba prikazati drugo sliko. Na background PictureBox-u imam razporejenih 40 do 50 manjših PictureBox-ov. Ob vsaki iteraciji timerja:
- resetiram sliko na teh pictureboxih (to pomeni celoten picturebox prebarvam z osnovno barvo)
- na določenih pictureboxih nastavim drugo ozadje (kvadratek druge barve) in vanj izpišem nek znak
Prej sem zaradi osveževanja teh manjših "kvadratkov" moral v vsaki iteraciji timerja izrisati še background, saj ga klic funkcije Refresh() odstrani - tu sem zgubil večino časa. Sedaj je background statičen, rišem pa samo v textboxe. Pomoje bi stvar morala delati hitrejše in v manjši odvisnosti od hitrosti procesorja. Nimam še pretestirano, ampak logika drži.
- resetiram sliko na teh pictureboxih (to pomeni celoten picturebox prebarvam z osnovno barvo)
- na določenih pictureboxih nastavim drugo ozadje (kvadratek druge barve) in vanj izpišem nek znak
Prej sem zaradi osveževanja teh manjših "kvadratkov" moral v vsaki iteraciji timerja izrisati še background, saj ga klic funkcije Refresh() odstrani - tu sem zgubil večino časa. Sedaj je background statičen, rišem pa samo v textboxe. Pomoje bi stvar morala delati hitrejše in v manjši odvisnosti od hitrosti procesorja. Nimam še pretestirano, ampak logika drži.
jernejl ::
Risanje po formi ne velja za zelo hitro. Obstaja pa nekaj možnosti, kako zadevo narediti bolj optimalno.
Graphics.InterpolationMode lahko recimo nastaviš na NearestNeighbor.
Pri izrisovanju se izogibaš vsakokratnemu risanju celotne površine. Veliko bolje je osveževati zgolj tiste dele slike, ki se spremenijo. Namesto Refresh() torej InvalidateRect(...) (mislim da se tako reče).
še nekaj nasvetov
Graphics.InterpolationMode lahko recimo nastaviš na NearestNeighbor.
Pri izrisovanju se izogibaš vsakokratnemu risanju celotne površine. Veliko bolje je osveževati zgolj tiste dele slike, ki se spremenijo. Namesto Refresh() torej InvalidateRect(...) (mislim da se tako reče).
še nekaj nasvetov
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [c#] ukaz radirkaOddelek: Programiranje | 1112 (905) | japol |
» | [c#] picturebox, slika na slikoOddelek: Programiranje | 1085 (895) | japol |
» | [c#] Risanje z miškoOddelek: Programiranje | 1429 (1110) | japol |
» | [c#] Slika iz URLOddelek: Programiranje | 2615 (2202) | MrBrdo |
» | video v c#Oddelek: Programiranje | 1536 (1076) | boss-tech |