Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 08:14 
Hallo!

In meinem Programm gibt es mehrere Images, alle dynamisch erzeugt, alle gleich gross, nebeneinander in einer Reihe auf einer ScrollBox.
Ich möchte sie nun per Maus umreihen, d.h., ziehen und an anderer Stelle ablegen (das klappt). Die anderen Images sollen dabei sozusagen "versetzt" werden. Beispiel: A B C D E -> ich möchte D umreihen -> A D B C E.
Es funktioniert, solange ich von rechts nach links reihe:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
  for i := Cnt downto TImage(FindComponent(Img)).Tag+1 do
  begin
   TImage(FindComponent('Image'+IntToStr(i))).Picture :=
     TImage(FindComponent('Image'+IntToStr(i-1))).Picture;
  end;

Wie reihe ich von links nach rechts um, also zB. A B C D E -> ich möchte B umreihen -> A C D B E.
So geht's nicht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
  for i := TImage(FindComponent(Img)).Tag+1 to Cnt do
  begin
   TImage(FindComponent('Image'+IntToStr(i+1))).Picture :=
     TImage(FindComponent('Image'+IntToStr(i))).Picture;
  end;

Ist sicher einfach, aber ich komm' nicht drauf...

//Edit: von rechts nach links funktioniert auch nicht, wenn ich nicht das letzte, ganz rechte Image ziehe.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 10:35 
Ok, rechts nach links klappt jetzt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
   n := Cnt;
   for i := 0 to Cnt do
   begin
    //FindComponent('Image'+IntToStr(ImageNr))) ist das zu versetzende Image
    if i = TImage(FindComponent('Image'+IntToStr(ImageNr))).Tag then break;
    Dec(n);
   end;

    for i := Cnt-n downto TImage(FindComponent(Img)).Tag+1 do
    begin
     TImage(FindComponent('Image'+IntToStr(i))).Picture :=
       TImage(FindComponent('Image'+IntToStr(i-1))).Picture;
    end;

Links nach rechts habe ich dzt. so, ist aber sehr buggy und definitif nicht korrekt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
//FindComponent('Image'+IntToStr(ImageNr))) ist das zu versetzende Image
    for i := 1 to Cnt-TImage(FindComponent('Image'+IntToStr(ImageNr))).Tag do
    begin
     TImage(FindComponent('Image'+IntToStr(i-1))).Picture :=
       TImage(FindComponent('Image'+IntToStr(i))).Picture;
    end;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 26.10.07 10:45 
Ich blick bei deinem Code nicht komplett durch, aber wenn man Dinge vertauscht, muss man irgendwo eine Zeile haben, die ein Objekt in einer temporären Variable speichert. Diese sehe ich bei dir nicht - mich wundert ehrlich gesagt, dass eine Richtung bei dir funktioniert...:gruebel:

Probier mal, das erste Bild, was du überschreibst, in einem Picture-Objekt zwischenzuspeichern und füge das dann am Ende wieder da ein, wo es hin soll. In etwa also so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
swap := myarray[start]
for i := start to ende-1 do
  myarray[i] := myarray[i+1]
myarray[ende] := swap;

_________________
We are, we were and will not be.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 10:58 
user profile iconGausi hat folgendes geschrieben:
Probier mal, das erste Bild, was du überschreibst, in einem Picture-Objekt zwischenzuspeichern

Das zu versetzende Bild ist in dem beim Ziehen mit der Maus angezeigten Image zwischengespeichert. Mein Code oben ist nicht komplett - es fehlt das Ersetzen:
ausblenden Delphi-Quelltext
1:
2:
3:
//LoadImage wird zum Öffnen per OpenPictureDialog und zum Umreihen als Zwischenspeicher benötigt
//TImage(FindComponent(Img)) ist das Ziel-Image
 TImage(FindComponent(Img)).Picture := LoadImage.Picture;

Ich kriege es einfach nicht hin, von links nach rechts zu ersetzen!
Im Prinzip so (jedes Image hat einen eindeutigen Tag-Wert, Image0.Tag := 0, Image1.Tag := 1 usw.):
1. Nimm das Quell-Image mit .Tag 0
2. Ziehe es nach rechts auf das Image mit .Tag 3
3. Lasse die Maustaste los
4. Alle Bilder von .Tag 0 bis .Tag 2 müssen nun aktualisiert werden ...
... und ab hier blicke ich nicht mehr durch!
Bild .Tag 3 wird durch das gezogene ersetzt, und alle Bilder rechts davon bleiben von der Änderung unberührt.

