Autor |
Beitrag |
Gerhard_S
      
Beiträge: 98
|
Verfasst: Sa 27.07.13 23:33
Aus lauter Faulheit habe ich mir gedacht, ich könnte den folgenden Code
Quelltext 1: 2: 3: 4: 5: 6:
| Shape3.Left := Shape2.Left+Shape2.Width; Shape4.Left := Shape3.Left+Shape3.Width; Shape5.Left := Shape4.Left+Shape4.Width; Shape6.Left := Shape5.Left+Shape5.Width; Shape7.Left := Shape6.Left+Shape6.Width; Shape8.Left := Shape7.Left+Shape7.Width; |
abkürzen durch:
Quelltext 1: 2: 3: 4:
| for j := 3 to 8 do begin TShape(Components[j]).Left := TShape(Components[j-1]).Left + TShape(Components[j-1]).Width; end; |
Leider unterscheiden sich die Ergebnisse stark voneinander; genauer: die kurze Schreibweise liefert Mist.
Kann mir das jemand erklären?
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Sa 27.07.13 23:49
Lass dir mal
Components[j].Name ausgeben.. Denn components[3] ist nicht automatisch shape 3..
Schau dir mal die Funktion getcomponent an  soviel ich weiß muss der Komponenten Name übergeben werden und du bekommst die Komponente zurück.. Diese dann in ein shape casten und anpassen..
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 28.07.13 09:09
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: So 28.07.13 11:01
Ich glaube, ich muss den vollständigen Code zeigen:
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: 28: 29: 30: 31: 32:
| for i := 0 to ComponentCount - 1 do begin if Components[i] is TShape then begin if (TShape(Components[i]).Brush.Color = clHighlight) and (TShape(Components[i]).Visible = true) then begin if TShape(Components[i]).Name = 'Shape1' then begin if MessageDlg('Wollen Sie das wirklich?', mtConfirmation, [mbYes, mbNo], 0, mbYes) = mrYes then begin Shape1.Visible := false; Label2.Visible := false; Shape2.Left := Shape1.Left; for j := 3 to 8 do begin if Components[j] is TShape then TShape(Components[j]).Left := TShape(Components[j-1]).Left + TShape(Components[j-1]).Width; end; Label3.BoundsRect := Shape2.BoundsRect; Label4.BoundsRect := Shape3.BoundsRect; Label5.BoundsRect := Shape4.BoundsRect; Label6.BoundsRect := Shape5.BoundsRect; Label7.BoundsRect := Shape6.BoundsRect; Label8.BoundsRect := Shape7.BoundsRect; Label9.BoundsRect := Shape8.BoundsRect; end else Exit; end; end; end; end; |
Die Aufgabe ist einfach: Hat der Benutzer Shape1 ausgewählt (woraufhin dieser seine Farbe nach clHighlight ändert), rücken alle anderen Shapes incl. ihrer Labels um eine Shape-Breite nach links.
Bei obigem Code wird Shape1 unsichtbar gemacht, die Anweisung Shape2.Left := Shape1.Left wird aber ebensowenig ausgeführt wie die Anweisung in der for-j-Schleife.
Das verstehe ich nicht.
Moderiert von Martok: Code- durch Delphi-Tags ersetzt
|
|
jaenicke
      
Beiträge: 19313
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 28.07.13 11:07
Und die for-Schleife muss über alle Components laufen usw.
Aber das ist ja auch nicht das gewünschte Ergebnis, denn die Durchnummerierung richtet sich nach der Erstellung, nicht nach dem Namen. j-1 ist also kaum das gewünschte andere Shape.
In diesem Fall ist das Problem, dass du direkt auf den Komponenten als Datenspeicher arbeitest statt diese nur zur Anzeige zu nutzen. Dadurch wird der Quelltext umständlich, riesig und langsam. Viel sinnvoller wäre, im Hintergrund dir zu merken was in der Anzeige ist und dann das anzuzeigen. So richtig kann ich mir nicht vorstellen wie das aussehen soll und was du damit im Programm erreichen möchtest, sonst könnte ich auch mehr sagen.
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: So 28.07.13 19:59
Sinn der Übung ist folgende:
Die Shapes repräsentieren die nebeneinander liegenden Items eines Menüs. Der Benutzer soll Items löschen, verschieben, hinzufügen können (so wie die "Kacheln" in Win  . Da Shapes kein OnClick-Ereignis haben, behelfe ich mir mit einem Trick: auf jedem Shape sitzt ein Label gleicher Größe (z.B. Label3.BoundsRect := Shape2.BoundsRect;), das über ein OnClick-Ereignis verfügt.
Im angeführten Code geht's um die Folgen des "Löschens" (=unsichtbar machen) einer linksaußen sitzenden "Kachel": wird sie unsichtbar gemacht, sollen alle rechts von ihr stehenden "Kacheln" eine Shape-Breite nach links rücken.
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 28.07.13 23:11
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: So 28.07.13 23:19
Frühlingsrolle schrieb: "Dem Shape kann man in so einer Situation das OnClick Ereignis vererben".
Das ist leider nur die halbe Miete. Das Shape braucht auch noch eine Beschriftung.
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: So 28.07.13 23:29
Canvas.textout, onpaint, StringVariable
Diese 3 Begriffe sollten reichen 
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Hobby-Programmierer
      
Beiträge: 238
Erhaltene Danke: 4
Win XP Pro, Vista Ultimate Trial :o)
D6 Pro, D7 Pro, Turbo, XE SE
|
Verfasst: Mo 29.07.13 01:01
Vielleicht könntest du stattdessen auf ein TPanel o.ä. ausweichen.
|
|
jaenicke
      
