Autor Beitrag
Daether
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Do 18.08.05 13:17 
Moin,
habe bie meinem Spiel ein paar fortschirtte gemacht, dank eurer Hilfe. Nun brauche ich wieder eure Hilfe.
Wie kann ich das Drawgrid dazu bringen, die gezeichnetetn Bitmaps nicht selbst wieder zu übermalen.
Ich weiß, dass man das Ereigniss onDrawCell nehmen muss und habe folgendes eingefügt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
DrawGridSpielFeld.refresh;
end;

desweiteren, lasse ich so die Bilder malen:
ausblenden Delphi-Quelltext
1:
FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*35,j*35,Bitmap);					


Wie kriege ich das Drawgrid dazu nicht in eine Endloschleife zu verfallen (wie momentan) und wie kriege ich es dazu die Bitmaps stehen zu lassen?
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Do 18.08.05 15:21 
Wenn ein DrawGrid gezeichnet wird, dann ruft es für jede einzelne Zelle einmal OnDrawCell auf (natürlich nicht jedesmal für alle Zellen, sondern nur für diejenigen, die auch tatsächlich neu gezeichnet werden müssen). Du musst den Inhalt einer Zelle also im OnDrawCell Ereignis zeichnen, nicht vorher und nicht nachher!
Dein jetziger OnDrawCell-Code DrawGridSpielFeld.refresh; ist Quatsch, denn Refresh veranlasst, dass das DrawGrid sofort neu gezeichnet wird, was zur Folge hat, dass wieder OnDrawCell aufgerufen wird... daher die Endlosschleife.
Daether Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Do 18.08.05 16:51 
ist diese Prozedur denn jetzt richtig?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var i,j: integer;
    Bitmap: TBitmap;
begin
Bitmap:= TBitmap.Create;
for i:=0 to strtoint(FormStartbedingungen.EditBreite.text)-1 do
begin
  for j:=0 to strtoint(FormStartbedingungen.EditHoehe.Text)-1 do
  begin
    if Spiel.Spielfeld[i,j].Planet.Name ='Planetwueste' then
    begin
      Bitmap.LoadFromFile('PlanetWueste.bmp');
      FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*34,j*34,Bitmap);
    end
    else
    begin
      Bitmap.LoadFromFile('All.bmp');
      FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*34,j*34,Bitmap);
    end;
  end;
end;
end;

Denn das Problem dabei ist, dass ich an die 100x100 Felder habe und sobald ich nur eines anklicke alle anderen neu gezeichnet werden.
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Do 18.08.05 17:06 
Nein, nicht ganz richtig. Du zeichnest jetzt in OnDrawCell mit den beiden Schleifen ALLE Zellen. Du sollst aber nur EINE Zelle zeichnen, nämlich genau diejenige, die durch die Parameter ACol, ARow und Rect angegeben wird. Außerdem vergisst du, das Bitmap mit Bitmap.Free wieder freizugeben, das ist nicht gut. Besonders effizient ist dein Vorgehen auch nicht, aber bevor man das optimiert, solltest du erstmal die Funktionsweise des DrawGrids verstanden haben.
Daether Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Do 18.08.05 20:01 
Ich glaube ich verstehe was du meinst. Habe die Prozedur nun umgeschrieben und habe das Problem nichtmehr, ich kann einzelne Bilder anklicken und auch Markierungen ziehen, ohne das ein Problem auftritt.
Anbie mal mein Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var i,j: integer;
    Bitmap: TBitmap;
begin
Bitmap:= TBitmap.Create;
if Spiel.Spielfeld[Acol,Arow].Planet.Name ='Planetwueste' then
    begin
      Bitmap.LoadFromFile('PlanetWueste.bmp');
      FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap);
    end
    else
    begin
      Bitmap.LoadFromFile('All.bmp');
      FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap);
    end;
Bitmap.free;

Ich habe das Bitmap nun frei gegeben und ich könnte (muss später) das ganze umstellen und anstatt mit if/then, case/of benutzten.
Danke schonmal für die Hilfe!

Aber ich habe jetzt ein ähnlich neues Problem. Wie kann ich die Bilder zeichnen und "verschieben", wenn ich die Scrollleisste eines Drawgrids benutze? Denn immer wenn ich die Scrollleisten bewege zeichnen sich die Bilder nicht neu, da ich ja onDrawCell so eingestellt habe, das die markierte Zelle gemalt wird.
Keldorn
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Do 18.08.05 20:21 
user profile iconDaether hat folgendes geschrieben:

Aber ich habe jetzt ein ähnlich neues Problem. Wie kann ich die Bilder zeichnen und "verschieben", wenn ich die Scrollleisste eines Drawgrids benutze? Denn immer wenn ich die Scrollleisten bewege zeichnen sich die Bilder nicht neu, da ich ja onDrawCell so eingestellt habe, das die markierte Zelle gemalt wird.

wo hast du denn die Abfrage, das du nur die markierte Zelle zeichnest? Du fragst den State doch gar nicht ab.

Aber die Funktionsweise von drawcell hast du auch nicht verstanden und es gibt hier im Fourm auch genügend CodeBeispiele, wirklich. Dein Problem beim scrollen rührt denke ich mal hiervon:
ausblenden Delphi-Quelltext
1:
FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap);					

richtig wäre:
ausblenden Delphi-Quelltext
1:
FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(rect.left,rect.top,Bitmap);					

rect ist die zu zeichnende Zelle, es ist nicht notwendig, das selber auzurechnen.

und zur Effizienz:
Wenn du jedesmal bei ondrawcell die Bitmap erstellst, ist das ein Performancekiller. In diesem Fall ist eine globalere Veriable besser angebracht und die Bitmap wird 1x erstellt und freigegeben, aber auch das brauchst du nicht, s.u..
Desweitern wird sich das loadfromfile auch nicht grad gut machen. Jedesmal, wenn die Zelle neu gezeichnet wird (Scrollen, Selektionsänderung, ...), lädst du das Bitmap von der Platte. Außerdem beuntzt Du nur relative Pfade und die werden dich irgendwann sicher vor Probelem stellen.

Erstell dir besser eine Liste/Array/Imagelist, wo du deine Bilder am Programmstart reinlädst. Bei Ondrawcell zeichnest du dann das entsprechende Bild aus der Liste und lädst es nicht erst von der Platte.

Mfg Frank

_________________
Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Do 18.08.05 20:28 
Jepp, wie Keldorn bereits geschrieben hat, dein Problem beim Scrollen kommt daher, dass du versuchst, die Canvas-Position der Zellen selbst auszurechnen anstatt den Rect Parameter dafür zu verwenden.
Statt Canvas.Draw kannst du übrigens auch Canvas.StretchDraw benutzen, dann wird dein Bitmap auf Zellengröße skaliert, falls es kleiner oder größer ist:
ausblenden Delphi-Quelltext
1:
DrawGridSpielfeld.Canvas.StretchDraw(Rect, Bitmap);					
Daether Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Do 18.08.05 20:43 
Danke für eure Hilfe.
Wenn wir schon dabei sind und ihr noch Zeit habt :D :
Ich werde es mal mit dem "BilderArray" versuchen.
Mal ne Frage Dazu, wie mache ich das mit Bitmap create und free?

Das ist meine momentane Struktur die in einer einzelnen UnitFunktionen ist:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
type
  TBild = record
          Name : string;
          Bitmap : TBitmap;
          end;
  TBilder = array of TBild;
  TPlanet = record
            Name : string;
            end;
  TSchiff = record
            Name : String;
            end;
  TFeld = record
          Planet : TPlanet;
          Schiffe : array of TSchiff;
          end;
  TSpielfeld = record
               Spielfeld : array of array of TFeld;
               end;
  TSpiel = class
  private
  public
  procedure Neuesspiel(Breite,Hoehe : integer);
  end;

var  Spiel : TSpielfeld;
     Spielfunktionen : TSpiel;


So könnte ich ja den Array (dynamisch) mit einer procedur füllen und alle Bilder in die "Bitmap"-Variablen reinladen. Muss ich die dann alle noch vorher createn? Wenn ja, wie lege ich fest wann sie auf free gesetzt werden?