Entwickler-Ecke

Multimedia / Grafik - JPEG verändern


ShinShan - So 13.08.06 22:04
Titel: JPEG verändern
Hi ich habe viele Jpg-Images auf ein Formular mit zufälliger Position erzeugen lassen, und möchte nun, wenn man auf ein entsprechendes Bild clickt dieses ändern. Sprich ein neues an die selbe Position Laden.

Die Daten über die Position der einzelnen Bilder habe ich in einem Array gespeichert.

Ich weis nur nicht wie ich das Bild raus bekommen soll, auf das geklickt wurde. Hab schon viel mit dem Sender des TImages rumprobiert. Aber wenn ich es mit


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
 
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var jpg:TJPEGImage;
  begin
 try TImage(Sender).Picture.LoadFromFile('E:\desktop\Memorie\Bilder\25.jpg');
 except
  showmessage('danaben');
 end;
end;


versucht, aber da ändert sich nichts, wenn ich wenn ich drauf klicke.


alias5000 - So 13.08.06 22:50

Benutze doch einfach entsprechende Ereignisse der einzelnen TImages
Also OnClick/OnMosueDown/OnMosueUp von jedem TImage

Gruß
alias5000


Narses - So 13.08.06 23:11

Moin!

Schau mal hier [http://www.delphi-library.de/topic_VCL+Memory+Tutorial++fuer+EinUmsteiger_44084.html], vielleicht kommst du damit weiter. ;)

cu
Narses


GSE - Mo 14.08.06 00:08

der Code muss ins MouseDown der Images nich das der Form

mfg
GSE


ShinShan - Mo 14.08.06 15:00

danke shcon mal für die Antworten.

Ich glub es ist besser wenn ich hier mal den ganzen Code anzeigen lasse, damit ihr seht, wie das alles funzt bzw. nicht funzt ;)


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:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
var
  Form1: TForm1;
  Karte: array[1..25of Bild;

...

procedure TForm1.Kartenlegen;      //hier werden zufällig Karten auf der Form abgelegt
var i,j:byte;
    jpg:TJPEGImage;
begin
 for i:=1 to 25 do
  begin
   for j:=1 to 2 do
    begin
    Karte[i].Bild:=TImage.Create(self); // in der Prozedur TForm1.Rungame (wegen TForm1 ist self=TForm1)
    Karte[i].Bild.Parent:=self;
    Karte[i].Bild.Left:=random(639)+1// Position setten
    Karte[i].Bild.Top:=random(479)+1;
    Karte[i].vorne:=inttostr(i); // welches Bild
    Karte[i].wo.X:=random(639)+1// wo liegt
    Karte[i].wo.Y:=random(479)+1//    "
    jpg:=TJPEGImage.create;
    jpg.LoadFromFile('E:\desktop\Memorie\Bilder\26.jpg'); // Ist das Bild der Rückseite einer Karte
    Karte[i].Bild.Picture.Assign(jpg);
    jpg.free;
    end;
  end;
end;

procedure TForm1.ImageMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var jpg:TJPEGImage;
    i:byte;
  begin
  for i:=1 to 25 do
   begin
    if (Karte[i].wo.X<=X) and (Karte[i].wo.X+30>=X) then // denn die Bilder 30x40 Pixel
     begin
      if (Karte[i].wo.Y<=Y) and (Karte[i].wo.Y+40>=Y) then
       begin
        Karte[i].Bild:=TImage.Create(self); // in der Prozedur TForm1.irgendwas(wegen TForm1 ist self=TForm1)
        Karte[i].Bild.Parent:=self;
        Karte[i].Bild.Left:=Karte[i].wo.X;  // Die Stelle raus suchen, an der das
        Karte[i].Bild.Top:=Karte[i].wo.Y;   // Bild ist.
        jpg:=TJPEGImage.create;             // und dort die Forderseite laden
        jpg.LoadFromFile('E:\desktop\Memorie\Bilder\'+inttostr(i)+'.jpg');
        Karte[i].Bild.Picture.Assign(jpg);
       end
        else showmessage('daneben');
     end
      else showmessage('daneben');
   end;
end;

initialization
randomize;

end.


Wieso läd der das neue Bild nicht rein, bzw. geht garnicht in die Prozedur um zu testen ob man mit der Maus getroffen hat?


Narses - Mo 14.08.06 15:06

Moin!

Zwei Sachen auf Anhieb:

- Warum packst du die Bilder nicht in eine Image-List? Ist doch viel einfacher zu handeln... ;)

- Du erzeugst da andauernd Images, wann gibst du die denn wieder frei? :gruebel:

cu
Narses


ShinShan - Do 17.08.06 19:00

@ Nerses:
Leider weis ich nicht wie ich eine Image-List handle :)
so ist es dann mit den einzelnen Bildern erstmal einfacher für mich gewesen.
Was sind denn die Vorteile von soner Image-List?

