Autor Beitrag
Gerhard_S
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Sa 27.07.13 23:33 
Aus lauter Faulheit habe ich mir gedacht, ich könnte den folgenden Code
ausblenden 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: 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 :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 28.07.13 09:09 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Gerhard_S Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: So 28.07.13 11:01 
Ich glaube, ich muss den vollständigen Code zeigen:
ausblenden volle Höhe 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:
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 user profile iconMartok: Code- durch Delphi-Tags ersetzt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19313
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: 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 8). 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



BeitragVerfasst: So 28.07.13 23:11 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Gerhard_S Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: So 28.07.13 23:29 
Canvas.textout, onpaint, StringVariable
Diese 3 Begriffe sollten reichen ;)

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Hobby-Programmierer
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 238
Erhaltene Danke: 4

Win XP Pro, Vista Ultimate Trial :o)
D6 Pro, D7 Pro, Turbo, XE SE
BeitragVerfasst: Mo 29.07.13 01:01 
Vielleicht könntest du stattdessen auf ein TPanel o.ä. ausweichen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19313
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 174
Erhaltene Danke: 43



BeitragVerfasst: 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:
ausblenden volle Höhe 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:
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
  // linker Rand des ersten sichtbaren Shape
  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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Mo 29.07.13 22:49 
user profile iconHobby-Programmierer hat folgendes geschrieben Zum zitierten Posting springen:
Vielleicht könntest du stattdessen auf ein TPanel o.ä. ausweichen.

Gute Idee, damit erspare ich mir die Huddelei mit den Labels.
Gerhard_S Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Mo 29.07.13 22:54 
user profile iconBlup hat folgendes geschrieben Zum zitierten Posting springen:
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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Mo 29.07.13 22:58 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19313
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 30.07.13 05:55 
user profile iconGerhard_S hat folgendes geschrieben Zum zitierten Posting springen:
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.