AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Idee für Auswahlfunktion

Ein Thema von DelphiUser1 · begonnen am 9. Okt 2012 · letzter Beitrag vom 28. Okt 2012
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.594 Beiträge
 
Delphi 11 Alexandria
 
#11

AW: Idee für Auswahlfunktion

  Alt 11. Okt 2012, 10:44
Also ich finde VirtualStringTree/VirtualDrawTree auch die beste Wahl. Kann man auch schön mit einer Live-Suche (Beim Tippen schon Ergebnisse einblenden) kombinieren und unter dem Edit einblenden. Noch mehr vorgefertigt ist, denke ich, zu unflexibel. Es sein denn, man kann es nicht.
Sven Harazim
--
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.883 Beiträge
 
Delphi 12 Athens
 
#12

AW: Idee für Auswahlfunktion

  Alt 11. Okt 2012, 13:22
Irgendwer hier im Forum hat mal eine SVG Komponente gemacht. Die würde ich erweitern!

Wegen TWebbrowser:
Das Design lässt sich ja relativ einfach von Webseiten klauen und in eine Art Template umwandeln.
bzw. man benutzt ein Template von http://www.opendesigns.org/
und passt das an.
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (11. Okt 2012 um 13:25 Uhr)
  Mit Zitat antworten Zitat
DelphiUser1

Registriert seit: 15. Sep 2012
56 Beiträge
 
#13

AW: Idee für Auswahlfunktion

  Alt 13. Okt 2012, 14:32
@Popov: Ehrlich gesagt habe ich mir das genauso vorgestellt
Ich schätze mal, ich war mir der Vielfältigkeit von Combobox und Listbox nur nicht so bewusst.
Trotzdem habe ich absolut keine Ahnung wie man so etwas mit diesen Komponenten erstellen soll
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#14

AW: Idee für Auswahlfunktion

  Alt 13. Okt 2012, 19:37
An für sich ist das nicht kompliziert, eher nur malen nach Zahlen, d. h. du hast deine Canvas auf der du zeichnest. Das ist fast genauso wie zeichnen auf dem Canvas des Formulars, einer Bitmap oder Image. Allerdings müssen hier vor allem drei Punkte beachtet werden.

Der erste ist, dass du schon auf der richtigen Canvas zeichnen mußt. Als Parameter bekommst du nur Control: TWinControl und nicht TListBox . Du mußt Control also sagen, dass es eine TListbox ist. Das machst du mit with (Control as TListbox) do
Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
  with (Control as TListbox) do
  begin
    ...
  end;
end;
Ob du nun mit With arbeitest (mußt du nicht, du kannst aber) oder anders, z. B. so

Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  MyListBox: TListBox;
begin
  MyListBox := (Control as TListbox);
  MyListBox.Canvas. ...
ist eigentlich egal. Beides geht.

Der zweite wichtige Punkt ist, dass du eigentlich auf der ganzen ListBox Canvas zeichnen kannst, aber das willst du ja nicht. Du willst nur auf dem kleinem Streifen des Items zeichnen. Dazu bekommst du den Parameter Rect: TRect . Jedes Item hat seinen eigenen Rect Bereich. Du mußt beim Zeichnen also in dem Bereich bleiben.

Die Prozedur OnDrawItem funktioniert so: sie wird so oft aufgerufen wie viele Items sichtbar sind. Sind fünf Items sichtbar, wird die Prozedur auch fünf mal aufgerufen. Nur bekommst du jedes Mal passend zu dem Item andere Rect Werte. Willst du also an Koordinate 1 und 1 einen Punkt setzten, dann nicht MyListBox.Canvas.Pixels[1, 1] := clBlack , sondern MyListBox.Canvas.Pixels[Rect.Left + 1, Rect.Top + 1] := clBlack . Du mußt also immer im Verhältnis zu Rect zeichnen. Läßt du es weg, zeichnest du alles oben in der ListBox.

Nur bedenke, man kann auch drüberzeichen in das darunterliegende Item. Die Begrenzung nach unten ist Rect.Bottom , nach rechts Rect.Right . Also immer schön im im Bereich bleiben und es immer wieder überprüfen. Außerdem sollte man bedenken, dass es auch eine Funktion Rect gibt. Die Namenswahl des Parameters ist nicht sonderlich glücklich, aber auch keine Katastrophe. Man muß eben aufpassen. Wenn eine Fehlermeldung kommt, dann sollte men es nur wissen um was es geht.

