Hoofdstuk 10.1 Toepassing: Bitmap-editor Toepassing: Bitmap-editor Klik punten op scherm Plaatje verschuiven left, right, up, down Plaatje bewerken clear, invert, bold, outline “Game of life” Opdeling in klassen Hoofdscherm gebruikersinterface, menu’s, akties, files BitmapControl tekenen van het plaatje op het scherm BitMap plaatje in geheugen, operaties Member-variabelen class Hoofdscherm : Form BitmapControl viewer; MenuStrip menuStrip; : UserControl class BitmapControl BitMap model; class BitMap bool [ , ] vakjes; zelfgemaakt Methoden Hoofdscherm class Hoofdscherm : Form Hoofdscherm vergroten // eventhandler voor Resize afsluiten // eventhandler voor "Close"-menu Methoden BitmapControl class BitmapControl : UserControl BitmapControl teken // eventhandler voor Paint klik // eventhandler voor MouseClick starten, stoppen // voor animatie-menu uitvoeren // voor andere menu-keuzes Methoden BitMap class BitMap constructor properties punten zetten schuiven bewerken game of life BitMap, BitMap Breedte, Hoogte veranderKleur, vraagKleur Left, Right, Up, Down Clear, Invert, Bold, Outline combineer Life, buren Methoden BitMap (versie 2) class BitMap : System.Drawing.Bitmap constructor properties punten zetten schuiven bewerken game of life BitMap, BitMap Breedte, Hoogte veranderKleur, vraagKleur Left, Right, Up, Down Clear, Invert, Bold, Outline combineer Life, buren class Hoofdscherm public Hoofdscherm( ) { this . Text = "Bitmap Editor"; this . viewer = new BitmapControl(); this . menuStrip = new MenuStrip( ); this . maakMenu(); this . Controls . Add(menuStrip); this . Controls . Add(viewer); } this . Resize += this.vergroten; this . vergroten(null, null); // meteen al even class Hoofdscherm MenuStrip menuStrip; BitmapControl viewer; private void maakMenu( ) { ToolStripDropDownItem menu; menu = new ToolStripDropDownItem("File"); menu.DropDownItems.Add("Close", null, this.afsluiten); menuStrip . Items . Add(menu); menu = new ToolStripMenuItem("Move"); menu.DropDownItems.Add("Left", null, viewer.uitvoeren); menu.DropDownItems.Add("Right",null, viewer.uitvoeren); menu.DropDownItems.Add("Up", null, viewer.uitvoeren); menu.DropDownItems.Add("Down",null, viewer.uitvoeren); menuStrip . Items . Add(menu); } class Hoofdscherm void vergroten (object o, EventArgs ea) { int w = this.ClientSize.Width – 20; int h = this.ClientSize.Height – 50; } viewer.Location = new Point(10,40); viewer.Size = new Size (w, h); void afsluiten (object o, EventArgs ea) { this.Close(); } Methoden BitMap class BitMap constructor properties punten zetten schuiven bewerken game of life BitMap, BitMap Breedte, Hoogte veranderKleur, vraagKleur Left, Right, Up, Down Clear, Invert, Bold, Outline combineer Life, buren class BitMap public BitMap ( int w, int h ) { vakjes = new bool [w , h]; } public BitMap ( BitMap ander) { vakjes = new bool [ander.Breedte , ander.Hoogte]; this.Kopieer(ander); } public void verander ( int x, int y, bool b ) vakjes[x, y] = b; { } public bool vraag ( int x, int y ) { return vakjes[x, y] ; } property public int Breedte { get { return vakjes.GetLength(0); } } class BitMap void combineer ( Bitmap ander , Functie comb ) { for (int x=0; this.Breedte; x++) for (int y=0; y<this.Hoogte; y++) this . verander (x, y, comb ( this.vraag(x,y) , ander.vraag(x,y) ) nieuwe type-declaratie:); nieuwe expressie: } het type van een functie naamloze functie delegate bool Functie (bool, bool) ; void Clear ( ) { this.combineer(this, (a,b)=>false ); } void Invert ( ) { this.combineer(this, (a,b)=>!a ); } void Kopieer(Bitmap ander) { this.combineer(ander, (a,b)=>b ); } class BitMap public void Left ( ) { for (int y=0; y<this.Hoogte; y++) { for (int x=0 1 ; x<this.Breedte; x++) this.verander( x-1, y, this.vraag(x,y) ); this.verander( this.Breedte-1, y, false ); } } class BitMap public void Right ( ) { for (int y=0; y<Hoogte; y++) { for (int x=0Breedte-1; ; x<Breedte; x++) x>0; x-- ) this.verander( x, y, this.vraag(x-1 ,y) ); this.verander( 0, y, false ); } } class BitMap public void Bold ( ) { BitMap ander; ander = new BitMap(this); ander . Left ( ); this . combineer (ander, (a,b)=>a||b ); ander = new BitMap(this); ander . Down ( ); this . combineer (ander, (a,b)=>a||b ); } class BitMap public void Outline ( ) { BitMap ander; ander = new BitMap(this); ander . Left ( ); ander . Down ( ); this . combineer (ander, (a,b) => a != b ); } class BitMap public void Life ( ) { BitMap oud; oud = new BitMap(this); for (int y=0; y<Hoogte; y++) for (int x=0; x<Breedte; x++) { int n = oud . buren(x,y); this . verander (x, y, n==3 || n==2 && oud.vraag(x,y) ); } } class BitMap public int buren (int x, int y ) if (xl<0) xl += Breedte; { int xl = x-1; int xr = x+1; if (xr>=breed) xr -= Breedte; int yb = y-1; if (yb<0) yb += Hoogte; int yo = y+1; if (yo>=hoog) yo -= Hoogte; int n = 0; if ( this.isZwart(xl,yb) ) n++; if ( this.isZwart(x ,yb) ) n++; if ( this.isZwart(xr,yb) ) n++; yb if ( this.isZwart(xl,y ) ) n++; if ( this.isZwart(xr,y ) ) n++; if ( this.isZwart(xl,yo) ) n++; yo if ( this.isZwart(x ,yo) ) n++; if ( this.isZwart(xr,yo) ) n++; return n; xl xr Game of Life meer-cellig “wezen” loopt! stabiel patroon Methoden BitmapControl class BitmapControl : UserControl BitmapControl teken // eventhandler voor Paint klik // eventhandler voor MouseClick starten, stoppen // voor animatie-menu uitvoeren // voor andere menu-keuzes membervariabele: Bitmap model; class BitmapControl class BitmapControl { Bitmap model; public BitmapControl ( ) { model = new Bitmap(20, 20); this . Paint += teken; this . MouseClick += klik; } class BitmapControl void teken ( object o, PEA pea ) { Graphics gr = pea.Graphics; int d = this . Diameter; this . lijnen (gr, d); for (int y=0; y<Hoogte; y++) for (int x=0; x<Breedte; x++) { Brush br; if (model.vraag(x,y)) br = Brushes.Red; else br = Brushes.White; gr . FillRectangle (br, x,x*d+1, x*d, y, 1,y*d, 1); y*d+1, d, d );d-1, d-1 ); } } class BitmapControl public int Diameter { get { Size s = this . ClientSize; return Math . min ( s.Width / model.Breedte , s.Height / model.Hoogte ); } } class BitmapControl private void lijnen ( Graphics gr, int d) { Pen p = Color.Blue; // horizontale lijnen for (int y=0; y <= Hoogte; y++) gr . drawLine ( p, 0, y*d, model.Breedte*d, y*d ); // verticale lijnen for (int x=0; x <= Breedte; x++) gr . drawLine ( p, x*d, 0, x*d, model.Hoogte*d ); } class BitmapControl void klik ( object o, MouseEventArgs mea ) { int diam = this . Diameter; model . verander ( mea . X / diam , mea . Y / diam , mea.Button==MouseButtons.Left ); } this . Invalidate ( ); class BitmapControl void uivoeren ( object sender, EventArgs ea ) { String keus = sender.ToString(); if if if if if if (keus=="Clear") this.model.Clear(); (keus=="Left") this.model.Left(); (keus=="Right") this.model.Right(); (keus=="Up") this.model.Up(); (keus=="Down") this.model.Down(); (keus=="Step") this.model.Step(); this . Invalidate ( ); } class BitmapControl Thread animatie; void starten ( object o, EventArgs ea ) animatie = new Thread(animatieFunctie); { animatie . Start( ); } void stoppen ( object o, EventArgs ea ) { animatie = null; } void animatieFunctie( ) (animatie!=null) ){ { { while (true this.model.Life( ); this.Invalidate( ); Thread.Sleep(50); } }