Obwohl mir das Prinzip klar ist, kann ich es einfach nicht!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 26.10.07 11:01 
Moin!

Dein Code ist etwas merkwürdig, ehrlich gesagt steige ich da nicht ganz durch.

Deshalb mal ein anderer Ansatz: :idea:
  • Füge die Bilder selbst in eine TImageListein.
  • Verwende die .Tag-Eigenschaft der Images, um den Index des Bildes in der TImageListzu speichern.
  • Schreib dir eine Prozedur, die die Images durchläuft und das Bild mit dem Index aus der .Tag-Eigenschaft aus der TImageListabruft.
  • Wenn du die Bilder umsortieren willst, dann änderst du nur die .Tag-Eigenschaften in den Image-Kompos und rufst abschließend einmal die Update-Prozedur auf, damit die Bilder wieder korrekt zugewiesen werden.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 26.10.07 11:02 
Vielleicht liegt der Fehler auch bei dem Image - ich hab damit auch öfter mal Probleme und blicke nicht wirklich durch, was da intern passiert. Folgende Sachen könntest du mal ausprobieren: Satt = mit Assign arbeiten, vor der eigentlichen Zuweisung des neuen Bildes ein Assign(Nil) einfügen und/oder ein paar Refreshs, Repaints oder Updates dazwischenpacken.

Aber generell würde ich da auch eher das Konzept ausbessern - besonders das ständige Findcomponent ist eher unschön.

_________________
We are, we were and will not be.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 11:08 
user profile iconNarses hat folgendes geschrieben:
:idea:
  • Füge die Bilder selbst in eine TImageListein.


Habe ich schon überlegt, aber wieder verworfen, weil ich dasselbe mit dem Pfad und dem Dateinamen machen muss (jedem Image ist ein TLabel zugeordnet, jedes Image und jedes Label haben identische Hint's, nämlich den Dateinamen), mir also eine ImageList nur für die Bilder nützlich wäre. Haut es aber erst mal mit den Bildern hin, klappt es auch mit den Strings, ich muss da im Prinzip nur TImage durch TLabel und .Picture durch .Caption ersetzen usw., dazu eine temporäre String-Variable zum Zwischenspeichern und - that's it!

Muss doch gehen!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 11:15 
user profile iconGausi hat folgendes geschrieben:
Vielleicht liegt der Fehler auch bei dem Image - ich hab damit auch öfter mal Probleme und blicke nicht wirklich durch, was da intern passiert. Folgende Sachen könntest du mal ausprobieren: Satt = mit Assign arbeiten, vor der eigentlichen Zuweisung des neuen Bildes ein Assign(Nil) einfügen und/oder ein paar Refreshs, Repaints oder Updates dazwischenpacken.

Ich meine, es liegt rein am Code. Wenn der korrekt ist, wird es auch gehen.

user profile iconGausi hat folgendes geschrieben:
Aber generell würde ich da auch eher das Konzept ausbessern - besonders das ständige Findcomponent ist eher unschön.

Was gibt es Besseres? Ich habe zB 100 Images, Image0 - Image99 und kann jedes mit FindComponent ansprechen. Irgendwie muss ich ja darauf zugreifen können.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 26.10.07 13:18 
Moin!

user profile icongalagher hat folgendes geschrieben:
Was gibt es Besseres?
Wenn du doch die Kompos sowieso dynamisch erzeugst, dann würde ich mir entsprechende, arbeitserleichterne bauen. Z.B. so: ;)
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:
type
   TLabledImage = class(TImage)
   private
     FLabel: TLabel;
     FImageList: TImageList;
     FCaptions: TStringList;
     FRefIndex: Integer;
    procedure SetRefIndex(const Value: Integer);
   public
     constructor Create(AOwner: TComponent; AImageList: TImageList; ACaptions: TStringList);
     property RefIndex: Integer read FRefIndex write SetRefIndex;
     property TheLabel: TLabel read FLabel;
   end;

implementation

