Grafikus C# – Windows Forms tanfolyam › 1.12 lecke Windows Forms · 1.12 lecke A képek megjelenítése az ablakos programok egyik legkedveltebb része. Ebben a leckében megtanulod megjeleníteni a képeket a PictureBox vezérlővel, kiválasztani őket a fájlválasztó ablakból, és egy ImageList segítségével lapozható képnézegetőt építesz.PictureBox, ImageList és képek megjelenítése

A lecke végére
- képet jelenítesz meg a
PictureBoxvezérlőben, és beállítod aSizeModetulajdonságot; - a felhasználó által kiválasztott képet megnyitod az
OpenFileDialogsegítségével, hibakezeléssel; - képeket töltesz egy
ImageListkomponensbe, és sorszám alapján előveszed őket; - érted, mire való az osztályszintű változó (mező), és hogyan jegyzi meg a program az aktuális sorszámot;
- lapozható képnézegetőt készítesz Előző és Következő gombbal;
- felismered a képek kezelésének tipikus hibáit.
Mielőtt elkezded
Ehhez a leckéhez kell az 1.11 lecke, az 1.6 lecke (ComboBox), az 1.8 lecke (Increment) és a 2.2 lecke gondolata (fájlválasztó), de az utóbbit itt is elmagyarázzuk. Készíts elő 3–4 saját képet (JPG vagy PNG) egy mappában.
A PictureBox és a SizeMode
A PictureBox egy keret, amelyben képet jeleníthetsz meg. Tegyél az ablakra egyet pbKep néven (előtag: pb), majd a Properties ablakban az Image tulajdonságnál kattints a három pontra, és importálj egy saját képet.
Ha a kép nem fér bele a keretbe, vagy kisebb nála, a SizeMode tulajdonság dönti el, mi történjen:
pbKep.SizeMode = PictureBoxSizeMode.Zoom;Jósolj!
A kép 1200 × 800 képpont, a PictureBox 300 × 200. Mit látsz, ha a SizeMode értéke Normal? És Zoom?
Jóslat ellenőrzése
Normal esetén a kép bal felső sarka látszik, kb. a negyede, a többi levágódik. Zoom esetén a teljes kép látszik, arányosan lekicsinyítve (300 × 200 képpontosra).
Mit tegyél ide: a PictureBox ugyanazzal a képpel három beállításban egymás mellett: Normal (levágva), StretchImage (torz) és Zoom (arányos).Javasolt fájlnév: winforms-1-12-sizemode.webp · Alt szöveg: Ugyanaz a kép a PictureBox három SizeMode beállításával
Kép megnyitása a fájlválasztóval
A felhasználó saját képét az OpenFileDialog komponenssel választathatod ki (Toolbox, Dialogs csoport, neve: ofdKep). A képfájlok szűrőjében több kiterjesztés is megadható, pontosvesszővel elválasztva:
private void btnMegnyit_Click(object sender, EventArgs e)
{
ofdKep.Filter = "Képfájlok (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|Minden fájl (*.*)|*.*";
if (ofdKep.ShowDialog() == DialogResult.OK)
{
try
{
pbKep.Image = Image.FromFile(ofdKep.FileName);
pbKep.SizeMode = PictureBoxSizeMode.Zoom;
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült megnyitni a képet: " + ex.Message);
}
}
}PictureBox.Image tulajdonság.A betöltött fájl zárolva marad
Az Image.FromFile a kép fájlját zárolja, amíg a kép használatban van. Ilyenkor nem tudod törölni vagy felülírni a fájlt. Egyszerű programnál ez nem baj, a későbbi, 9. fejezetben megtanuljuk a megfelelő kezelését.
Jósolj!
A felhasználó a szűrő „Minden fájl” beállításával egy szövegfájlt (jegyzet.txt) választ ki. Mi történik?
Jóslat ellenőrzése
Az Image.FromFile hibát dob (általában OutOfMemoryException, ami félrevezető üzenet, de azt jelenti, hogy a fájl nem képformátum). A try–catch miatt a program nem omlik össze, hanem hibaüzenetet mutat.
Az ImageList: képek gyűjteménye
Az ImageList egy komponens, amely több képet tárol, és sorszám alapján előhívhatók belőle. Így a program képei egy helyen vannak, és nem kell külön fájlokat kezelni. Tegyél az ablakra egyet (Toolbox, Components csoport, neve: ilKepek), majd:
- Állítsd az
ImageSizetulajdonságot256, 256értékre (a legnagyobb megengedett méret). AColorDepthlegyenDepth32Bit. - Az
Imagestulajdonságnál kattints a (Collection) gombra, és az Add gombbal add hozzá 3–4 képedet.
Az ImageSize az alapból apró!
Az ImageList minden képet az ImageSize méretére alakít, és az alapérték 16 × 16 képpont. Ha ezt nem állítod át a képek hozzáadása előtt, minden kép apró lesz és elmosódik. Előbb állítsd be a méretet, utána add hozzá a képeket.
Mit tegyél ide: az Image Collection Editor ablak három hozzáadott képpel, mellette a Properties ablak az ImageSize 256, 256 értékkel.Javasolt fájlnév: winforms-1-12-imagelist.webp · Alt szöveg: Az ImageList képeinek szerkesztése a Visual Studióban
Az ImageList képeit a Images gyűjteményből kérheted le sorszámmal (0-tól), a darabszámot pedig az Images.Count adja:
pbKep.Image = ilKepek.Images[0]; // az első kép
int db = ilKepek.Images.Count; // ennyi kép van a gyűjteménybenJósolj!
Az ilKepek három képet tartalmaz. Mi történik, ha ezt írod: ilKepek.Images[3]?
Jóslat ellenőrzése
Futás közbeni hiba (ArgumentOutOfRangeException): három kép esetén a sorszámok 0, 1 és 2. A 3-as sorszám már nem létezik.
Új fogalom: az eseménykezelőn kívüli változó
A lapozható képnézegetőnek emlékeznie kell arra, hányadik képnél tart. Egy eseménykezelőben létrehozott változó azonban a metódus végén megszűnik: a következő kattintáskor már nem létezik. Ha meg akarjuk jegyezni az értékét, a változót a metódusokon kívül, az osztály elején kell létrehozni. Az ilyen változó neve mező, és az osztály összes metódusa eléri:
public partial class Form1 : Form
{
private int aktualis = 0; // mező: az aktuális kép sorszáma
public Form1()
{
InitializeComponent();
}
// ... itt következnek a metódusok ...
}hely a keresésnél) a metódus végén megszűnik.Kapcsolódik a későbbi anyaghoz
A mezőkről, a láthatóságról és az osztályok felépítéséről a 12. fejezetben tanulunk részletesen. Most elég annyi, hogy a metóduson kívüli változó megjegyzi az értékét.
Most már megírhatjuk a lapozást: a Mutat() metódus megjeleníti az aktuális képet, az Előző és a Következő gomb pedig módosítja a sorszámot. Ha az elejére vagy a végére érünk, körbe fordulunk:
private int aktualis = 0;
private void Mutat()
{
if (ilKepek.Images.Count > 0)
{
pbKep.Image = ilKepek.Images[aktualis];
lblSorszam.Text = $"{aktualis + 1} / {ilKepek.Images.Count}";
}
}
private void Form1_Load(object sender, EventArgs e)
{
pbKep.SizeMode = PictureBoxSizeMode.Zoom;
Mutat();
}
private void btnKovetkezo_Click(object sender, EventArgs e)
{
aktualis = aktualis + 1;
if (aktualis >= ilKepek.Images.Count)
{
aktualis = 0;
}
Mutat();
}
private void btnElozo_Click(object sender, EventArgs e)
{
aktualis = aktualis - 1;
if (aktualis < 0)
{
aktualis = ilKepek.Images.Count - 1;
}
Mutat();
}+ 1 a kiírásnál.Jósolj!
Három kép van, az aktualis értéke 2 (a harmadik kép). Megnyomod a Következő gombot. Melyik képet látod, és mi lesz a felirat?
Jóslat ellenőrzése
Az aktualis 3-ra nő, ami túl nagy, ezért 0-ra áll vissza: az első képet látod, és a felirat 1 / 3.
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. Csak egy darab látszik a képből
A képnek csak a bal felső sarka látszik a PictureBoxban. A Ok és javítás
SizeMode értéke Normal, ezért a kép eredeti méretben látszik, és a keretből kilógó rész levágódik. Állítsd Zoom értékre.
2. Apró, elmosódott kép
Az ImageListből előhívott képek nagyon kicsik és homályosak. Az Ok és javítás
ImageSize értéke az alapértelmezett 16 × 16 maradt, amikor a képeket hozzáadtad. Állítsd 256 × 256 értékre, töröld a képeket, és add hozzá újra.
3. Kilép a sorszám a tartományból
aktualis = aktualis + 1;
pbKep.Image = ilKepek.Images[aktualis];Hiba és javítás
Futás közbeni hiba (ArgumentOutOfRangeException) az utolsó képnél: a sorszám túllépi a darabszámot. Ellenőrizd a határt, és ugorj vissza 0-ra (if (aktualis >= ilKepek.Images.Count)).
4. A Következő mindig az első képre ugrik
private void btnKovetkezo_Click(object sender, EventArgs e)
{
int aktualis = 0;
aktualis = aktualis + 1;
Mutat();
}Hiba és javítás
Rossz működés: az aktualis változót a metóduson belül hoztad létre, ezért minden kattintásnál újra 0-ról indul, és a metódus végén eltűnik. A változót az osztály elején kell létrehozni (mező), a metóduson kívül.
5. Rossz fájl a képnéző számára
A program összeomlik, amikor egy nem kép fájlt választanak. Az Ok és javítás
Image.FromFile hibát dob nem képformátumú fájlnál. Tedd try–catch blokkba, és mutass a felhasználónak érthető üzenetet.
Mini projekt: képnéző
Készíts képnézegetőt, amely a saját képeidet mutatja lapozva és a megnyitott képet is megjeleníti:
- Felület:
pbKep(SizeMode: Zoom,BorderStyle: FixedSingle),btnElozo,btnKovetkezo,lblSorszam,btnMegnyitésofdKep, valamintilKepek(ImageSize: 256, 256, benne 3–4 saját képpel). - A lapozó gombok és a
Mutat()a 4. szakasz kódja alapján működnek. - A Megnyitás gomb a 2. szakasz kódjával egy külső képet jelenít meg (ilyenkor a lapozás nem használható, de a következő lapozásnál az ImageList képei jönnek vissza).
- A
cmbMeretlegördülő listából (Zoom, Stretch, Center) a felhasználó választhassa a megjelenítés módját.
private void cmbMeret_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbMeret.Text == "Zoom")
{
pbKep.SizeMode = PictureBoxSizeMode.Zoom;
}
else if (cmbMeret.Text == "Stretch")
{
pbKep.SizeMode = PictureBoxSizeMode.StretchImage;
}
else if (cmbMeret.Text == "Center")
{
pbKep.SizeMode = PictureBoxSizeMode.CenterImage;
}
}Mit tegyél ide: a kész képnéző egy képpel, az Előző és Következő gombbal, a „2 / 3” felirattal, a Megnyitás gombbal és a megjelenítési mód legördülő listájával.Javasolt fájlnév: winforms-1-12-kepnezo.webp · Alt szöveg: A kész képnéző lapozógombokkal és megjelenítési móddal
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. A kép mérete
Írd ki egy Az lblMeret feliratra a megjelenített kép méretét képpontban, például: 1200 × 800.Egy lehetséges megoldás
if (pbKep.Image != null)
{
lblMeret.Text = $"{pbKep.Image.Width} × {pbKep.Image.Height}";
}Image.Width és az Image.Height a kép szélessége és magassága. A null ellenőrzés kell, mert még lehet, hogy nincs betöltött kép.
2. Automatikus diavetítés
Készíts egy A tmrVetites Timert (Interval: 2000), amely kétmásodpercenként a következő képre lép. A chkVetites jelölőnégyzet kapcsolja be és ki.Egy lehetséges megoldás
private void chkVetites_CheckedChanged(object sender, EventArgs e)
{
tmrVetites.Enabled = chkVetites.Checked;
}
private void tmrVetites_Tick(object sender, EventArgs e)
{
btnKovetkezo.PerformClick();
}PerformClick() úgy viselkedik, mintha a gombra kattintottak volna, így nem kell a lapozó kódot megismételni.
3. Az Előző gomb az első képen
Az Előző gomb legyen letiltva, amíg az első képnél vagy, és a Következő gomb legyen letiltva az utolsó képen (körbefordulás nélkül). Az összehasonlítás eredménye igaz vagy hamis, ezt kapja az Egy lehetséges megoldás
// a Mutat() metódus végén:
btnElozo.Enabled = aktualis > 0;
btnKovetkezo.Enabled = aktualis < ilKepek.Images.Count - 1;Enabled tulajdonság. A lapozó gombokban ilyenkor a körbefordulást el kell hagyni.
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. A feladatokhoz használj egy pbKep PictureBoxot (SizeMode: Zoom) és az imlKepek ImageList komponenst. A képeket a projekt mappájába teheted, vagy az ImageList Images gyűjteményébe tölthetsz be. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Kép betöltése fájlból
A Az btnKep gomb nyisson meg egy képválasztó ablakot (ofdKep), és a kiválasztott képet jelenítse meg a pbKep PictureBoxban. Hibás fájlnál ne omoljon össze.Megoldás megnyitása
Image.FromFile betölti a képet. Ha a fájl nem kép, kivétel keletkezik, ezért try–catch blokkba tesszük. A Filter tulajdonság csak a képfájlokat mutatja.private void btnKep_Click(object sender, EventArgs e)
{
ofdKep.Filter = "Képek (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp";
if (ofdKep.ShowDialog() != DialogResult.OK)
{
return;
}
try
{
pbKep.Image = Image.FromFile(ofdKep.FileName);
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült megnyitni a képet: " + ex.Message);
}
}
2. Két kép váltogatása
Az Az imlKepek két képet tartalmaz. Egy gomb minden megnyomásra a másik képet mutassa a PictureBoxban.Megoldás megnyitása
imlKepek.Images[0] az első kép, az Images[1] a második. A váltáshoz egy bool mezőben jegyezzük meg, melyik látszik éppen.private bool elsoKepLatszik = true;
private void btnValt_Click(object sender, EventArgs e)
{
elsoKepLatszik = !elsoKepLatszik;
if (elsoKepLatszik)
{
pbKep.Image = imlKepek.Images[0];
}
else
{
pbKep.Image = imlKepek.Images[1];
}
}
Közepes szint
3. Képnézegető
Az Az aktuális képsorszámot mezőben tároljuk. A körbeforgatást ellenőrzéssel oldjuk meg: ha túlmennénk az utolsón, visszaugrunk az elsőre, és fordítva. A megjelenítést külön metódusba tesszük.imlKepek több képet tartalmaz. A btnElore és a btnVissza gomb léptessen előre és hátra, az utolsó után az első következzen, és fordítva. A lblSorszam mutassa: 2 / 5.Megoldás megnyitása
private int sorszam = 0;
private void Megjelenit()
{
pbKep.Image = imlKepek.Images[sorszam];
lblSorszam.Text = $"{sorszam + 1} / {imlKepek.Images.Count}";
}
private void btnElore_Click(object sender, EventArgs e)
{
sorszam = sorszam + 1;
if (sorszam >= imlKepek.Images.Count)
{
sorszam = 0;
}
Megjelenit();
}
private void btnVissza_Click(object sender, EventArgs e)
{
sorszam = sorszam - 1;
if (sorszam < 0)
{
sorszam = imlKepek.Images.Count - 1;
}
Megjelenit();
}
private void Form1_Load(object sender, EventArgs e)
{
Megjelenit();
}
4. Dobókocka
Az A imlKepek hat képet tartalmaz (a kocka 1–6 oldala, ebben a sorrendben). A btnDob gomb véletlenszerűen mutassa az egyiket, és a lblDobas írja ki a dobott számot.Megoldás megnyitása
Random objektumot mezőben hozzuk létre, hogy mindig ugyanazt használjuk, mert gyors egymásutánban új Random-ok ugyanazt a számot adhatnák. A Next(1, 7) 1 és 6 közötti számot ad (a felső határ nem tartozik bele).private Random veletlen = new Random();
private void btnDob_Click(object sender, EventArgs e)
{
int dobas = veletlen.Next(1, 7);
pbKep.Image = imlKepek.Images[dobas - 1];
lblDobas.Text = "Dobás: " + dobas;
}
Kihívás szint
5. Diavetítés
A Start gomb indítson automatikus diavetítést: a A Timer tmrDia Timer (Interval: 2000) kétmásodpercenként váltson a következő képre. A Stop gomb állítsa le.Megoldás megnyitása
Tick eseménye ugyanazt teszi, mint az előre gomb. A közös lépést külön metódusba tesszük, így nem kell kétszer megírni.private int sorszam = 0;
private void KovetkezoKep()
{
sorszam = sorszam + 1;
if (sorszam >= imlKepek.Images.Count)
{
sorszam = 0;
}
pbKep.Image = imlKepek.Images[sorszam];
}
private void tmrDia_Tick(object sender, EventArgs e)
{
KovetkezoKep();
}
private void btnStart_Click(object sender, EventArgs e)
{
tmrDia.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
tmrDia.Stop();
}
6. Két kocka és statisztika
Két PictureBox ( A dobások számát és az összegek összegét két mezőben tároljuk, mert a gombnyomások között is meg kell maradniuk. Az átlag az összeg osztva a dobások számával. A pbKocka1, pbKocka2) két kockát mutat. A gomb mindkettővel dob, a lblStat pedig kiírja: Dobások: 7, összeg átlaga: 7,3. A számláló és az összeg a program futása alatt folyamatosan gyűljön.Megoldás megnyitása
(double) átalakítás azért kell, hogy az osztás ne egész számként csonkoljon.private Random veletlen = new Random();
private int dobasokSzama = 0;
private int osszesen = 0;
private void btnDob_Click(object sender, EventArgs e)
{
int elso = veletlen.Next(1, 7);
int masodik = veletlen.Next(1, 7);
pbKocka1.Image = imlKepek.Images[elso - 1];
pbKocka2.Image = imlKepek.Images[masodik - 1];
dobasokSzama = dobasokSzama + 1;
osszesen = osszesen + elso + masodik;
double atlag = (double)osszesen / dobasokSzama;
lblStat.Text = $"Dobások: {dobasokSzama}, összeg átlaga: {Math.Round(atlag, 1)}";
}
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A Betölti a képet a fájlból. Hibát dob, ha a fájl nem létezik vagy nem képformátumú. Több képet tárol egy helyen, amelyek sorszámmal elérhetők. A 0-t. Három kép sorszáma: 0, 1, 2. Mert a metóduson belüli változó a metódus végén megszűnik. A metóduson kívüli változó (mező) megőrzi az értékét a kattintások között. Mert az ImageList a képeket a beállított méretre alakítja át hozzáadáskor. Az alapérték 16 × 16, ami apró és elmosódott képeket ad.1. Melyik SizeMode tartja meg a kép arányát, és mutatja a teljes képet?
Zoom.2. Mit ad vissza az Image.FromFile, és mikor hibázik?
3. Mire való az ImageList?
4. Milyen sorszámot kap az ImageList első képe?
5. Miért kell a lapozásnál az aktuális sorszámot az osztály elején létrehozni?
6. Miért kell az ImageSize értékét a képek hozzáadása előtt beállítani?
Mit tudsz már?
- Képet jelenítesz meg a PictureBoxban, és beállítod a SizeMode-ot.
- A felhasználó képét megnyitod hibakezeléssel.
- Képeket tárolsz az ImageListben.
- Érted, mire való a mező (metóduson kívüli változó).
- Lapozható képnézegetőt készítettél.
Következő lecke: záró projekt, adatbekérő és kalkulátor
Az 1. fejezet vezérlőit már mind ismered. A következő leckében egy záró projektben használjuk őket együtt.




