BGRABitmap tutorial 3/de: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: BGRABitmap tutorial 3/de
| Old | New | Line | |
|---|---|---|---|
| 1 | + | Dieses Tutorial zeigt, wie man mit der Maus auf einer Bitmap zeichnet. | |
| 2 | + | ||
| 3 | + | ### Erzeugen Sie ein neues Projekt | |
| 4 | + | ||
| 5 | + | Erzeugen Sie ein neues Projekt und fügen Sie eine Referenz auf [[BGRABitmap/de|BGRABitmap]] hinzu, genau so wie im [[BGRABitmap tutorial/de|ersten Tutorial]]. | |
| 6 | + | ||
| 7 | + | ### Erzeugen Sie ein neues Bild | |
| 8 | + | ||
| 9 | + | Fügen Sie eine private Variable zum Hauptformular hinzu, um das Bild zu speichern: | |
| 10 | + | ||
| 11 | + | ``` pascal | |
| 12 | + | TForm1 = class(TForm) | |
| 13 | + | private | |
| 14 | + | { private declarations } | |
| 15 | + | image: TBGRABitmap; | |
| 16 | + | public | |
| 17 | + | { public declarations } | |
| 18 | + | end; | |
| 19 | + | ``` | |
| 20 | + | ||
| 21 | + | Erzeugen Sie das Bild, wenn das Formular erzeugt wird. Dazu doppelklicken Sie auf das Formular, eine Prozedur erscheint im Quelltexteditor. Fügen Sie eine Anweisung zum Erzeugen des Bildes ein: | |
| 22 | + | ||
| 23 | + | ``` pascal | |
| 24 | + | procedure TForm1.FormCreate(Sender: TObject); | |
| 25 | + | begin | |
| 26 | + | image := TBGRABitmap.Create(640,480,BGRAWhite); //erzeuge ein 640x480 Bild | |
| 27 | + | end; | |
| 28 | + | ``` | |
| 29 | + | ||
| 30 | + | ### Zeichnen Sie die Bitmap | |
| 31 | + | ||
| 32 | + | Fügen Sie einen OnPaint-Handler hinzu. Dazu wählen Sie das Hauptformular aus, gehen zum Objektinspektor, zum Karteireiter Ereignisse und doppelklicken Sie auf die Zeile 'OnPaint'. Dann fügen Sie den Zeichenbefehl ein: | |
| 33 | + | ||
| 34 | + | ``` pascal | |
| 35 | + | procedure TForm1.FormPaint(Sender: TObject); | |
| 36 | + | begin | |
| 37 | + | PaintImage; | |
| 38 | + | end; | |
| 39 | + | ``` | |
| 40 | + | ||
| 41 | + | Schreiben Sie die Prozedur 'PaintImage': | |
| 42 | + | ||
| 43 | + | ``` pascal | |
| 44 | + | procedure TForm1.PaintImage; | |
| 45 | + | begin | |
| 46 | + | image.Draw(Canvas,0,0,True); | |
| 47 | + | end; | |
| 48 | + | ``` | |
| 49 | + | ||
| 50 | + | Danach setzen Sie den Mauszeiger auf PaintImage und drücken Strg-Umsch-C, um die Deklaration dem Interface hinzuzufügen. | |
| 51 | + | ||
| 52 | + | ### Behandeln Sie die Maus-Ereignisse | |
| 53 | + | ||
| 54 | + | Im Objektinspektor fügen Sie für die Ereignisse 'MouseDown' und 'MouseMove' jeweils einen Handler hinzu: | |
| 55 | + | ||
| 56 | + | ``` pascal | |
| 57 | + | procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 58 | + | Shift: TShiftState; X, Y: Integer); | |
| 59 | + | begin | |
| 60 | + | if Button = mbLeft then DrawBrush(X,Y); | |
| 61 | + | end; | |
| 62 | + | ||
| 63 | + | procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, | |
| 64 | + | Y: Integer); | |
| 65 | + | begin | |
| 66 | + | if ssLeft in Shift then DrawBrush(X,Y); | |
| 67 | + | end; | |
| 68 | + | ``` | |
| 69 | + | ||
| 70 | + | Ergänzen Sie die Prozedur 'DrawBrush': | |
| 71 | + | ||
| 72 | + | ``` pascal | |
| 73 | + | procedure TForm1.DrawBrush(X, Y: Integer); | |
| 74 | + | const radius = 5; | |
| 75 | + | begin | |
| 76 | + | image.GradientFill(X-radius,Y-radius, X+radius,Y+radius, | |
| 77 | + | BGRABlack,BGRAPixelTransparent, gtRadial, | |
| 78 | + | PointF(X,Y), PointF(X+radius,Y), dmDrawWithTransparency); | |
| 79 | + | ||
| 80 | + | PaintImage; | |
| 81 | + | end; | |
| 82 | + | ``` | |
| 83 | + | ||
| 84 | + | Danach setzen Sie den Mauszeiger auf DrawBrush und drücken Strg-Umsch-C, um die Deklaration dem Interface hinzuzufügen. | |
| 85 | + | ||
| 86 | + | Diese Prozedur zeichnet einen radialen Farbverlauft (gtRadial): | |
| 87 | + | ||
| 88 | + | - das umgebende Rechteck ist (X-radius,Y-radius, X+radius,Y+radius). | |
| 89 | + | - die Mitte ist schwarz, der Rand ist transparent | |
| 90 | + | - die Mitte ist bei (X,Y) und der Rand bei (X+radius,Y) | |
| 91 | + | ||
| 92 | + | ### Code | |
| 93 | + | ||
| 94 | + | ``` pascal | |
| 95 | + | unit UMain; | |
| 96 | + | ||
| 97 | + | {$mode objfpc}{$H+} | |
| 98 | + | ||
| 99 | + | interface | |
| 100 | + | ||
| 101 | + | uses | |
| 102 | + | Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, | |
| 103 | + | BGRABitmap, BGRABitmapTypes; | |
| 104 | + | ||
| 105 | + | type | |
| 106 | + | { TForm1 } | |
| 107 | + | ||
| 108 | + | TForm1 = class(TForm) | |
| 109 | + | procedure FormCreate(Sender: TObject); | |
| 110 | + | procedure FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 111 | + | Shift: TShiftState; X, Y: Integer); | |
| 112 | + | procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); | |
| 113 | + | procedure FormPaint(Sender: TObject); | |
| 114 | + | private | |
| 115 | + | { private declarations } | |
| 116 | + | image: TBGRABitmap; | |
| 117 | + | procedure DrawBrush(X, Y: Integer); | |
| 118 | + | procedure PaintImage; | |
| 119 | + | public | |
| 120 | + | { public declarations } | |
| 121 | + | end; | |
| 122 | + | ||
| 123 | + | var | |
| 124 | + | Form1: TForm1; | |
| 125 | + | ||
| 126 | + | implementation | |
| 127 | + | ||
| 128 | + | { TForm1 } | |
| 129 | + | ||
| 130 | + | procedure TForm1.FormCreate(Sender: TObject); | |
| 131 | + | begin | |
| 132 | + | image := TBGRABitmap.Create(640,480,BGRAWhite); | |
| 133 | + | end; | |
| 134 | + | ||
| 135 | + | procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 136 | + | Shift: TShiftState; X, Y: Integer); | |
| 137 | + | begin | |
| 138 | + | if Button = mbLeft then DrawBrush(X,Y); | |
| 139 | + | end; | |
| 140 | + | ||
| 141 | + | procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, | |
| 142 | + | Y: Integer); | |
| 143 | + | begin | |
| 144 | + | if ssLeft in Shift then DrawBrush(X,Y); | |
| 145 | + | end; | |
| 146 | + | ||
| 147 | + | procedure TForm1.FormPaint(Sender: TObject); | |
| 148 | + | begin | |
| 149 | + | PaintImage; | |
| 150 | + | end; | |
| 151 | + | ||
| 152 | + | procedure TForm1.DrawBrush(X, Y: Integer); | |
| 153 | + | const radius = 20; | |
| 154 | + | begin | |
| 155 | + | image.GradientFill(X-radius,Y-radius, X+radius,Y+radius, | |
| 156 | + | BGRABlack,BGRAPixelTransparent,gtRadial, | |
| 157 | + | PointF(X,Y), PointF(X+radius,Y), dmDrawWithTransparency); | |
| 158 | + | ||
| 159 | + | PaintImage; | |
| 160 | + | end; | |
| 161 | + | ||
| 162 | + | procedure TForm1.PaintImage; | |
| 163 | + | begin | |
| 164 | + | image.Draw(Canvas,0,0,True); | |
| 165 | + | end; | |
| 166 | + | ||
| 167 | + | initialization | |
| 168 | + | {$I UMain.lrs} | |
| 169 | + | ||
| 170 | + | end. | |
| 171 | + | ``` | |
| 172 | + | ||
| 173 | + | ### Starten Sie das Programm | |
| 174 | + | ||
| 175 | + | Sie sollten mit der Maus auf dem Formular zeichnen können. | |
| 176 | + | ||
| 177 | + | <figure> | |
| 178 | + | <img src="BGRATutorial3.png" title="BGRATutorial3.png" /> | |
| 179 | + | <figcaption>BGRATutorial3.png</figcaption> | |
| 180 | + | </figure> | |
| 181 | + | ||
| 182 | + | ### Kontinuierliches Zeichnen | |
| 183 | + | ||
| 184 | + | Für das kontinuierliche Zeichnen brauchen wir zusätzliche Variablen: | |
| 185 | + | ||
| 186 | + | ``` pascal | |
| 187 | + | TForm1 = class(TForm) | |
| 188 | + | ... | |
| 189 | + | private | |
| 190 | + | { private declarations } | |
| 191 | + | image: TBGRABitmap; | |
| 192 | + | mouseDrawing: boolean; | |
| 193 | + | mouseOrigin: TPoint; | |
| 194 | + | ``` | |
| 195 | + | ||
| 196 | + | 'mouseDrawing' ist während des Zeichnens (also bei gedrückter linker Maustaste) TRUE und 'mouseOrigin' ist der Anfangspunkt des zu zeichnenden Segments. | |
| 197 | + | ||
| 198 | + | Der Klick-Handler wird dadurch ein bisschenkomplizierter: | |
| 199 | + | ||
| 200 | + | ``` pascal | |
| 201 | + | procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 202 | + | Shift: TShiftState; X, Y: Integer); | |
| 203 | + | begin | |
| 204 | + | if Button = mbLeft then | |
| 205 | + | begin | |
| 206 | + | mouseDrawing := True; | |
| 207 | + | mouseOrigin := Point(X,Y); | |
| 208 | + | DrawBrush(X,Y,True); | |
| 209 | + | end; | |
| 210 | + | end; | |
| 211 | + | ``` | |
| 212 | + | ||
| 213 | + | Er initialisiert die Zeichnung mit der aktuellen Position. Dann zeichnet er ein geschlossenes Segment (beachten Sie den neuen Parameter von DrawBrush). Wirklich, am Anfang wird das Segment geschlossen und hat die Länge Null, das ergibt eine Scheibe: | |
| 214 | + | ||
| 215 | + | <figure> | |
| 216 | + | <img src="BGRATutorial3b.png" title="BGRATutorial3b.png" /> | |
| 217 | + | <figcaption>BGRATutorial3b.png</figcaption> | |
| 218 | + | </figure> | |
| 219 | + | ||
| 220 | + | Schritt für Schritt fügen wir einen neuen Teil (aber ein offenes Segment) hinzu: | |
| 221 | + | ||
| 222 | + | <figure> | |
| 223 | + | <img src="BGRATutorial3c.png" title="BGRATutorial3c.png" /> | |
| 224 | + | <figcaption>BGRATutorial3c.png</figcaption> | |
| 225 | + | </figure> | |
| 226 | + | ||
| 227 | + | Darum brauchen wir einen neuen Parameter für die Funktion 'DrawBrush', diese wird zu: | |
| 228 | + | ||
| 229 | + | ``` pascal | |
| 230 | + | procedure TForm1.DrawBrush(X, Y: Integer; Closed: Boolean); | |
| 231 | + | const brushRadius = 20; | |
| 232 | + | begin | |
| 233 | + | image.DrawLineAntialias(X,Y,mouseOrigin.X,mouseOrigin.Y,BGRA(0,0,0,128),brushRadius,Closed); | |
| 234 | + | mouseOrigin := Point(X,Y); | |
| 235 | + | ||
| 236 | + | PaintImage; | |
| 237 | + | end; | |
| 238 | + | ``` | |
| 239 | + | ||
| 240 | + | Wir übergen den Parameter 'Closed' an 'DrawLineAntialias', um anzuzeigen, ob das Segment geschlossen ist oder nicht. Beachten Sie die Reihenfolge der Koordinaten. Die Anfangs- und Endposition sind vertauscht. Tatsächlich ist für 'DrawLineAntialias' das Ende offen - wir hingegen wollen in diesem Fall, dass der Anfang offen ist. | |
| 241 | + | ||
| 242 | + | Die Definition von DrawBrush muss im Interface angepasst werden. | |
| 243 | + | ||
| 244 | + | Der MouseMove-Handler wird zu: | |
| 245 | + | ||
| 246 | + | ``` pascal | |
| 247 | + | procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, | |
| 248 | + | Y: Integer); | |
| 249 | + | begin | |
| 250 | + | if mouseDrawing then DrawBrush(X,Y,False); | |
| 251 | + | end; | |
| 252 | + | ``` | |
| 253 | + | ||
| 254 | + | Zuletzt fügen wir einen MouseUp-Handler hinzu, der 'mouseDrawing' aktualisiert: | |
| 255 | + | ||
| 256 | + | ``` pascal | |
| 257 | + | procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; | |
| 258 | + | Shift: TShiftState; X, Y: Integer); | |
| 259 | + | begin | |
| 260 | + | if Button = mbLeft then | |
| 261 | + | mouseDrawing := False; | |
| 262 | + | end; | |
| 263 | + | ``` | |
| 264 | + | ||
| 265 | + | ### Code | |
| 266 | + | ||
| 267 | + | ``` pascal | |
| 268 | + | unit UMain; | |
| 269 | + | ||
| 270 | + | {$mode objfpc}{$H+} | |
| 271 | + | ||
| 272 | + | interface | |
| 273 | + | ||
| 274 | + | uses | |
| 275 | + | Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, | |
| 276 | + | BGRABitmap, BGRABitmapTypes; | |
| 277 | + | ||
| 278 | + | type | |
| 279 | + | { TForm1 } | |
| 280 | + | ||
| 281 | + | TForm1 = class(TForm) | |
| 282 | + | procedure FormCreate(Sender: TObject); | |
| 283 | + | procedure FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 284 | + | Shift: TShiftState; X, Y: Integer); | |
| 285 | + | procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); | |
| 286 | + | procedure FormMouseUp(Sender: TObject; Button: TMouseButton; | |
| 287 | + | Shift: TShiftState; X, Y: Integer); | |
| 288 | + | procedure FormPaint(Sender: TObject); | |
| 289 | + | private | |
| 290 | + | { private declarations } | |
| 291 | + | image: TBGRABitmap; | |
| 292 | + | mouseDrawing: boolean; | |
| 293 | + | mouseOrigin: TPoint; | |
| 294 | + | procedure DrawBrush(X, Y: Integer; Closed: boolean); | |
| 295 | + | procedure PaintImage; | |
| 296 | + | public | |
| 297 | + | { public declarations } | |
| 298 | + | end; | |
| 299 | + | ||
| 300 | + | var | |
| 301 | + | Form1: TForm1; | |
| 302 | + | ||
| 303 | + | implementation | |
| 304 | + | ||
| 305 | + | { TForm1 } | |
| 306 | + | ||
| 307 | + | procedure TForm1.FormCreate(Sender: TObject); | |
| 308 | + | begin | |
| 309 | + | image := TBGRABitmap.Create(640,480,BGRAWhite); | |
| 310 | + | end; | |
| 311 | + | ||
| 312 | + | procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; | |
| 313 | + | Shift: TShiftState; X, Y: Integer); | |
| 314 | + | begin | |
| 315 | + | if Button = mbLeft then | |
| 316 | + | begin | |
| 317 | + | mouseDrawing := True; | |
| 318 | + | mouseOrigin := Point(X,Y); | |
| 319 | + | DrawBrush(X,Y,True); | |
| 320 | + | end; | |
| 321 | + | end; | |
| 322 | + | ||
| 323 | + | procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, | |
| 324 | + | Y: Integer); | |
| 325 | + | begin | |
| 326 | + | if mouseDrawing then DrawBrush(X,Y,False); | |
| 327 | + | end; | |
| 328 | + | ||
| 329 | + | procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; | |
| 330 | + | Shift: TShiftState; X, Y: Integer); | |
| 331 | + | begin | |
| 332 | + | if Button = mbLeft then | |
| 333 | + | mouseDrawing := False; | |
| 334 | + | end; | |
| 335 | + | ||
| 336 | + | procedure TForm1.FormPaint(Sender: TObject); | |
| 337 | + | begin | |
| 338 | + | PaintImage; | |
| 339 | + | end; | |
| 340 | + | ||
| 341 | + | procedure TForm1.DrawBrush(X, Y: Integer; Closed: Boolean); | |
| 342 | + | const brushRadius = 20; | |
| 343 | + | begin | |
| 344 | + | image.DrawLineAntialias(X,Y,mouseOrigin.X,mouseOrigin.Y,BGRA(0,0,0,128),brushRadius,Closed); | |
| 345 | + | mouseOrigin := Point(X,Y); | |
| 346 | + | ||
| 347 | + | PaintImage; | |
| 348 | + | end; | |
| 349 | + | ||
| 350 | + | procedure TForm1.PaintImage; | |
| 351 | + | begin | |
| 352 | + | image.Draw(Canvas,0,0,True); | |
| 353 | + | end; | |
| 354 | + | ||
| 355 | + | initialization | |
| 356 | + | {$I UMain.lrs} | |
| 357 | + | ||
| 358 | + | end. | |
| 359 | + | ``` | |
| 360 | + | ||
| 361 | + | ### Starten Sie das Programm | |
| 362 | + | ||
| 363 | + | Jetzt ist das Zeichnen nahezu kontinuierlich: | |
| 364 | + | ||
| 365 | + | <figure> | |
| 366 | + | <img src="BGRATutorial3d.png" title="BGRATutorial3d.png" /> | |
| 367 | + | <figcaption>BGRATutorial3d.png</figcaption> | |
| 368 | + | </figure> | |
| 369 | + | ||
| 370 | + | [[BGRABitmap tutorial 2/de|Voriges Tutorial (Laden eines Bildes)]] \| [[BGRABitmap tutorial 4/de|Nächstes Tutorial (direkter Zugriff auf die Pixel)]] | |
| 371 | + | ||
| 372 | + | --- | |
| 373 | + | *From the Free Pascal wiki, page "BGRABitmap tutorial 3/de", as it stood on 2020-02-10 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