constructor TLabledImage.Create(AOwner: TComponent; AImageList: TImageList; ACaptions: TStringList);
begin
  inherited Create(AOwner);
  Parent := TWinControl(AOwner);
  FLabel := TLabel.Create(AOwner);
  FLabel.Parent := TWinControl(AOwner);
  FImageList := AImageList;
  FRefIndex := -1; // unzugeordnet
  FCaptions := ACaptions;
end;

procedure TLabledImage.SetRefIndex(const Value: Integer);
begin
  FRefIndex := Value;
  if (FRefIndex >= 0) and (FRefIndex < FImageList.Count) then // Index gültig?
    FImageList.GetBitmap(FRefIndex,Picture.Bitmap) // dann von da holen
  else // sonst
    Picture.Bitmap := NIL; // Inhalt leeren
  if (FRefIndex >= 0) and (FRefIndex < FCaptions.Count) then // Index gültig?
    FLabel.Caption := FCaptions.Strings[FRefIndex]
  else
    FLabel.Caption := '';
end;
Zentraler Ansatz: du packst alle Bilder in eine TImageListund alle Captions in eine TStringList(klar, Indices müssen zusammen passen!). Dann erzeugst du dir von der obigen Kompo entsprechend viele und speicherst eine Referenz darauf in einem Array (klar, die Größe/Position des Image/Labels noch anpassen). Jetzt kannst du durch Schreiben auf die Eigenschaft .RefIndexder Kompo ganz einfach das Bild und den zugehörigen Text aus den Listen abrufen. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 26.10.07 18:43 
Hab's jetzt hinbekommen!

user profile iconNarses hat folgendes geschrieben:
Wenn du doch die Kompos sowieso dynamisch erzeugst, dann würde ich mir entsprechende, arbeitserleichterne bauen.

Ich bin froh, dass es so funktioniert! Ich müsste sonst das ganze Programm umbauen, es ist praktisch fertig.

Danke!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2562
Erhaltene Danke: 46

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: So 28.10.07 16:46 
Hallo!
Also, jetzt liess mir das doch keine Ruhe und ich wollte mir so eine Komponente basteln:
user profile iconNarses hat folgendes geschrieben:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
   TLabledImage = class(TImage)
   private
     FLabel: TLabel;
     FImageList: TImageList;
     FCaptions: TStringList;
     FRefIndex: Integer;
    procedure SetRefIndex(const Value: Integer);
   public
     constructor Create(AOwner: TComponent; AImageList: TImageList; ACaptions: TStringList);
     property RefIndex: Integer read FRefIndex write SetRefIndex;
     property TheLabel: TLabel read FLabel;
   end;

Klappte auch (mit einigen Änderungen), lässt sich installieren und läuft dann auch, aber das Label wird einfach irgendwo auf dem Formular erstellt und "gehört" nicht dem LabledImage. Ich dachte, wenn ich im Create die Position angebe, sollte es gehen, aber ist nicht so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
constructor TLabledImage.Create(AOwner: TComponent; AImageList: TImageList; ACaptions: TStringList);
begin
  inherited Create(AOwner);
  Parent := TWinControl(AOwner);
  FLabel := TLabel.Create(AOwner);
  FLabel.Parent := TWinControl(AOwner);  //-> AOwner ist doch das TLabledImage, oder?
  Flabel.Top  := Top+Height+10;  //Top, Height und Left beziehen sich doch auf TLabledImage, oder?
  Flabel.Left := 0;  //Mit 0 meine ich nicht 0 auf der Form, sondern den linken Rand vom LabledImage!
end;

Das geht so nicht! Ich habe dann eine TLabledImage-Kompo auf dem Formular und ein unbenanntes Label, das aber nicht mit dem LabledImage "verbunden" ist, sondern separat auf der Form rumliegt. Ich meine das so, wie es bei LabeledEdit ist - da ist das Label "Teil" der Komponente.

Da tritt auch gleich das nächste Problem auf: Wenn ich es also hinbekomme, dass das Label zu TLabledImage gehört, wie erreiche ich, dass es bei Grössenänderung des TLabledImage's relativ zum TLabledImage seine Position behält, also immer 10 Pixel unterhalb (Top+Height+10) und immer am linken Rand vom TLabledImage?

//Edit: Da das nicht hierher gehört - hier geht's weiter:www.delphi-forum.de/...erstellen_77742.html

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!