Grafikus C# – Windows Forms tanfolyam › 9.4 lecke Windows Forms · 9.4 lecke · rajzeszközök A Pen, Brush, Color, Rectangle
Graphics megmondja, mit rajzoljunk, a rajzeszközök pedig azt, hogyan: a toll (Pen) a vonalat és a körvonalat, az ecset (Brush) a kitöltést adja, a szín (Color) mindkettőnek az anyaga, a téglalap (Rectangle) pedig a helyet és a méretet fogalmazza meg. Ebben a leckében megtanulod az átlátszó színeket, a szaggatott és nyilas vonalakat, a sraffozott és átmenetes kitöltést, a téglalap-műveleteket (metszet, tartalmazás), és a DrawRectangle apró, de bosszantó csapdáját.
A lecke végére
- színeket adsz meg (név,
FromArgb, átlátszóság) és keversz (átmenet két szín között); - a
Pentulajdonságait használod (vastagság,DashStyle, végződés,LineJoin); - egyszínű, sraffozott és átmenetes ecsetet készítesz (
SolidBrush,HatchBrush,LinearGradientBrush); - a
Rectangletulajdonságait és műveleteit használod (Contains,IntersectsWith,Intersect,Union,Inflate); - tudod, melyik eszközt kell felszabadítani, és melyik a közös (
Pens,Brushes); - elkerülöd a gyakori hibákat (
DrawRectanglemérete, üres téglalapú átmenet, átlátszó szöveg).
Mielőtt elkezded
Ehhez a leckéhez a 9.3 lecke (Paint, Graphics, using) és a 7.9 lecke (Color, ColorDialog) szükséges.
Color: színek és átlátszóság
Color a = Color.Crimson; // névvel (140 elnevezett szín)
Color b = Color.FromArgb(104, 64, 165); // piros, zöld, kék (0–255), teljesen átlátszatlan
Color c = Color.FromArgb(128, 104, 64, 165); // az első szám az ALFA: 0 átlátszó ... 255 átlátszatlan
Color d = Color.FromArgb(100, Color.Red); // meglévő szín áttetszővé tétele
int piros = b.R, zold = b.G, kek = b.B, alfa = c.A; // a csatornák
float arnyalat = b.GetHue(); // 0–360 fok: a színkör szöge (HSB modell)
float telitettseg = b.GetSaturation(); // 0–1
float vilagossag = b.GetBrightness(); // 0–1 (HSL világosság)
// két szín keverése: t = 0 → a, t = 1 → b
private Color Kever(Color a, Color b, double t)
{
t = Math.Max(0, Math.Min(1, t));
return Color.FromArgb(
(int)(a.A + (b.A - a.A) * t),
(int)(a.R + (b.R - a.R) * t),
(int)(a.G + (b.G - a.G) * t),
(int)(a.B + (b.B - a.B) * t));
}FromArgb paraméterei alfa, piros, zöld, kék sorrendben vannak (az alfa az első, ha négyet adsz meg).GetHue() a színkör szöge (piros 0°, zöld 120°, kék 240°): színek halványítására, színkör szerinti sorozatok készítésére hasznos.Kever csatornánként lineárisan számol: színátmenetekhez, hőtérképhez, animált színváltáshoz.Jósolj!
A Color.FromArgb(128, 255, 0, 0) színnel kitöltött téglalap fehér háttéren van. Milyen színűnek látod?
Jóslat ellenőrzése
Világos rózsaszín (kb. 255, 127, 127): a 50%-ban átlátszó piros a fehérrel keveredik. Fekete háttéren sötétpiros lenne. A látható szín az alfától és a háttértől függ.
Pen: a toll
private void pnlRajz_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// egyszerű toll: szín és vastagság (pixel)
using (Pen alap = new Pen(Color.Black, 3))
{
g.DrawLine(alap, 20, 20, 200, 20);
}
// szaggatott vonal
using (Pen szaggatott = new Pen(Color.SteelBlue, 2))
{
szaggatott.DashStyle = DashStyle.Dash; // Solid, Dash, Dot, DashDot, DashDotDot
g.DrawLine(szaggatott, 20, 50, 200, 50);
szaggatott.DashPattern = new float[] { 4, 2, 1, 2 }; // saját minta: vonal, hézag... (a vastagság többszöröse)
g.DrawLine(szaggatott, 20, 70, 200, 70);
}
// nyíl és lekerekített vonalvég
using (Pen nyil = new Pen(Color.Firebrick, 4))
{
nyil.StartCap = LineCap.Round; // lekerekített kezdet
nyil.EndCap = LineCap.ArrowAnchor; // nyílhegy a végén
g.DrawLine(nyil, 20, 100, 200, 100);
}
// vastag töröttvonal: a csúcsok összekötése (LineJoin)
using (Pen toro = new Pen(Color.SeaGreen, 10))
{
toro.LineJoin = LineJoin.Round; // Miter (hegyes), Bevel (levágott), Round (lekerekített)
g.DrawLines(toro, new Point[] { new Point(20, 160), new Point(80, 120), new Point(140, 160) });
}
// készen kapható tollak (1 pixel vastag): ezeket NEM szabadítjuk fel
g.DrawRectangle(Pens.DarkSlateGray, 220, 20, 100, 60);
}Pen második paramétere (float) a vastagság képpontban. A 0 vagy 1 vékony (egy képpontos) vonalat ad; törtszám is lehet.DashStyle kész szaggatott mintákat ad; a DashPattern tömb a vonal és a hézag váltakozó hosszát adja (a toll vastagságának többszörösében).StartCap, EndCap (LineCap: Flat, Round, Square, ArrowAnchor, DiamondAnchor…) a vonal végét formálja; a LineJoin a töröttvonal csúcsait.Pens.Black, Pens.Red stb. előre elkészített, 1 képpont vastag tollak: kényelmesek, de nem módosíthatók és nem felszabadítandók. A saját tollat (new Pen) mindig using blokkban használd.Jósolj!
A Pens.Red.Width = 5; sort hajtod végre a Paint-ben. Mi történik?
Jóslat ellenőrzése
ArgumentException (a toll nem módosítható): a Pens osztály tollai közösek és védettek. Vastagabb tollhoz saját new Pen(Color.Red, 5) kell.
Brush: az ecset
| Ecset | Mit ad? |
|---|---|
SolidBrush(szín) | Egyszínű kitöltés (áttetsző színnel áttetsző). |
HatchBrush(stílus, előtér, háttér) | Sraffozás: ismétlődő minta (vonalak, kockák, pöttyök). |
LinearGradientBrush(téglalap, szín1, szín2, szög) | Lineáris színátmenet az adott szögben. |
TextureBrush(kép) | Kép mint ismétlődő minta. |
PathGradientBrush | Sugaras (alakzat közepétől kifelé) átmenet (haladó). |
Rectangle hely = new Rectangle(20, 20, 200, 100);
// egyszínű, félig átlátszó
using (Brush egyszinu = new SolidBrush(Color.FromArgb(120, Color.DodgerBlue)))
{
g.FillRectangle(egyszinu, hely);
}
// sraffozott
using (Brush sraf = new HatchBrush(HatchStyle.DiagonalCross, Color.DarkGreen, Color.Honeydew))
{
g.FillRectangle(sraf, new Rectangle(240, 20, 200, 100));
}
// átmenetes: a téglalap a rajzolandó alakzat helye, a szög 45 fok
Rectangle atmenetHely = new Rectangle(20, 140, 200, 100);
using (LinearGradientBrush atmenet = new LinearGradientBrush(atmenetHely, Color.Gold, Color.OrangeRed, 45f))
{
g.FillEllipse(atmenet, atmenetHely);
}
// az áttekinthetőség: a hátsó rajz előbb, az elülső később (festő módszer)
g.FillRectangle(Brushes.LightGray, 240, 140, 120, 80);
g.FillRectangle(Brushes.White, 280, 170, 120, 80); // a később rajzolt takarja az előzőtLinearGradientBrush téglalapja azt a területet adja, amelyen a színátmenet lefut. Ha az alakzat máshol van, mint a téglalap, az átmenet nem az alakzaton fut végig (csak egyszínű sáv látszik): a téglalap egyezzen az alakzattal.ArgumentException kivételt dob az átmenetes ecsetnél: ellenőrizd a méretet (például átméretezéskor).new …Brush felszabadítandó (using); a Brushes.Name közös, nem szabadítjuk. Gyakori Paint esetén a tollat, ecsetet előre elkészítve a Form zárásáig megtarthatod, és ott szabadíthatod (9.8 lecke).Jósolj!
A LinearGradientBrush téglalapja (0, 0, 100, 100), de a kitöltött téglalap a (300, 300, 100, 100) helyen van. Milyen a kitöltés?
Jóslat ellenőrzése
A kitöltés egyszínű (az átmenet végén álló szín): az alakzat az átmenet területén kívül esik, és a színátmenet a terület szélén túl ismétlődik, vagy fixen az utolsó színt kapja. Az átmenetes ecset téglalapja mindig az alakzat helyén legyen.
Rectangle és a téglalap-műveletek
A Rectangle (egész koordináták) és a RectangleF (törtszám) a hely és a méret leírója (X, Y, Width, Height), ráadásul számos hasznos tulajdonsága és művelete van. Ezekkel az ütközésvizsgálat, a kijelölés és az elrendezés is egyszerű:
Rectangle a = new Rectangle(20, 20, 100, 60);
Rectangle b = new Rectangle(80, 50, 100, 60);
int bal = a.Left, felso = a.Top, jobb = a.Right, also = a.Bottom; // Right = X + Width, Bottom = Y + Height
Point hely = a.Location;
Size meret = a.Size;
bool bent = a.Contains(new Point(50, 40)); // a pont a téglalapon belül van? (kattintás vizsgálat)
bool utkozik = a.IntersectsWith(b); // átfedik egymást? (ütközés)
Rectangle kozos = Rectangle.Intersect(a, b); // a közös rész (üres, ha nincs: kozos.IsEmpty)
Rectangle egyesitett = Rectangle.Union(a, b); // mindkettőt befoglaló legkisebb téglalap
Rectangle nagyobb = a;
nagyobb.Inflate(10, 10); // minden oldalon 10 pixellel nagyobb (X, Y is mozog)
nagyobb.Offset(15, 0); // eltolás
// téglalap két pontból (az egérrel húzott terület, a pontok bármilyen sorrendben)
private Rectangle PontokbolRect(Point p, Point q)
{
return new Rectangle(Math.Min(p.X, q.X), Math.Min(p.Y, q.Y), Math.Abs(p.X - q.X), Math.Abs(p.Y - q.Y));
}
// a DrawRectangle csapdája: a körvonal 1 képponttal nagyobb a megadott méretnél
g.FillRectangle(Brushes.LightYellow, hely);
g.DrawRectangle(Pens.Black, hely.X, hely.Y, hely.Width - 1, hely.Height - 1); // -1: a kitöltéssel egy vonalbanRight (X + Width) és a Bottom (Y + Height) a téglalap első képponton kívüli széle: nincs benne a téglalapban. A Contains ezt figyelembe veszi.IntersectsWith hívás: két alakzat befoglaló téglalapjának átfedése. Körnél a pontos vizsgálat a középpontok távolsága.Inflate(dx, dy) minden oldalon bővít (a téglalap mérete 2·dx, 2·dy értékkel nő): kijelölő keret rajzolásához hasznos. Negatív érték zsugorít.DrawRectangle a megadott méretnél 1 képponttal tovább rajzolja a körvonalat jobbra és lefelé. Ha kitöltött téglalapra rajzolsz kerettel, a szélesség és magasság -1 értéke illeszti a keretet.Jósolj!
Az a = (20, 20, 100, 60) és a b = (80, 50, 100, 60) téglalapok metszete mekkora, és hol van?
Jóslat ellenőrzése
Az a jobb széle 120, alsó széle 80; a b bal széle 80, felső széle 50. A metszet X: 80–120, Y: 50–80, vagyis (80, 50, 40, 30). Az Union (20, 20, 160, 90).
Mit tegyél ide: a stílus-labor: vonalstílusok, ecsetek és két téglalap metszetének kiemelése.Javasolt fájlnév: winforms-9-4-stilus-labor.webp · Alt szöveg: Toll- és ecsetstílusok a stílus-laborban
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. ArgumentException a Pens használatakor
Pens.Red.DashStyle = DashStyle.Dash; // a közös toll nem módosíthatóHiba és javítás
A Pens tollai közösek és írásvédettek. Hozz létre saját tollat: using (Pen p = new Pen(Color.Red)) { p.DashStyle = ...; }.
2. Az átmenet nem látszik
using (LinearGradientBrush b = new LinearGradientBrush(new Rectangle(0, 0, 50, 50), Color.Red, Color.Blue, 0f))
{
g.FillRectangle(b, 200, 200, 100, 100); // az átmenet területén kívül
}Hiba és javítás
Az ecset téglalapja nem egyezik az alakzattal. Használd ugyanazt a Rectangle változót az ecsetnél és a kitöltésnél.
3. ArgumentException az átmenetes ecsetnél
Az ablak kicsinyítése után kivétel keletkezik. A téglalap szélessége vagy magassága nulla lett. Ellenőrizd (Ok és javítás
if (hely.Width < 1 || hely.Height < 1) return;) az ecset létrehozása előtt.
4. A keret kilóg a kitöltésből
A téglalap körvonala 1 képponttal nagyobb a kitöltésnél. A Ok és javítás
DrawRectangle a megadott méret után is rajzol egy képpontot. Add meg a Width - 1, Height - 1 értéket.
5. A rajzolás lelassul sok alakzatnál
foreach (Alakzat a in alakzatok)
{
g.FillRectangle(new SolidBrush(a.Szin), a.Hely); // minden alakzathoz felszabadítatlan ecset
}Hiba és javítás
Szivárog a rendszererőforrás (az ecset nincs felszabadítva). Használj using (Brush b = new SolidBrush(a.Szin)) blokkot, vagy cache-eld az ecseteket szín szerint.
6. A fekete szöveg olvashatatlan az átlátszó háttéren
A félig átlátszó színű téglalapon a szöveg nehezen olvasható. Az áttetsző háttér színe a mögötte lévő rajztól függ, ezért a kontraszt változik. Szövegnél legyen átlátszatlan háttér, vagy számold a kontrasztot (6.9 lecke).Ok és javítás
Mini projekt: stílus-labor
Készíts programot, amellyel kísérletezhetsz a tollakkal, ecsetekkel és a téglalap-műveletekkel:
- RajzPanel (a 9.3 lecke osztálya):
rp,Dock = Fill, jobb oldalán a beállító panel. - Toll beállítói: szín (
btnTollSzin+ColorDialog), vastagság (nudVastag, 1–30),cmbVonal(Folytonos, Szaggatott, Pontozott, Szaggatott-pontozott),cmbVeg(Sima, Kerek, Nyíl),cmbCsucs(Hegyes, Levágott, Kerek). - Ecset beállítói:
cmbEcset(Egyszínű, Sraffozott, Átmenetes), két szín (btnSzin1,btnSzin2),tbAlfa(TrackBar0–255: az átlátszóság),nudSzog(átmenet szöge). - Előnézet (Paint): a háttér sakktábla minta (hogy az átlátszóság látszódjon); egy kitöltött téglalap és ellipszis az ecsettel; egy töröttvonal a tollal; egy nyíl; mindegyik a kiválasztott beállításokkal. Az
using-os tollak, ecsetek. - Kódmutató: a
txtKod(csak olvasható, többsoros) megmutatja a beállításokhoz tartozó C# kódot (new Pen(Color.FromArgb(...), 3),DashStyle = ...), és a Másolás gomb a vágólapra teszi. - Téglalap-labor: két téglalap (
A: fix;B:nudBX,nudBY,nudBSz,nudBMmezőkkel állítható); a metszet (Intersect) sraffozott kitöltéssel, azUnionszaggatott kerettel; alblTeglalapkiírja: Metszet: (80, 50, 40, 30), átfedés: igen. - Ellenőrzések: nincs nulla méretű átmenetes ecset (az előnézet kis ablaknál sem omlik össze); a közös tollakat (
Pens) nem módosítja. - Teszteld: minden vonalstílus és végződés, átlátszóság sakktábla fölött, az átmenet szöge, a keret illeszkedése (
-1), kicsinyített ablak, a kódmutató egyezése a rajzzal, a téglalapok különböző helyzetei (nincs metszet, tartalmazás).
Megoldás megnyitása (próbáld ki előbb önállóan!)
A beállítók egy közös Valtozas kezelővel hívják az rp.Invalidate() metódust, a Paint pedig a vezérlők állapotából rajzol.
private Color tollSzin = Color.Black, szin1 = Color.DodgerBlue, szin2 = Color.Orange;
private void Form1_Load(object sender, EventArgs e)
{
cmbVonal.Items.AddRange(new object[] { "Folytonos", "Szaggatott", "Pontozott", "Szaggatott-pontozott" });
cmbVeg.Items.AddRange(new object[] { "Sima", "Kerek", "Nyíl" });
cmbCsucs.Items.AddRange(new object[] { "Hegyes", "Levágott", "Kerek" });
cmbEcset.Items.AddRange(new object[] { "Egyszínű", "Sraffozott", "Átmenetes" });
cmbVonal.SelectedIndex = cmbVeg.SelectedIndex = cmbCsucs.SelectedIndex = cmbEcset.SelectedIndex = 0;
tbAlfa.Maximum = 255;
tbAlfa.Value = 200;
}
private Pen UjToll()
{
Pen p = new Pen(tollSzin, (float)nudVastag.Value);
DashStyle[] vonalak = { DashStyle.Solid, DashStyle.Dash, DashStyle.Dot, DashStyle.DashDot };
LineCap[] vegek = { LineCap.Flat, LineCap.Round, LineCap.ArrowAnchor };
LineJoin[] csucsok = { LineJoin.Miter, LineJoin.Bevel, LineJoin.Round };
p.DashStyle = vonalak[cmbVonal.SelectedIndex];
p.StartCap = LineCap.Round;
p.EndCap = vegek[cmbVeg.SelectedIndex];
p.LineJoin = csucsok[cmbCsucs.SelectedIndex];
return p;
}
private Brush UjEcset(Rectangle hely)
{
Color c1 = Color.FromArgb(tbAlfa.Value, szin1);
Color c2 = Color.FromArgb(tbAlfa.Value, szin2);
if (cmbEcset.SelectedIndex == 1) { return new HatchBrush(HatchStyle.Percent50, c1, c2); }
if (cmbEcset.SelectedIndex == 2) { return new LinearGradientBrush(hely, c1, c2, (float)nudSzog.Value); }
return new SolidBrush(c1);
}
private void rp_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// sakktábla háttér az átlátszóság megmutatásához
for (int y = 0; y < rp.Height; y += 20)
{
for (int x = 0; x < rp.Width; x += 20)
{
g.FillRectangle(((x / 20 + y / 20) % 2 == 0) ? Brushes.White : Brushes.Gainsboro, x, y, 20, 20);
}
}
Rectangle hely = new Rectangle(30, 30, 220, 120);
if (hely.Width > 0 && hely.Height > 0)
{
using (Brush ecset = UjEcset(hely))
using (Pen toll = UjToll())
{
g.FillRectangle(ecset, hely);
g.DrawRectangle(toll, hely.X, hely.Y, hely.Width - 1, hely.Height - 1);
Rectangle kor = new Rectangle(280, 30, 120, 120);
using (Brush ecset2 = UjEcset(kor))
{
g.FillEllipse(ecset2, kor);
}
g.DrawEllipse(toll, kor);
g.DrawLines(toll, new Point[] { new Point(30, 240), new Point(110, 180), new Point(190, 240), new Point(270, 180) });
g.DrawLine(toll, 300, 220, 420, 220);
}
}
TeglalapLabor(g);
txtKod.Text = "new Pen(Color.FromArgb(" + tollSzin.R + ", " + tollSzin.G + ", " + tollSzin.B + "), " + nudVastag.Value + ") { DashStyle = DashStyle." + ((DashStyle)new DashStyle[] { DashStyle.Solid, DashStyle.Dash, DashStyle.Dot, DashStyle.DashDot }[cmbVonal.SelectedIndex]) + " }";
}
private void TeglalapLabor(Graphics g)
{
Rectangle a = new Rectangle(30, 300, 160, 100);
Rectangle b = new Rectangle((int)nudBX.Value, (int)nudBY.Value, (int)nudBSz.Value, (int)nudBM.Value);
Rectangle metszet = Rectangle.Intersect(a, b);
Rectangle egyesitett = Rectangle.Union(a, b);
g.DrawRectangle(Pens.DarkBlue, a.X, a.Y, a.Width - 1, a.Height - 1);
g.DrawRectangle(Pens.DarkRed, b.X, b.Y, b.Width - 1, b.Height - 1);
if (!metszet.IsEmpty)
{
using (Brush sraf = new HatchBrush(HatchStyle.DiagonalCross, Color.Black, Color.FromArgb(80, Color.Yellow)))
{
g.FillRectangle(sraf, metszet);
}
}
using (Pen szagg = new Pen(Color.Gray) { DashStyle = DashStyle.Dash })
{
g.DrawRectangle(szagg, egyesitett.X, egyesitett.Y, egyesitett.Width - 1, egyesitett.Height - 1);
}
lblTeglalap.Text = "Metszet: (" + metszet.X + ", " + metszet.Y + ", " + metszet.Width + ", " + metszet.Height + "), átfedés: " + (a.IntersectsWith(b) ? "igen" : "nem");
}
private void Valtozas(object sender, EventArgs e) { rp.Invalidate(); }
private void btnTollSzin_Click(object sender, EventArgs e)
{
using (ColorDialog cd = new ColorDialog { Color = tollSzin })
{
if (cd.ShowDialog(this) == DialogResult.OK) { tollSzin = cd.Color; rp.Invalidate(); }
}
}
private void btnSzin1_Click(object sender, EventArgs e)
{
using (ColorDialog cd = new ColorDialog { Color = szin1 })
{
if (cd.ShowDialog(this) == DialogResult.OK) { szin1 = cd.Color; rp.Invalidate(); }
}
}
private void btnSzin2_Click(object sender, EventArgs e)
{
using (ColorDialog cd = new ColorDialog { Color = szin2 })
{
if (cd.ShowDialog(this) == DialogResult.OK) { szin2 = cd.Color; rp.Invalidate(); }
}
}
private void btnMasol_Click(object sender, EventArgs e)
{
Clipboard.SetText(txtKod.Text);
}Mit tegyél ide: a kész stílus-labor az átlátszó alakzatokkal a sakktáblán, a vonalstílusokkal és a téglalap-metszettel.Javasolt fájlnév: winforms-9-4-kesz.webp · Alt szöveg: A kész stílus-labor
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. Színátmenet-sáv
Rajzolj 256 egymás melletti 2 pixel széles függőleges vonalat, amelyek színe pirosról kékre vált (a A saját keverés a színek közti átmenet minden lépését szabályozza (például három szín közötti, nem lineáris vagy HSB alapú átmenet); a Kever metódussal). Miért jobb ez az egyetlen átmenetes ecsetnél bizonyos esetekben?Egy lehetséges megoldás
LinearGradientBrush egyszerű két színre elég.for (int i = 0; i < 256; i++)
{
using (Pen toll = new Pen(Kever(Color.Red, Color.Blue, i / 255.0), 2))
{
g.DrawLine(toll, i * 2, 0, i * 2, 40);
}
}
2. Kijelölő keret
A kijelölt alakzat körül szaggatott, 4 pixellel nagyobb keret látszik. Hogyan számolod a keret téglalapját? A téglalap másolatán Egy lehetséges megoldás
Inflate(4, 4), és szaggatott toll (DashStyle.Dash).Rectangle keret = alakzat.Hely;keret.Inflate(4, 4);using (Pen toll = new Pen(Color.RoyalBlue) { DashStyle = DashStyle.Dash }){ g.DrawRectangle(toll, keret.X, keret.Y, keret.Width - 1, keret.Height - 1);}
3. Ütköző labdák
Két mozgó kör ütközését vizsgáld. Elég-e a téglalapok Gyors előszűrésnek igen, de körnél a sarkokban téves találatot ad. Pontos vizsgálat: a középpontok távolsága kisebb a sugarak összegénél.IntersectsWith vizsgálata?Egy lehetséges megoldás
private bool Utkozik(PointF k1, float r1, PointF k2, float r2){ float dx = k1.X - k2.X; float dy = k1.Y - k2.Y; return dx * dx + dy * dy <= (r1 + r2) * (r1 + r2); // a gyökvonás elkerülhető}
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. FromArgb
Írd meg a következő színt: 25%-ban átlátszatlan zöld (0, 128, 0). A 25% átlátszatlanság az alfa: 255 × 0,25 ≈ 64: Megoldás megnyitása
Color.FromArgb(64, 0, 128, 0).
2. Melyiket kell felszabadítani?
Jelöld: (a) (b) és (d): a saját példányokat. A (a) és (c) közös, készen kapott objektum: nem szabad felszabadítani.Pens.Red; (b) new Pen(Color.Red); (c) Brushes.Blue; (d) new SolidBrush(Color.Blue).Megoldás megnyitása
Közepes szint
3. Csíkos háttér
Rajzolj váltakozó világos és sötétebb szürke vízszintes csíkokat a panelre, a csík magasságát egy számmező adja. Melyik a legegyszerűbb? Ciklus a panel magasságán, Megoldás megnyitása
FillRectangle váltakozó Brushes ecsettel (a sorszám paritása szerint).
4. Pont a téglalapban
Egér kattintásra kiírja, melyik téglalapra kattintottál (több téglalap közül). Mit használsz, és mi a sorrend átfedés esetén? A Megoldás megnyitása
Rectangle.Contains(point) hívást; átfedésnél a legfelül rajzoltat keresd (a lista végétől visszafelé), mert az látszik a képernyőn (9.7 lecke).
Kihívás szint
5. Hőtérkép színek
Egy érték (0–100) színe: 0 kék, 50 zöld, 100 piros. Hogyan készíted el a három szín közötti átmenetet? Két szakaszban: 0–50 között kékről zöldre, 50–100 között zöldről pirosra keversz (a Megoldás megnyitása
Kever metódussal).private Color HoSzin(double ertek){ ertek = Math.Max(0, Math.Min(100, ertek)); return ertek < 50 ? Kever(Color.Blue, Color.Green, ertek / 50) : Kever(Color.Green, Color.Red, (ertek - 50) / 50);}
6. Saját tollkészlet
A program sok vonalat rajzol ugyanazokkal a tollakkal. Készíts Nem jön létre és szűnik meg ugyanaz a toll minden TollGyar osztályt, amely a tollakat színenként tárolja, és a Form zárásakor felszabadítja. Mi az előnye?Megoldás megnyitása
Paint-ben (gyorsabb, kevesebb szemét); a felszabadítás egy helyen történik (9.8 lecke).public class TollGyar : IDisposable
{
private readonly Dictionary<string, Pen> tollak = new Dictionary<string, Pen>();
public Pen Toll(Color szin, float vastagsag)
{
string kulcs = szin.ToArgb() + ":" + vastagsag;
Pen p;
if (!tollak.TryGetValue(kulcs, out p))
{
p = new Pen(szin, vastagsag);
tollak[kulcs] = p;
}
return p;
}
public void Dispose()
{
foreach (Pen p in tollak.Values) { p.Dispose(); }
tollak.Clear();
}
}
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Az átlátszóságot: 0 teljesen átlátszó, 255 teljesen átlátszatlan. A A vonal és a hézag hosszának váltakozó mintája (a vastagság többszörösében). Az alakzat helyére, különben az átmenet nem az alakzaton fut le. Az A körvonal 1 képponttal nagyobb a megadott méretnél; így illeszkedik a kitöltéshez. A 1. Mit jelent az alfa csatorna?
2. Mire való a Pen és a Brush?
Pen a vonalat/körvonalat (Draw…), a Brush a kitöltést (Fill…) adja.3. Mi a DashPattern?
4. Hova kell az átmenetes ecset téglalapja?
5. Mi az Intersect és az Union?
Intersect a közös részt, az Union a két téglalapot befoglaló legkisebb téglalapot adja.6. Miért kell a DrawRectangle-nél Width - 1?
7. Melyik tollat tilos módosítani?
Pens osztályét (közös): ArgumentException.
Mit tudsz már?
- Színeket adsz meg, keversz, és átlátszóságot használsz.
- Tollakat állítasz (vastagság, szaggatás, végződés, csúcsok).
- Egyszínű, sraffozott és átmenetes ecsettel töltesz ki.
- A
Rectangleműveleteit (metszet, tartalmazás, bővítés) használod. - Tudod, mit kell felszabadítani, és elkerülöd a gyakori hibákat.
Következő lecke: Pontok, koordináták és méretezés
A koordináta-rendszer mélyebben: Point, PointF, átszámítás, a világ- és a képernyő-koordináta, a Graphics transzformációi.