Der dritte wichtige Punkt ist, dass man die State: TOwnerDrawState Parameter betrachten sollte. Denn die sagen einem was für ein Item das aktuelle Item ist. Ist es ein normales Item oder eine der den Fokus besitz oder ist er gerade selektiert.

Delphi-Quellcode:
  with (Control as TListbox) do
  begin
    if odSelected in State then
      Canvas.Font.Color := clInactiveCaptionText
    else
      Canvas.Font.Color := clWindowText;
Das Beispiel fragt ab ob der Item gerade selektiert ist. In diesem Fall ändert sich die Schriftfarbe. Die Hintergrundfarbe ist schon automatisch in Brush.Color eingestellt. Eigentlich mußt du die Textfarbe und Hintergrundfarbe nicht einstellen, da sie schon voreingestellt sind. Das ist nur dann wichtig wenn du deine eigenen Farben wählen willst. Ansonsten bekommst du die Systemfarben voreingestellt.

Wenn man sein eigenes Design wählen will, dann muß man die Hintergrundfarbe ändern, die Schriftfarbe, dann den Focus löschen und durch seinen eigenen ersetzte. Aber das erkläre ich evt. später, sonst verwirrt das alles nur.

Zuletzt noch der Hinweis, dass Index: Integer den Index beinhaltet der bei dem Durchlauf gerade gezeichnet wird.
  Mit Zitat antworten Zitat
DelphiUser1

Registriert seit: 15. Sep 2012
56 Beiträge
 
#15

AW: Idee für Auswahlfunktion

  Alt 14. Okt 2012, 00:14
Okay danke an Popov schon mal dafür und ich hab mich da auch gleich mal an die Arbeit gemacht. Bin allerdings nicht soo weit gekommen. Vielleicht wäre es hilfreich erst einmal den ganzen Quelltext zu posten und dann zu den einzelnen Schritten etwas zu sagen, weil ich mich leider noch nicht so gut mit Delphi auskenne.
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#16

AW: Idee für Auswahlfunktion

  Alt 15. Okt 2012, 17:29
So, sorry, habe dich übersehen. Hier nun der Sorcecode für das Beispiel vorne. Ich hab den Part mit den Daten heute noch etwas vereinfacht, da ich die Daten vorher in einem Record als Object am Item hatte, was die Sache zwar stark vereinfacht, aber für dich als Anfänger evtl. eine zusätzliche Hürde darstellt. Also habe ich ein anderes Konzept gewählt und alle Daten in einem String zusammengefasst. Das aber nur so nebenbei.
Angehängte Dateien
Dateityp: zip ListBoxWieFB_Src.zip (21,8 KB, 13x aufgerufen)
Dateityp: zip ListBoxWieFB_Exe.zip (213,2 KB, 21x aufgerufen)
  Mit Zitat antworten Zitat
DelphiUser1

Registriert seit: 15. Sep 2012
56 Beiträge
 
#17

AW: Idee für Auswahlfunktion

  Alt 16. Okt 2012, 22:17
Okay alles klar, danke dafür.
Ich habe es mir mal angeschaut und verstehe es auch weitestgehend, aber mir ist gerade schleierhaft wie ich jetzt die Daten einbinden kann
Also es wird eben abgefragt
Delphi-Quellcode:
if FileExists(path+Edit1.text+'.txt')then
begin
 Listbox1.Items.Add()
Path extrahiert einfach den Filepath (wird im FormCreate deklariert) und was ich mich jetzt frage ist wie ich die daten erfassen kann? Diese werden bislang in "Info(Username).txt" abgespeichert und ich habe diese bisher einfach mit einer Stringlist erfasst und dann ausgegeben. Aber in diesem Fall ist das ganze ein wenig schwieriger wenn ich mich nicht irre. Und kann ich das Bild auch einfach in die Imagelist laden. (Bild = Username.jpg)
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#18

AW: Idee für Auswahlfunktion

  Alt 16. Okt 2012, 23:08
Wie du die mit deinen Daten umgehen kannst und welche du hast, das weißt doch du, nicht ich.

Ich hab dir das Beispiel umgeschrieben. Im Item selbst werden hier keine Daten mehr gespeichert. Stattdessen werden die Daten in einem Objekt an den Item gebunden. Die Daten können bei Bedarf gelesen werden, das Item selbst enthält nur noch einen leeren String.