Beiträge: 19313
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 29.07.13 06:30
Viel sinnvoller ist wirklich wie ich eingangs schrieb die Daten von der Darstellung zu trennen...
Du hast also fünf Einträge, die du anzeigen willst? Nun, dann zeige sie auf den ersten fünf an und blende die anderen aus. Dann brauchst du nicht den ersten Eintrag ausblenden und mühsam die Positionen zu verändern.
|
|
Blup
      
Beiträge: 174
Erhaltene Danke: 43
|
Verfasst: Mo 29.07.13 15:50
Man kann sich das Leben leichter machen, wenn man den Zugriff auf die Komponenten kapselt.
Der Code wird übersichtlicher und man kann sich auf die eigentliche Aufgabe konzentrieren:
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: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| function TForm1.GetColShape(ACol: Integer): TShape; begin Result := FindComponent('Shape' + IntToStr(ACol)) as TShape; end;
function TForm1.GetColLabel(ACol: Integer): TLabel; begin Result := FindComponent('Label' + IntToStr(ACol + 1)) as TLabel; end;
procedure TForm1.ShapeUpdate; var i, iLeft: Integer; Sh: TShape; Lb: TLabel; begin iLeft := 0; for i := 1 to 6 do begin Sh := GetColShape(i); Lb := GetColLabel(i); Sh.Visible := Lb.Visible; if Sh.Visible then begin Sh.Left := iLeft; Lb.Left := iLeft; Inc(iLeft, Sh.Width); end; end; end;
procedure TForm1.LabelClick(Sender: TObject); begin if Sender is TLabel then begin if MessageDlg('Wollen Sie das wirklich?', mtConfirmation, [mbYes, mbNo], 0, mbYes) = mrYes then begin TLabel(Sender).Visible := False; ShapeUpdate; end; end; end; |
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: Mo 29.07.13 22:49
Hobby-Programmierer hat folgendes geschrieben : | Vielleicht könntest du stattdessen auf ein TPanel o.ä. ausweichen. |
Gute Idee, damit erspare ich mir die Huddelei mit den Labels.
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: Mo 29.07.13 22:54
Blup hat folgendes geschrieben : | Man kann sich das Leben leichter machen, wenn man den Zugriff auf die Komponenten kapselt.
|
Vollkommen einverstanden. Leider gibt Zeile 23 (Sh.Visible := Lb.Visible;) eine AV, wenn i = 6 ist (6 ist die Anzahl der Shapes); nach Klick auf OK sieht es so aus, als ob nur die Labels gewandert sind, denn das letzte Shape rechts außen hat kein Label mehr.
Wenn i maximal Shapeanzahl -1 erreichen darf, gibt es keine AV; das letzte - ohnehin überflüssige - Shape rechts außen hat weiterhin kein Label mehr.
Auch das lässt sich lösen:
direkt hinter die for-Schleife (hinter Zeile 30, vor Zeile 31) schreiben wir:
Quelltext 1: 2: 3:
| Sh := GetColShape(i); Lb := GetColLabel(i); if Sh.Visible then Sh.Visible := false; |
Danke an alle fürs Kümmern.
Zuletzt bearbeitet von Gerhard_S am Di 30.07.13 00:38, insgesamt 3-mal bearbeitet
|
|
Gerhard_S 
      
Beiträge: 98
|
Verfasst: Mo 29.07.13 22:58
jaenicke hat folgendes geschrieben : | Viel sinnvoller ist wirklich wie ich eingangs schrieb die Daten von der Darstellung zu trennen...
Du hast also fünf Einträge, die du anzeigen willst? Nun, dann zeige sie auf den ersten fünf an und blende die anderen aus. Dann brauchst du nicht den ersten Eintrag ausblenden und mühsam die Positionen zu verändern. |
Es soll aber so aussehen, wie die Schlange vorm Freibad: hat der erste in der Schlange das Freibad betreten, rücken alle anderen einen Schritt nach vorn - um mal einen jahreszeitlich angepassten Vergleich zu bringen.
|
|
jaenicke
      
Beiträge: 19313
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.07.13 05:55
Gerhard_S hat folgendes geschrieben : | Es soll aber so aussehen, wie die Schlange vorm Freibad: hat der erste in der Schlange das Freibad betreten, rücken alle anderen einen Schritt nach vorn - um mal einen jahreszeitlich angepassten Vergleich zu bringen. |
Eben, aber dafür brauchst du ja nicht die Komponenten verschieben, sondern es reicht das zu ändern, was sie anzeigen.
Bei Kacheln erinnere ich mich an ein Beispiel-Programm von mir, das damit durchaus Ähnlichkeit hat:
www.delphi-forum.de/viewtopic.php?p=557541
Ich glaube eine Umsetzung in der Richtung würde besser aussehen und ließe sich auch einfacher umsetzen als visuelle Komponenten, die auf dem Formular umherwandern. Das wäre bei dir auch viel einfacher, da du gar nicht verschiedene Raster hast wie bei mir.
|
|