Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno C# - problém s jednorázovým vytvorením Bitmap

V C# mám formulár a na ňom obrázok. Pred kreslením do obrázka musím vytvoriť kresliacu plochu:

picture1.Image = new Bitmap(200, 200);

Do obrázku sa kreslí vždy, ak sa na formulári stlačí tlačítko, takže ak pridám do obsluhy tlačítka kód na vytvorenie kresliacej plochy, tak to síce funguje, ale vlastne sa tá plocha vždy nanovo vytvára v pamäti, čo je zbytočné, pretože ju stačí vytvoriť raz. Takže som vytvorenie plochy dal do obsluhy udalosti Load formulára:

private void form1_Load(object sender, EventArgs e)
{
    picture1.Image = new Bitmap(200, 200);
}

Lenže odvtedy sa mi kresliaca plocha vytvára, ale zrejme nejako nešťastne, lebo obrázok sa na formulári vizuálne neukáže.

Doplnené:
Ak ten riadok v Load zapoznámkujem, tak pri pokuse o prístup do obrázku vznikne behová chyba. To znamená, že obrázok sa teda v Load vytvorí, ale na formulári ho neuvidím.

Jsou zobrazeny jen nové odpovědi. Zobrazit všechny
Předmět Autor Datum
Nikto tak skusim ja: Bolo by dobre viac info ze jak ten tvoj program vyzera a co je picture1 / co ro…
MM.. 06.06.2009 15:59
MM..
No skúsim sem dať viac, skúsim nejakú kostru.
msx. 06.06.2009 16:06
msx.
Skusal si uz po stlaceni tlacitka (zmena obrazku) program minimalizovat a obnovit? Ked sa tam potom…
MM.. 06.06.2009 16:16
MM..
A vážne, máš pravdu. Zrejme to súvisí s udalosťou Paint. Ale teraz tomu nerozumiem. Pri minimalizáci…
msx. 06.06.2009 16:22
msx.
Na tom objekte triedy PictureBox zavolaj metódu Refresh.
los 06.06.2009 20:04
los
Ďakujem. Pomohlo. Prosím ťa, vysvetli mi to, aby som tomu ešte rozumel.
msx. 06.06.2009 21:44
msx.
Kazdy program pod windows je riadeny udalostami, t.j. nic nebezi dokial Windows nezavola obsluznu ru…
MM.. 06.06.2009 22:29
MM..
Tomuto čo píšeš rozumiem a z Delphi to aj poznám, ale nerozumiem, prečo sa to vykreslilo keď som vyt…
msx. 06.06.2009 22:53
msx.
Zrejme pri vytvarani noveho to invaliduje automaticky framework. V C# nevies co framweork robi, kedy…
MM.. 06.06.2009 22:59
MM..
Neviď framework takým čiernym pohľadom. Ten objekt nezanikne. Iba, ak myslíš objekt Graphics. Ale vš…
msx. 06.06.2009 23:17
msx.
Ja kod vidim (nizsie), a tak ako si to mal predtym tak framework urcite objekt pictureBox1 po skonce…
MM.. 06.06.2009 23:31
MM..
Nie, pictureBox1 ak si si všimol nemá uvedený typ. On je deklarovaný ešte vo formulári. Tento kód je…
msx. 06.06.2009 23:35
msx.
Hej hej uz som to zeditoval, to je fuk proste niekto tam robil refresh aj ked nemal. No krasne nahod…
MM.. 06.06.2009 23:38
MM..
Zasa píšeš blbosti o .NET frameworku. Zdrojové kódy .NET frameworku sú k dispozícii, prípadne sa daj…
los 07.06.2009 13:16
los
Ked to je tak ako pises, tak mu to nemohlo fungovat ani predtym. Pisal ze mu to predtym fungovalo, t…
MM.. 07.06.2009 15:45
MM..
Prečo mu nemohlo fungovať to predtým? Keď volal picture1.Image = new Bitmap(200, 200) vždy pri stlač…
los 07.06.2009 16:26
los
Lenže aj v metóde Load, keď sa to odpoznámkuje a zapoznámkuje sa to v obsluhe Click tlačítka, tak aj…
msx. 07.06.2009 23:55
msx.
Prečo by sa to malo po stlačení tlačidla vykonať, ak to priradenie do Image bolo len v Load? Vykoná…
los 08.06.2009 08:49
los
Chceš teda povedať, že priradenie do Image funguje cez metódy "SetImage"? Neviem si teraz spomenúť a… poslední
msx. 08.06.2009 11:06
msx.

