[gelöst]DrawGrid wird beim Programmstart nicht richtig...
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
[gelöst]DrawGrid wird beim Programmstart nicht richtig...
Hi,
ich benutze ein DrawGrid, um ein zweidimensionales Spielfeld darzustellen. Beim Programmstart wird es nicht korrekt dargestellt: die oberen zwei Zeilen sind nicht sichtbar, dafür wird unten ein Rand von zwei Zeilen dargestellt (siehe beigefügtes Bild). Ich habe schon mit den Ankern usw. rumgespielt, aber keine Lösung gefunden. Das Problem tritt nur bei der ersten Darstellung des Grids auf. Ab Level 2 ist alles in Ordnung!? Könnt ihr mir sagen, was da schief geht?
Das Programm wird unter Windows entwickelt. Programmcode anbei.
ich benutze ein DrawGrid, um ein zweidimensionales Spielfeld darzustellen. Beim Programmstart wird es nicht korrekt dargestellt: die oberen zwei Zeilen sind nicht sichtbar, dafür wird unten ein Rand von zwei Zeilen dargestellt (siehe beigefügtes Bild). Ich habe schon mit den Ankern usw. rumgespielt, aber keine Lösung gefunden. Das Problem tritt nur bei der ersten Darstellung des Grids auf. Ab Level 2 ist alles in Ordnung!? Könnt ihr mir sagen, was da schief geht?
Das Programm wird unter Windows entwickelt. Programmcode anbei.
- Dateianhänge
-
MinedOut.zip
- (72.59 KiB) 49-mal heruntergeladen
Zuletzt geändert von Marsmännchen am Fr 25. Nov 2016, 23:37, insgesamt 1-mal geändert.
Ich mag Pascal...
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Seltsam, bei mir startet das Programm gleich in der richtigen Darstellung. Sorry, ich kann dir da konkret nicht helfen.
Gehe in die Projekt-Optionen und entferne vorübergehend unter "Konfiguration und Ziele" das Häkchen vor "Win32-GUI-Anwendung". Dann kannst du per WriteLn Variablenwerte auf der Konsole ausgeben (das ist einfacher als mit dem Debugger mit Klassen zu arbeiten). Nicht vergessen, die WriteLn-Anweisungen wieder zu entfernen, wenn du das Win32-GUI Häkchen wieder setzt, sonst stürzt das Programm am WriteLn ab. Folgende Grid-Größen fallen mir im Zusammenhang mit dem beschriebenen Verhalten ein:
- Pitch.RowCount --> Zahl der Zeilen im Grid
- Pitch.TopRow --> Index der ersten oben sichtbaren Zeile, muss 0 sein.
- Pitch.Top --> Pixel-Koordinate des oberen Randes des Grids, muss 0 sein.
- Pitch.DefaultRowHeight --> Höhe der Zeilen
Da du diese Größen nirgendwo explizit veränderst, würde ich die writeLn's in die FormCreate-/FormActivate-/ und FormShow-Methoden setzen und prüfen, ob die ausgegebenen Werte irgendwo von den erwarteten abweichen.
Unabhängig von deinem Problem ist mir aufgefallen, dass du eine TFPGList verwendest, in der du TPos-Objekte speicherst. Im Zusammenhang mit irgendwelchen TList-Objekten blitzt bei mir gleich die Warnlampe: Speicherleck! Und tatsächlich, wenn du in dem Compileroptionen / Debuggen die HeapTrace-Unit aktivierst, das Programm neu kompilierst, startest und gleich wieder beendest, wird dir beim Programmende eine Liste von Speicherlecks angezeigt. Das liegt daran, dass TFPGList eigentlich nur Zeiger speichert und nicht weiß, wie die zugehörigen Speicherbereich wieder freigegeben werden müssen. Nimmst du stattdessen TFPGObjectList, werden statt nackten Zeigern Objekte gespeichert, von denen die Liste weiß, dass es eine Destroy-Methode gibt --> keine Speicherlecks mehr.
Und eine kleine Anregung noch: die immer nach oben weisenden Spuren sehen etwas seltsam aus, wenn der Spieler sich nach links/rechts/unten bewegt. Drehe das Bitmap in einem Bildbearbeitungsprogramm doch um 90, 180 und 270 Grad und nimm diese gedrehten Fußabdrücke ebenfalls in die ImageList mit auf, so dass du dann das in Bewegungsrichtung weisende Bitmap auswählen kannst.
Gehe in die Projekt-Optionen und entferne vorübergehend unter "Konfiguration und Ziele" das Häkchen vor "Win32-GUI-Anwendung". Dann kannst du per WriteLn Variablenwerte auf der Konsole ausgeben (das ist einfacher als mit dem Debugger mit Klassen zu arbeiten). Nicht vergessen, die WriteLn-Anweisungen wieder zu entfernen, wenn du das Win32-GUI Häkchen wieder setzt, sonst stürzt das Programm am WriteLn ab. Folgende Grid-Größen fallen mir im Zusammenhang mit dem beschriebenen Verhalten ein:
- Pitch.RowCount --> Zahl der Zeilen im Grid
- Pitch.TopRow --> Index der ersten oben sichtbaren Zeile, muss 0 sein.
- Pitch.Top --> Pixel-Koordinate des oberen Randes des Grids, muss 0 sein.
- Pitch.DefaultRowHeight --> Höhe der Zeilen
Da du diese Größen nirgendwo explizit veränderst, würde ich die writeLn's in die FormCreate-/FormActivate-/ und FormShow-Methoden setzen und prüfen, ob die ausgegebenen Werte irgendwo von den erwarteten abweichen.
Unabhängig von deinem Problem ist mir aufgefallen, dass du eine TFPGList verwendest, in der du TPos-Objekte speicherst. Im Zusammenhang mit irgendwelchen TList-Objekten blitzt bei mir gleich die Warnlampe: Speicherleck! Und tatsächlich, wenn du in dem Compileroptionen / Debuggen die HeapTrace-Unit aktivierst, das Programm neu kompilierst, startest und gleich wieder beendest, wird dir beim Programmende eine Liste von Speicherlecks angezeigt. Das liegt daran, dass TFPGList eigentlich nur Zeiger speichert und nicht weiß, wie die zugehörigen Speicherbereich wieder freigegeben werden müssen. Nimmst du stattdessen TFPGObjectList, werden statt nackten Zeigern Objekte gespeichert, von denen die Liste weiß, dass es eine Destroy-Methode gibt --> keine Speicherlecks mehr.
Und eine kleine Anregung noch: die immer nach oben weisenden Spuren sehen etwas seltsam aus, wenn der Spieler sich nach links/rechts/unten bewegt. Drehe das Bitmap in einem Bildbearbeitungsprogramm doch um 90, 180 und 270 Grad und nimm diese gedrehten Fußabdrücke ebenfalls in die ImageList mit auf, so dass du dann das in Bewegungsrichtung weisende Bitmap auswählen kannst.
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Hi,
das ist ja ein ganzer Strauß von guten Hinweisen, danke
.
Das probiere ich gleich heute Nachmittag aus.
BTW: Ich habe das Programm bisher immer im Debuggermodus gestartet. Ich werde es mal kompilieren und dann als Release starten. Mal sehen, ob sich dadurch was ändert...
das ist ja ein ganzer Strauß von guten Hinweisen, danke