Und die Freiganbe, hab ich im close-event.
Oder gehört die in das destroy-event?


Raffo - Do 17.08.06 19:04

Na ja, ich für meinen Teil würde sagen, es wird eh "destroyed" wenn das Programm beendet wird. Wichtig wäre das nur, wenn Dein Programm aufm Server läuft und es ständig an wäre...


ShinShan - Do 17.08.06 22:09

Ja aber zurück zu meiner Frage:

Ich hab jetzt mit

Getcursorpos

die Mausposition geholt und vergleiche dann, ob ein Bild getroffen wurde.

Aber irgendwie treffe ich auch die Bilder, wenn ich nicht drauf klicke *kopfkratz*

Kann das an Getsursorpos liegen?

Meine Form füllt nämlich nicht den ganzen Bildschirm aus.
Vielleicht geht aber Getcursorpos davon aus.

ich stelle mal den gesammten code rein
Ich hoffe er erklärt sich ein wenig von alleine


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:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jpeg, ExtCtrls, ImgList;

type
  Bild = record
   vorne:string;
   Bild:TImage;
   wo:TPoint;
  end;
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Kartenlegen;
    procedure ImageMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ImageClick(Sender:TObject);
  private
    gabe:integer;
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;
  Karte: array[1..50of Bild;
  Spieler: array of byte;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var n:byte;
begin
 try
  n:=strtoint(edit1.text);
 except
  showmessage('Bitte geben Sie keine Buchstaben ein!');
 end;
 if (n>0)and(n<5then setlength(Spieler,n)
  else
   showmessage('Keine Spieler?/zu viele?');
  Button1.Visible:=false;
  Edit1.Visible:=false;
  Label1.Visible:=false;
  Kartenlegen;
end;

procedure TForm1.Kartenlegen;      //hier werden zufällig Karten auf der Form abgelegt
var i,j:byte;
    jpg:TJPEGImage;
begin
 for i:=1 to 50 do
  begin
    Karte[i].Bild:=TImage.Create(self); // in der Prozedur TForm1.Rungame (wegen TForm1 ist self=TForm1)
    Karte[i].Bild.Parent:=self;
    Karte[i].Bild.Left:=random(639)+1// Position setten
    Karte[i].Bild.Top:=random(479)+1;
    Karte[i].vorne:=inttostr(i); // welches Bild
    Karte[i].wo.X:=Karte[i].Bild.Left; // wo liegt
    Karte[i].wo.Y:=Karte[i].Bild.Top; //    "
    jpg:=TJPEGImage.create;
    jpg.LoadFromFile('E:\desktop\Memorie\Bilder\26.jpg'); // Ist das Bild der Rückseite
    Karte[i].Bild.OnClick:=ImageClick;
    Karte[i].Bild.Picture.Assign(jpg);
    jpg.free;
  end;
end;

procedure TForm1.ImageMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var jpg:TJPEGImage;
    i:byte;
  begin

end;

procedure TForm1.ImageClick(Sender:TObject);
var i,X,Y,b:integer;
    jpg:TJPEGImage;
    p:TPoint;
begin
   GetCursorPos(p);
   X:=p.X;
   Y:=p.Y;
   for i:=1 to 50 do
   begin
    if (Karte[i].wo.X<=X) and (Karte[i].wo.X+30>=X) then // denn die Bilder 30x40 Pixel
     begin
      if (Karte[i].wo.Y<=Y) and (Karte[i].wo.Y+40>=Y) then
       begin
        if i<=25 then b:=i else b:=i-25;
        Karte[i].Bild:=TImage.Create(self); // in der Prozedur TForm1.irgendwas(wegen TForm1 ist self=TForm1)
        Karte[i].Bild.Parent:=self;
        Karte[i].Bild.Left:=Karte[i].wo.X;  // Die Stelle raus suchen, an der das
        Karte[i].Bild.Top:=Karte[i].wo.Y;   // Bild ist.
        jpg:=TJPEGImage.create;             // und dort die Forderseite laden
        jpg.LoadFromFile('E:\desktop\Memorie\Bilder\'+inttostr(b)+'.jpg');
        Karte[i].Bild.Picture.Assign(jpg);
        jpg.free;
       end
        else showmessage('daneben');
     end;
   end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var i:integer;
begin
 for i:=1 to 50 do
   Karte[i].Bild.Free;
end;

initialization
randomize;

end.


Vorhanden sind am Anfang ein Label, Edit1 (eingabe der Anzahl der Spieler (was bishar noch keine Auswikungen hat, es sei denn ,man gibt einen Buchsatben oder ein eZahl größer als 4 ein), und der LOS-(button1) der alles starten lässt.

Die Bilder die Geladen werden, haben Zahlen als Namen (von 1 bis 26). 26 ist dabei die Rückseite.
ich hoffe ihr seht jetzt etwas durch.


Marco D. - Do 17.08.06 22:17

user profile iconShinShan hat folgendes geschrieben:

Ich hab jetzt mit

Getcursorpos

die Mausposition geholt und vergleiche dann, ob ein Bild getroffen wurde.

Aber irgendwie treffe ich auch die Bilder, wenn ich nicht drauf klicke *kopfkratz*

Kann das an Getsursorpos liegen?

Meine Form füllt nämlich nicht den ganzen Bildschirm aus.
Vielleicht geht aber Getcursorpos davon aus.

Dafür gibts die Funktion ScreenToClient. Schau mal in der Hilfe nach.


Narses - Do 17.08.06 23:27

user profile iconNarses hat folgendes geschrieben:
Warum packst du die Bilder nicht in eine Image-List? Ist doch viel einfacher zu handeln...

user profile iconShinShan hat folgendes geschrieben:
Leider weis ich nicht wie ich eine Image-List handle

user profile iconNarses hat folgendes geschrieben:
Schau mal hier [http://www.delphi-library.de/topic_VCL+Memory+Tutorial++fuer+EinUmsteiger_44084.html], vielleicht kommst du damit weiter.


---

user profile iconRaffo hat folgendes geschrieben:
Na ja, ich für meinen Teil würde sagen, es wird eh "destroyed" wenn das Programm beendet wird. Wichtig wäre das nur, wenn Dein Programm aufm Server läuft und es ständig an wäre...

:shock: Aha, dann würde ich schrecklich gerne mal dein Zimmer sehen, und wie´s da drin so aussieht... :rofl:

cu
Narses


Raffo - Fr 18.08.06 07:37

@marco, habe folgendes Grundgerüst gefunden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
function IsMouseOver(Control: TControl): Boolean; 
var 
  p: TPoint;
begin
  if GetCursorPos(p) then 
  begin
    p := Control.ScreenToClient(p);
    Result := (p.X >= 0and (p.X <= Control.Width) and
              (p.Y >= 0and (p.Y <= Control.Height) {AND Control.Visible};
  end
  else
    Result := False;
end;


@narses, wirklich sehr geistreicher Kommentar, was hat die Virtualität mit der Realität zu tun? Ich würde das in der Realtität eher so vergleichen: Wenn ich meinen Computer ausschalte, brauche ICH die laufenden Programme nicht beenden.


Narses - Fr 18.08.06 09:20

Moin!

user profile iconRaffo hat folgendes geschrieben:
Wenn ich meinen Computer ausschalte, brauche ICH die laufenden Programme nicht beenden.

Windows hat folgendes geschrieben:
Der Computer wurde das letzte mal nicht ordnungsgemäß heruntergefahren...

Und wer repariert dann die kaputt gegangenen Files? ;)

Das hat was mit sinnvoller Art und Weise zu tun, man könnte auch "Programmierstil" dazu sagen. Da das hier aber schon fast immer auf einen Glaubenskrieg hinauslaufen wird, spare ich mir Weiteres, will dir aber eine meiner Erkenntnisse nicht vorenthalten: "Geht doch" ist der Programmierstil, der dir langfristig die meisten Probleme bereiten wird. :|

cu
Narses


heinze - Fr 18.08.06 10:44

Zitat:
Und wer repariert dann die kaputt gegangenen Files?


Es gehen doch keine Kaputt?

Windows schickt an alle Programme den Befehl sich zu Beenden, und sofern sich keins extrem dagegen auflehnt fährt sich der PC dan runter ohne das ich Programme wie WinAmp, ICQ, bzw 20 andere Hintergrundprozesse selbst beenden mus.

Soweit ich es Richtig verstanden habe macht Delphi selbiges, sofern das Program richtig beendet wird und nicht bei testläufen einfach abgebrochen wird (wegen Endlosschleife usw) was nach einigen male dan ne Meldung bringt das der Speicher zu voll ist und man dan Delphi selbst neu starten muss. (So gings mir bei Datenbanken)

Zitat:
Wenn ich meinen Computer ausschalte, brauche ICH die laufenden Programme nicht beenden.


Er hat ja nie behauptet das sie niemand beendet, nur das er selbst es nicht tut.

Optimiert wirds wens erstmal überhaupt richtig läuft denk ich mir bei sowas.


ShinShan - Mi 20.09.06 22:17

Ich hab das ganze jetzt malso gelöst.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
Klick.X:=X;
Klick.Y:=Y;
klick:=ScreenToClient(ClientToScreen(klick));
showmessage(inttostr(klick.x)+'/'+inttostr(klick.y));
end;


Das Problem ist jetzt nur noch, dass mir an einigen Stellen des Bildschirms keine Rückgabe gegeben wird, welche Koordinaten der Klcik hatte.

Das ist volkommen unabhängig davon, ob ich auf ein Bild klicke, das erstellt wurde oder nicht.
Was kann daran nur falsch sein?????

Die Idee mit dem ScreenToClient war trotzdem super!
DANKE nochmal