Nikto tak skusim ja:
Bolo by dobre viac info ze jak ten tvoj program vyzera a co je picture1 / co robis s tym picture1.
Ale jeden napad: ten obrazok mozno neni visible (kazde okno vo Win ma flag VISIBLE). Skus to pohladat ci ten objekt nema na to metodu.
Alebo je to picture1 nejak blbo napojene na ten formular, ze ho nezobrazuje/neprekresluje automaticky (nemoze vediet kedy si ho zmenil, vo Win vseobecne ked sa neurobi invalidate tak sa nic neprekresli - skus ten formular vo Win minimalizovat a znova obnovit - potom by sa mal prekreslit - cele okno dostane WM_PAINT message)

A vážne, máš pravdu. Zrejme to súvisí s udalosťou Paint. Ale teraz tomu nerozumiem. Pri minimalizácii a obnovení to obrázok zobrazilo, hoci pred minimalizáciou som klepol na Button a nezobrazilo sa nič. Ako mám teda postupovať?

Doplnené: Pravdepodobne pri udalosti Paint dojde k "pospájaniu" odkazov v objektoch. Ale ako to teraz vyriešiť, aby to fungovalo správne a obrázok sa vytvoril len raz?

Kazdy program pod windows je riadeny udalostami, t.j. nic nebezi dokial Windows nezavola obsluznu rutinu s parametrom ktory hovori ze co sa stalo (napr. uzivatel klikol na X,Y do okna aplikacie). Tvoja button rutina neprekresluje nic na obrazovke (nemoze lebo nema dost informacii, neni to rutina ktora obsluhuje WM_PAINT), tvoja button rutina moze len prepisat nieco kdesi v pamati pridelenej aplikacii.
Obsah okna prekresluje rutina ktora prekresluje ten dialog, ta ale sa spusti len ako reakcia na message prekresli oblast okna odtial potial. Win ale nema sajnu ze ty si zmenil nieco co zmenilo obsah okna, preto musis Windowsom povedat zmenil sa obsah okna tam a tam a potom Win zavola obsluznu rutinu s parametrom prekresli oblast odtial potial a s dalsimi informaciami ktore kreslenie na obrazovku vobec umoznia.

P.S. zasa si necital MSDN :-)

Tomuto čo píšeš rozumiem a z Delphi to aj poznám, ale nerozumiem, prečo sa to vykreslilo keď som vytvoril obrázok v obslužnej metóde kliknutia tlačítka, ale nevykreslilo, keď som vytvoril obrázok v obsluhe Load. O tento rozdiel mi ide. Toto potrebujem vysvetliť. Ostatné rozumiem.

Zrejme pri vytvarani noveho to invaliduje automaticky framework. V C# nevies co framweork robi, kedy to robi, ani preco to robi. Mozno to je napisane v MSDN (a mozno nie), mna osobne framework fakt nezaujima.

P.S. alebo najskor to je tak ze to refreshne framework vtedy ked ten objekt do ktoreho si kreslil zanikne, co bolo na konci tej button rutiny (alebo niekedy potom ked nejaky garbage collector ten objekt odstranil). Niekto to ale refreshnut/invalidovat musel. Napada ma len tajuplny poloautomaticky niktonevicorobiaci framework :)

Neviď framework takým čiernym pohľadom. Ten objekt nezanikne. Iba, ak myslíš objekt Graphics. Ale všimni si kód. Je identický až na to, že plocha na kreslenie sa vytvára v inej metóde. Totiž ten kód v tom kliknutí tlačítka je na malú úpravu totožný s kódom v jednom príklade v MSDN. Chcel som ho nájsť, ale už neviem, kde to bolo.