Bei dieser Methode kannst du deine Informationen viel besser verwalten. Du übergibst sie irgendwo an Info und dann greifst du sie bei Bedarf ab. Die Klasse Info vorher an deine Bedürfnissse anpassen. Sie ist simpel gehalten.

Delphi-Quellcode:
type
  TInfo = class
    Name: String;
    Ort: String;
    Freunde: Integer;
    ImageIndex: Integer;
  end;

  {Gibt den X-ten Teilstring eines mit Kommas getrennten Daten-Strings}
function ExtractSubStr(Str: String; Index: Integer): String;
var
  i: Integer;
begin
  Result := '';
  if Index < 1 then Exit;
  Str := Str + ',';
  for i := 1 to Index - 1 do Delete(Str, 1, Pos(',', Str));
  Result := Trim(Copy(Str, 1, Pos(',', Str) - 1));
end;

procedure TForm1.FormCreate(Sender: TObject);

  procedure SetInfo(s: String; var Info: TInfo);
  begin
    Info := TInfo.Create;
    Info.Name := ExtractSubStr(s, 1);
    Info.Ort := ExtractSubStr(s, 2);
    Info.Freunde := StrToIntDef(ExtractSubStr(s, 3), -1);
    Info.ImageIndex := StrToIntDef(ExtractSubStr(s, 4), -1);
  end;

var
  Info: TInfo;
begin
  ListBox1.Style := lbOwnerDrawFixed;

  {Beispieldaten. Letzter Wert Index ist für Bilder in ImageList}
  {SetInfo nur für Übergabe der Beispieldateien. Daten können auch anders an
   Info übergeben werden}

  SetInfo('Anna, Köln, 1, 0', Info);
  ListBox1.Items.AddObject('', Info);

  SetInfo('Kristina, München, 1 , 1', Info);
  ListBox1.Items.AddObject('', Info);

  SetInfo('Sonja, Berlin,,', Info);
  ListBox1.Items.AddObject('', Info);

  SetInfo('Petra, Frankfurt, 5 , 3', Info);
  ListBox1.Items.AddObject('', Info);

  SetInfo('Berbel, Lübeck,, 4', Info);
  ListBox1.Items.AddObject('', Info);

  ListBox1.Font.Name := 'Segoe UI';
  ListBox1.Font.Size := 10;

  ListBox1.ItemHeight := 2 + ImageList1.Height + 2;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  th, tl: Integer;
  i: Integer;
  bmp: TBitmap;
  Info: TInfo;