Das probiere ich gleich heute Nachmittag aus.
BTW: Ich habe das Programm bisher immer im Debuggermodus gestartet. Ich werde es mal kompilieren und dann als Release starten. Mal sehen, ob sich dadurch was ändert...
Ich mag Pascal...
-
- Beiträge: 6918
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Das habe ich auch gemacht, und bei mir wird es auch richtig dargestellt. Da einzigem der Text rechts oben kommt mit einer ganz anderen Schrift, aber dies liegt daran, das ich es mit Linux kompiliert habe.Seltsam, bei mir startet das Programm gleich in der richtigen Darstellung. Sorry, ich kann dir da konkret nicht helfen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
... da ist der Lump!
Im OnCreate ist noch alles in Ordnung, im OnActivate ist Pitch.TopRow plötzlich 2! (siehe angehängtes Bild)
Bei näherer Recherche habe ich auch den Code identifizieren können, der dafür verantwortlich ist. Ist die Funktion InitializePitch, welche das Spielfeld aufbaut:
Ich schnall nur nicht, warum das passiert? Die Playerfigur wird genau dort gesetzt, wo ich sie hinhaben will. Und warum passiert das nur nach dem Programmstart im ersten Level? Und warum offenbar nur bei mir???
Habt ihr eine Idee?
Im OnCreate ist noch alles in Ordnung, im OnActivate ist Pitch.TopRow plötzlich 2! (siehe angehängtes Bild)
Bei näherer Recherche habe ich auch den Code identifizieren können, der dafür verantwortlich ist. Ist die Funktion InitializePitch, welche das Spielfeld aufbaut:
Code: Alles auswählen
procedure TMainForm.InitializePitch;
var
i, j: integer;
X, Y: integer;
NumberOfMines : Integer;
begin
Writeln;
Writeln('Initialize Pitch procedure...');
Writeln('TopRow before Define Playerposition: '+InttoStr(Pitch.TopRow));
{ Define Playerposition}
Pitch.Col := Pitch.ColCount div 2;
Pitch.Row := Pitch.RowCount - 1; //<= Hier passiert es offenbar!
Writeln('TopRow after Define Playerposition: '+InttoStr(Pitch.TopRow));
{ Reset Settings}
FGameLost := False;
Pitch.Enabled:= True;
MessagePanel.Visible:= False;
OKButton.Visible:= False;
NextLevelButton.Visible:= True;
FMoves.Clear;
FNumberOfCarriedDamsels:= 0;
{ Increase Gamelevel}
Inc(FLevelIndex);
if FLevelIndex > 10 then
WinGame;
LevelLabel.Caption:= IntToStr(FLevelIndex);
{Clear FPitchContent}
for i := 0 to Pitch.ColCount - 1 do
for j := 0 to Pitch.RowCount - 1 do
FPitchContent[i, j] := Empty;
Pitch.Invalidate;
{ Define Targetposition}
for i := ((Pitch.ColCount div 2) - 2) to ((Pitch.ColCount div 2) + 2) do
begin
FPitchContent[i, 0] := Target;
end;
{ Define Damselpositions }
if FLevels[FLevelIndex].HaveDamsels then
begin
Y := Pitch.RowCount div 3;
// Position of first Damsel
X := Pitch.ColCount div 4;
FPitchContent[X, Y] := Damsel;
// Position of second Damsel
X := Pitch.ColCount - (Pitch.ColCount div 4);
FPitchContent[X, Y] := Damsel;
end;
{ Mining}
NumberOfMines := FLevels[FLevelIndex].Mines;
Randomize;
while NumberOfMines > 0 do
begin
X := Random(Pitch.ColCount);
Y := Random(Pitch.RowCount);
{ No Mines in the first and last row!}
if (Y > 0) and (Y < Pitch.RowCount - 1) then
begin
{put down mine, if it is an empty place}
if FPitchContent[X, Y] = Empty then
begin
FPitchContent[X, Y] := Mine;
Dec(NumberOfMines);
end;
end;
end;
Pitch.SetFocus;
end;



Habt ihr eine Idee?
Ich mag Pascal...
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Ich finde es seltsam, dass du das Formular mit seinen Constraints in der Größe festgezurrt hast. Das sollte eigentlich nichts ausmachen, aber da das Grid client-aligned ist, könnte es sein dass die Zeilenhöhe und Gridhöhe nicht ganz zueinanderpassen, so dass du unterste Zeile vielleicht um ein paar Pixel über den Bildschirm ragt. Dies würde bedeuten, dass das Grid, um die unterste Zeile ganz anzeigen zu können, nach unten scrollt (--> TopRow wird >0).
Versuchse es mal anders, das Formular optimal zu füllen. Benutze dafür die Automatik des Anchor-Editors:
- Form.Constraints: alle Werte auf 0 setzen
- Pitch.Align = alNone
- ControlPanel.Align = alNone
AnchorEditor öffnen
- Pitch: links und oben an MainForm verankern (Sibling = MainForm, jeweils den zugehörigen linken Button anklicken
- ControlPanel: links, oben und unten mit Pitch verankern (Sibling = Pitch), rechts keine Verankerung. Den linken Anker an den rechten Rand des Pitch legen (d.g. den mittleren Button unter den linken Sibling klicken); der obere ControlPanel-Anker bezieht sich auf den oberen Pitch-Rand (linker Button), der unter ControlPanel-Anker auf den unteren Pitch-rand (mittlerer Button).
- MainForm.AutoSize = true
- MainForm.BorderStyle bsSingle oder bsDialog, so dass das Formular nicht mehr durch den Benutzer in seiner Größe verändert werden kann
Falls jetzt das Grid zur Laufzeit etwas höher oder niedriger ausfällt als zur Designzeit, sorgt die Verankerung dafür, dass sich alles automatisch anpasst. Bei deiner Lösung geht das nicht, weil die Formulargröße durch die Constraints starr festgelegt ist.
Versuchse es mal anders, das Formular optimal zu füllen. Benutze dafür die Automatik des Anchor-Editors:
- Form.Constraints: alle Werte auf 0 setzen
- Pitch.Align = alNone
- ControlPanel.Align = alNone
AnchorEditor öffnen
- Pitch: links und oben an MainForm verankern (Sibling = MainForm, jeweils den zugehörigen linken Button anklicken
- ControlPanel: links, oben und unten mit Pitch verankern (Sibling = Pitch), rechts keine Verankerung. Den linken Anker an den rechten Rand des Pitch legen (d.g. den mittleren Button unter den linken Sibling klicken); der obere ControlPanel-Anker bezieht sich auf den oberen Pitch-Rand (linker Button), der unter ControlPanel-Anker auf den unteren Pitch-rand (mittlerer Button).
- MainForm.AutoSize = true
- MainForm.BorderStyle bsSingle oder bsDialog, so dass das Formular nicht mehr durch den Benutzer in seiner Größe verändert werden kann
Falls jetzt das Grid zur Laufzeit etwas höher oder niedriger ausfällt als zur Designzeit, sorgt die Verankerung dafür, dass sich alles automatisch anpasst. Bei deiner Lösung geht das nicht, weil die Formulargröße durch die Constraints starr festgelegt ist.
- Dateianhänge
-
minedout-wp.zip
- (6.94 KiB) 46-mal heruntergeladen
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Hi,
ich habe alle Einstellungen so wie vorgeschlagen übernommen. Resultat negativ.
Ich habe das nochmal mit dem von dir angehängten Projekt gegengecheckt. Ich hatte nichts vergessen. Ich habe daraufhin einfach mal dein Projekt gestartet. Wieder zwei leere Reihen im ersten Level.
Kann das an meiner Hardware liegen? Ich habe ein ziemlich simples i3-Notebook mit 15'' und einer Shared-Memory-Grafikeinheit.
Du hast übrigens recht mit meinen seltsamen Anker- und Constraintseinstellungen. Ich habe mich in diese Gruppierungsgeschichten erst vor kurzem so ein bisschen eingearbeitet. Erst habe ich über die Anker daran gearbeitet, dass die Formularelemente bei Größenänderung weiter zueinander passen. Hat so halb und halb geklappt. Dann dachte ich, es wäre vielleicht sicherer das Formular gegen Größenänderungen zu sperren. Das habe ich über die Constraints versucht, weil ich es nicht besser wusste
. Deine Lösung werde ich mir natürlich gut merken.
ich habe alle Einstellungen so wie vorgeschlagen übernommen. Resultat negativ.
Ich habe das nochmal mit dem von dir angehängten Projekt gegengecheckt. Ich hatte nichts vergessen. Ich habe daraufhin einfach mal dein Projekt gestartet. Wieder zwei leere Reihen im ersten Level.
Kann das an meiner Hardware liegen? Ich habe ein ziemlich simples i3-Notebook mit 15'' und einer Shared-Memory-Grafikeinheit.
Du hast übrigens recht mit meinen seltsamen Anker- und Constraintseinstellungen. Ich habe mich in diese Gruppierungsgeschichten erst vor kurzem so ein bisschen eingearbeitet. Erst habe ich über die Anker daran gearbeitet, dass die Formularelemente bei Größenänderung weiter zueinander passen. Hat so halb und halb geklappt. Dann dachte ich, es wäre vielleicht sicherer das Formular gegen Größenänderungen zu sperren. Das habe ich über die Constraints versucht, weil ich es nicht besser wusste

Ich mag Pascal...
-
- Beiträge: 6918
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Was hast du für ein Lazarus, eine Trunk ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
... siehe Anhang...
- Dateianhänge
-
- Lazarusversíon.PNG (10.6 KiB) 1982 mal betrachtet
Ich mag Pascal...
Re: DrawGrid wird beim Programmstart nicht richtig dargestel
Keine Ahnung, was da los ist. Als Workaround: was passiert, wenn du nach "Pitch.Row := Pitch.RowCount - 1" einfach "Pitch.TopRow := 0" erzwingst?
PS. Irgendwie muss es mit der Gridhöhe und Zeilenhöhe zu tun haben... Mache testhalber mal das Grid einfach ein Stück höher, so dass unterhalb des Spielfelds etwas weißer Grid-Hintergrund zu sehen ist.
PS. Irgendwie muss es mit der Gridhöhe und Zeilenhöhe zu tun haben... Mache testhalber mal das Grid einfach ein Stück höher, so dass unterhalb des Spielfelds etwas weißer Grid-Hintergrund zu sehen ist.
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: DrawGrid wird beim Programmstart nicht richtig dargestel











Das hier funktioniert:
Code: Alles auswählen
Pitch.Col := Pitch.ColCount div 2;
Pitch.Row := Pitch.RowCount - 1;
Pitch.TopRow:= 0; // <= Das ist der Gewinner!

... ich bin so glücklich!
Ich mag Pascal...
Re: [gelöst]DrawGrid wird beim Programmstart nicht richtig..
Freut mich. Aber trotzdem würde ich gerne verstehen, warum bei dir das Grid um zwei Zeilen nach unten scrollt, wenn du die aktive Zelle in the unterste Zeile setzt. Welches Windows hast du eigentlich? Ist es im "Classic Style" (a la Windows 95) oder mit Themes? Was passiert, wenn du, wie oben schon gefragt, das Grid einige Zeilen höher machst als eigentlich nötig? Wenn hier der Effekt weg ist, um wieviel muss das Grid höher sein, bis der Effekt wieder kommt?
-
- Beiträge: 6918
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: [gelöst]DrawGrid wird beim Programmstart nicht richtig..
Wen man seinen ersten Post anguckt, muss es Win10 sein.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: [gelöst]DrawGrid wird beim Programmstart nicht richtig..
Ich kann das Problem inzwischen nachstellen: Wenn ich unter Windows die Bildschirmauflösung auf 125% oder 150% hochsetze, tritt das beschriebene Problem auf. Wenn ich dann das Grid um etwa zwei Zeilen höher mache als nötig, ist das Problem wieder weg, nur hat man dann unter den Spielfeld zwei leere Zeilen. Scheint mir ein Bug zu sein.
-
- Beiträge: 294
- Registriert: So 4. Mai 2014, 21:32
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
- CPU-Target: 64bit
- Wohnort: Oranienburg
Re: [gelöst]DrawGrid wird beim Programmstart nicht richtig..
Da wäre ich im Leben nicht drauf gekommen. Ich hatte jetzt nochmal wie vorgeschlagen mit den Größen der Form und des Pitches rumgespielt, war aber noch auf keine Lösung gekommen.
Ich mag Pascal...