Ja kod vidim (nizsie), a tak ako si to mal predtym tak framework urcite objekt pictureBox1 po skonceni metody odstrani (ptz ak skonci ta metoda tak uz neni nikde viac pouzitelny). C# ma myslim nieco v style garbage collectora.
//edit: a hej pictureBox1 nezanikne (to mas nejaky globalny ci co :-? globaly su fuj :-) ale zanikne ten g).
Vtedy mozno zavola framework nejaky refresh. Ja to nevidim cierne ale vidim nieco co si robi co chce a kedy chce, ja som zvyknuty robit programy v ktorych vzdy na 100% viem co sa deje, preco sa deje a ako sa deje, a framework povazujem za tajuplny poloautomaticky nezmysel.

Ine vysvetlenie asi neni. Ked si nemenil nic ine.

Nie, pictureBox1 ak si si všimol nemá uvedený typ. On je deklarovaný ešte vo formulári. Tento kód je druhá časť kódu pre ten formulár (kľúčové slovo partial). picureBox1 je deklarovaný v tej druhej časti, pretože je to komponenta na formulári a to je v druhej časti kvôli designeru, aby vedel graficky vykresliť formulár podľa zadaného kódu (niečo ako dfm súbor v Delphi, ale so zdrojovým kódom, nie ako v Delphi).

Hej hej uz som to zeditoval, to je fuk proste niekto tam robil refresh aj ked nemal. No krasne nahodne funguje ten fremework, MS robi len same nahodne fungujuce veci :-) A asi aby sa necitili tak blbi osamote, tak nuti aj ostatnych robit nejake nahodne fungujuce programy v C# :-D

Zasa píšeš blbosti o .NET frameworku. Zdrojové kódy .NET frameworku sú k dispozícii, prípadne sa dajú pozrieť pomocou .NET Reflectora.

Pri priradení bitmapu do vlastnosti Image sa volá metóda InstallNewImage, ktorá volá Invalidate - preto sa to pri priradení nového obrázku prekreslilo. Keď modifikoval obrázok pomocou Graphics, tak sa žiadny Invalidate nevolal.

Metóda Refresh volá Invalidate a UpdateWindow.

Ked to je tak ako pises, tak mu to nemohlo fungovat ani predtym. Pisal ze mu to predtym fungovalo, takze bud ani nevedel ze mu to nefunguje (lol), alebo to s tym frameworkom nebude take krasne ale funguje nejak nahodne. A ked programator ma studovat zdrojaky frameworku, tak ta vyhoda ze v C# urobi clovek rychlejsie je potom uplne v prd..., ked musi clovek tyzden studovat zdrojaky frameworku aby vedel nieco urobit.
V prenesenom vyzname sa s rovnakou situaciou stretavam momentalne v oblasti BIOSov, ked si intel vymyslel nieco ako "framework" v BIOSe a namiesto jedneho riadku v asm musim teraz prestudovat 10000riadkov uplnych staciek v C++ a potom 3hodiny rozmyslat jak ten "framework" odrbat. Vsetko trva 100x dlhsie, je tam 100x vacsia sanca problemov, atd. Taky skvely je prinos "frameworkov" v praxi. Vidime to aj tu ked clovek ktory podla toho co pise to vedel urobit korektne v delphi aj v C++, a s frameworkom ma chaos.

Prečo mu nemohlo fungovať to predtým? Keď volal picture1.Image = new Bitmap(200, 200) vždy pri stlačení tlačidla, tak tam bolo to priradenie do vlastnosti Image, takže sa to prekreslilo.

Zdrojáky študovať netreba, stačí dokumentácia. Keď však chceš vedieť, ako to funguje interne, tak pozrieť sa môžeš a zistíš, že .NET framework nefunguje "náhodne".

Keď treba framework odrbávať, tak je niekde chyba. Nie každý framework má hlavu a pätu.

Lenže aj v metóde Load, keď sa to odpoznámkuje a zapoznámkuje sa to v obsluhe Click tlačítka, tak aj v tom Load sa priraďuje do Image a vtedy sa to po stlačení tlačítka neprekreslilo. Prečo?

Prečo by sa to malo po stlačení tlačidla vykonať, ak to priradenie do Image bolo len v Load? Vykoná sa Load, tam je priradenie - zavolá sa Invalidate a potom sa to prekreslí. Po stlačení tlačidla sa Load už nevolá a ani v obsluhe Click nie je priradenie do Image, takže sa nezavolá ani Invalidate. Takže nie je dôvod, prečo by sa to malo prekresliť.

Zpět do poradny Odpovědět na původní otázku Nahoru