begin
  with (Control as TListBox) do
  begin
    //Einstellungen für selektierten Item (A)
    if odSelected in State then
      Canvas.Brush.Color := $00EFD3C6; //Helles Blau für selektierte Items

    //Löscht den Item-Canvas
    Canvas.FillRect(Rect);

    //Einstellungen für selektierten Item (B)
    if odSelected in State then
    begin
      Canvas.Pen.Color := $00C66931; //Dunkleres Blau für Fokus-Rand
      Canvas.Brush.Style := bsClear;
      Canvas.Rectangle(Rect);
    end;

    Info := TInfo(Items.Objects[Index]);

    //-Bild 48x48 px aus ImageList zeichnen----------------------------------

    bmp := TBitmap.Create;
    try
      i := Info.ImageIndex;
      if (i > -1) and (i <= Form1.ImageList1.Count - 1) then
      begin
        Form1.ImageList1.GetBitmap(i, bmp);
        Canvas.Draw(Rect.Left + 2, Rect.Top + 2, bmp);
      end;
    finally
      bmp.Free;
    end;

    //-Text-Zeile 1 ausgeben-------------------------------------------------

    //Seitenabstand für Text (rechts vom Bild)
    tl := ItemHeight + 4;
    //Oberkante für Textzeilen. Jeder neue Zeile addiert ihre Höhe dazu
    th := 2;

    Canvas.Font.Style := [fsBold]; //Font-Eigenschaften für aktuelle Zeile
    Canvas.Font.Color := $00C66931; //Blau und fett

    Canvas.TextOut(Rect.Left + tl, Rect.Top + th, Info.Name);
    th := Canvas.TextHeight(#32); //Unterkante alter Text = Oberkante neuer Text

    //-Text-Zeile 2 ausgeben-------------------------------------------------

    Canvas.Font.Style := Canvas.Font.Style - [fsBold]; //-
    Canvas.Font.Color := clWindowText; //Normal

    Canvas.TextOut(Rect.Left + tl, Rect.Top + th, Info.Ort);
    th := th + Canvas.TextHeight(#32); //s. o.

    //-Text-Zeile 3 ausgeben-------------------------------------------------

    Canvas.Font.Size := Canvas.Font.Size - 2; //-
    Canvas.Font.Color := clGray; //Grau und etwas kleiner

    if Info.Freunde > -1 then
      Canvas.TextOut(Rect.Left + tl, Rect.Top + th, Format('%d Gemeinsame Freunde', [Info.Freunde]))
    else
      Canvas.TextOut(Rect.Left + tl, Rect.Top + th, 'Keine gemeinsame Freunde');

    //-------------------------------------------------------------------------

    //Überzeichnet alten Fokus
    if odFocused in State then
      Canvas.DrawFocusRect(Rect);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  with ListBox1 do //Objekte müssen separat freigegeben werden
    for i := 0 to Items.Count - 1 do
      TInfo(Items.Objects[i]).Free; //Freigeben
end;
Das einzieg auf das du hier achten mußt ist, dass du Items nicht mehr direkt löschen darfst. Vorher mußt du das Objekt freigeben. Abgesehen am Ende. In FormDestroy werden die Objekte automatisch freigegeben.

Was deine Jpeg Daten angeht, so weiß ich nicht ob das mit ImageList geht. Alternativ beim laden in Bmp konvertieren und in Größe 48x48 konvertieren.
  Mit Zitat antworten Zitat
DelphiUser1

Registriert seit: 15. Sep 2012
56 Beiträge
 
#19

AW: Idee für Auswahlfunktion

  Alt 24. Okt 2012, 22:59
So also mithilfe dieses Quellcodes ist es mir gelungen, meine Daten zu laden:
Delphi-Quellcode:
  type
  TInfo=class
  Name:String;
  Ort:String;
  ImageIndex:Integer;
  end;

var
  Form1: TForm1;
  Info: TInfo;
  Path:String;

implementation

{$R *.dfm}

 {Gibt den X-ten Teilstring eines mit Kommas getrennten Daten-Strings}
function ExtractSubStr(Str: String; Index: Integer): String;
var
  i: Integer;
begin
  Result := '';
  if Index < 1 then Exit;
  Str := Str + ',';
  for i := 1 to Index - 1 do Delete(Str, 1, Pos(',', Str));
  Result := Trim(Copy(Str, 1, Pos(',', Str) - 1));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Doublebuffered:=True;
Path:= ExtractFilepath(ParamStr(0));
Info := TInfo.Create;
ListBox1.Style := lbOwnerDrawFixed;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  th, tl: Integer;
  i: Integer;
  bmp: TBitmap;
  Info:TInfo;
begin
  with (Control as TListBox) do
  begin
    //Einstellungen für selektierten Item (A)
    if odSelected in State then
      Canvas.Brush.Color := $00EFD3C6; //Helles Blau für selektierte Items

    //Löscht den Item-Canvas
    Canvas.FillRect(Rect);

    //Einstellungen für selektierten Item (B)
    if odSelected in State then
    begin
      Canvas.Pen.Color := $00C66931; //Dunkleres Blau für Fokus-Rand
      Canvas.Brush.Style := bsClear;
      Canvas.Rectangle(Rect);
    end;
    Info:=TInfo(Items.Objects[Index]);
    //-Bild 48x48 px aus ImageList zeichnen----------------------------------

    bmp := TBitmap.Create;
    try
      i := Info.ImageIndex;
      if (i > -1) and (i <= Form1.ImageList1.Count - 1) then
      begin
        Form1.ImageList1.GetBitmap(i, bmp);
        Canvas.Draw(Rect.Left + 2, Rect.Top + 2, bmp);
      end;
    finally
      bmp.Free;
    end;

    //-Text-Zeile 1 ausgeben-------------------------------------------------

    //Seitenabstand für Text (rechts vom Bild)
    tl := ItemHeight + 4;
    //Oberkante für Textzeilen. Jeder neue Zeile addiert ihre Höhe dazu
    th := 2;

    Canvas.Font.Style := [fsBold]; //Font-Eigenschaften für aktuelle Zeile
    Canvas.Font.Color := $00C66931; //Blau und fett

    Canvas.TextOut(Rect.Left + tl, Rect.Top + th, Info.Name);
    th := Canvas.TextHeight(#32); //Unterkante alter Text = Oberkante neuer Text

    //-Text-Zeile 2 ausgeben-------------------------------------------------

    Canvas.Font.Style := Canvas.Font.Style - [fsBold]; //-
    Canvas.Font.Color := clWindowText; //Normal

    Canvas.TextOut(Rect.Left + tl, Rect.Top + th, Info.Ort);
    th := th + Canvas.TextHeight(#32); //s. o.

    //-Text-Zeile 3 ausgeben-------------------------------------------------

    Canvas.Font.Size := Canvas.Font.Size - 2; //-
    Canvas.Font.Color := clGray; //Grau und etwas kleiner

    //-------------------------------------------------------------------------

    //Überzeichnet alten Fokus
    if odFocused in State then
      Canvas.DrawFocusRect(Rect);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  with ListBox1 do //Objekte müssen separat freigegeben werden
    for i := 0 to Items.Count - 1 do
      TInfo(Items.Objects[i]).Free; //Freigeben
end;



procedure TForm1.Timer1Timer(Sender: TObject);
var hallo:TStrings;
begin
if FileExists(path+ Edit1.Text+'.txt') then
begin
hallo:=TStringlist.Create;
hallo.LoadFromFile(path+'Info'+Edit1.Text+'.txt');
Info.Name := hallo.Strings[0]+' '+hallo.Strings[1];
Info.Ort := hallo.Strings[3];
  ListBox1.Items.AddObject('', Info);
  ListBox1.Font.Name := 'Segoe UI';
  ListBox1.Font.Size := 10;

  ListBox1.ItemHeight := 2 + ImageList1.Height + 2;
  Edit1.Text:='';
  hallo.free;
end;
das einzige Problem ist, ich weiß nicht wie ich das Bild lade (es ist eine jpg datei) und wenn man jetzt öfter nacheinander sucht, dann werden auf einmal immer wieder neue Items für die Listbox created, man hat also nach dem zweiten suchen zwei mal die selbe Person angezeigt.
Mögliche Lösung:
Delphi-Quellcode:
if Listbox1.Items.Count>1 then
ListBox1.Items.Delete(1)
else
if FileExists(path+ Edit1.Text+'.txt') then
begin
....
Jetzt sieht es aber nicht nur verbugt aus, sondern es können nicht mal zwei leute in der liste angezeigt werden, da ja direkt der zweite wieder gelöscht wird
Hilfe bitte
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#20

AW: Idee für Auswahlfunktion

  Alt 24. Okt 2012, 23:38
Du hast zum Teil den Code verstanden, ein Teil wohl nicht.

Zum Beispiel bringt es nichts die Zeile zu wiederholen. Sie gilt für alle Items gleich: ListBox1.ItemHeight := 2 + ImageList1.Height + 2; . Das Gleiche gilt für ListBox1.Font.Name und ListBox1.Font.Size. Es ist eine Einmalige Einstellung.

Die Funktion ExtractSubStr hebe ich nur gebraucht um Beispieldaten zu füllen. Wenn man es nicht braucht, dann weg damit.

Kein Fehler, aber bring etwas Struktur in deinen Code. Unübersichtlichkeit ist der erste Schritt zu Fehlern.
Delphi-Quellcode:
begin
if FileExists(path+ Edit1.Text+'.txt') then
begin
hallo:=TStringlist.Create;
Kein Fehler, aber schütze deine Objekte mit try finally end; Zuerst programmieren lernen und dann lernen es richtig zu machen (das hat mal einer so gepostet als ich ihm try finally vorschlug) ist nicht der richtige Weg.

Ohne try finalle end; erzeugt den Programm im Fehlerfall Speicherlecks. Und wie ich mir die Prozedur angucke, ist sie geradezu prädestiniert dazu Fehler zu produzieren. Da reicht nur eine Datei die deine StringList hallo nicht mit ausreichend Daten füllt und schon bricht die Prozedur zusammen. Mit einem Speicherleck. Hier zuerst schützen, dann entweder vorher abfragen ob hallo Count genug Items liefert, oder besser bei jedem Item explizit fragen. So kann man wenigstens auf die Zeilen zugreifen die die Textdatei liefert.

Zu deinem Problem mit Jpg, da gibt es zwei Möglichkeiten: die erste ist alle Daten auf der Festplatte vorher in Bmp und 48x48 zu konvertieren oder als Jpg zu laden, zu Bmp konvertieren und dann die Größe anpassen. Die Funktion die du suchst heißt JpgToBmp oder Jpg2Bmp oder statt Jpg auch JpegToBmp usw.

Am besten wäre es du postest eine Beispieldatei, dann weiß man was du laden willst.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz