Frage zu Images



  • Hallo,

    ich möchte ein Programm schreiben, welches mehrere Images enthalten soll. Jedoch ist es ziemlich mühsam und führt of zu Fehlern (durch Schreibfehler z.b.), wenn ich jedes Image einzeln "erwähnen" muss. Zum Beispiel:

    if(anzahl==30)
    {
    Image1->Visible=true;
    Image2->Visible=true;
    ...
    ...
    Image30->Visible=true;
    }

    Meine Frage währe jetzt, ob man nicht alle irgendwie einfacher in einer for-Schleife oder so (z.B. nur durch einen einzigen Befehl) abklopfen kann?
    Wie es zum Beispiel mit einem Array möglich ist/währe?!



  • Schau doch mal in die FAQ Thema: Komponenten benutzen



  • Benutze ImageListen (falls die Bilder die gleichen Abmessungen haben). Dann kannst du die einzelnen Bilder über einen Index ansprechen.



  • Danke soweit...
    Bin schon etwas weiter gekommen, jedoch bin ich wieder auf ein Problem gestoßen.
    Ein Ausschnitt aus meinem Code sieht wie folgt aus:

    for(x=0;x<6;x++)
      {
        bilder[x]=new TImage(Form1);
        bilder[x]->Parent=Form1;
        bilder[x]->Width=90;
        bilder[x]->Height=132;
        bilder[x]->Top=20;
        bilder[x]->Left=x*94;
        bilder[x]->OnClick=Bild1Click;
        bilder[x]->Show();
        bilder[x]->Picture->LoadFromFile("Bilder\\" + String(x+1) + ".jpg");
      }
    
    void __fastcall TForm1::Bild1Click(TObject *Sender)
    {
        bilder[1]->Visible=false;
    }
    

    Hierbei ist es aber so, das egal welches der 6 Bilder angeklickt werden, wird immer das selbe Ereignis ausgeführt. Ich jedoch möchte das jedes einzelne Bild verschiedene Ereignisse ausführt. Meine Frage:
    Gibt es sowas ähnliches wie:

    bilder[x]->OnClick=Bild + x + Click ???

    Also etwas von der Art wie ich es bei LoadFromFile habe...
    Sodass ich folgende Funktionen benutzen kann:

    *void __fastcall TForm1::Bild1Click(TObject *Sender)
    {
    bilder[1]->Visible=false;
    }
    //----------------------------------------------------------------
    void __fastcall TForm1::Bild2Click(TObject *Sender)
    {
    bilder[2]->Top=60;
    bilder[2]->Left=522;
    }

    usw...*

    Sollte es sowas nicht geben, oder auf diese weise nicht lösbar sein, könnte mir jemand genauer (am besten direkt an meinem Beispiel) Erklären, wie ich es mit einem dynamic_cast umsetzen kann oder mit einer Tag-Abfrage, je nachdem was besser/einfacher ist. Da ich hier nirgends eine Erklärung gefunden habe, mit der ich etwas Anfangen konnte.



  • bilder[x]=new TImage(Form1);
        bilder[x]->Parent=Form1;
        .
        .
        .
        bilder[x]->Tag=x;
    
    void __fastcall TForm1::Bild1Click(TObject *Sender) 
    {
      switch (TImage(Sender)->Tag)
      {
        case 0: //Was mit bild 0 passieren soll
        .
        .
        .
    
                break;
        case n: //Was mit bild n passieren soll
    
                break;
    
      } 
    }
    


  • Du bräuchtest in dem Fall schon eine OnClick-Funktion für alle Images.
    Wegen Tag:
    Du kannst doch beim Erstellen deiner Images der Tag-Eigenschaft den dazugehörigen Index zuweisen
    bilder[x]->Tag = x;

    Das Erkennen des richtigen Images solltest du anhand der Beispiele in der FAQ eigentlich hinkriegen.
    z.Bsp. so in der OnClick-Funktion

    TImage *img = dynamic_cast<TImage *>(Sender);
    if( img != 0 )
    {
    // hier dann irgend was
    // wegen Tag
       if( img->Tag == 5 )
       {
       }
    }
    


  • Wunderbar, hat jetzt alles geklappt, was ich wollte, Dank an alle!
    Wobei ich sagen muss, das der Beispiel Code vom "DerAltenburger" bei mir nicht so ganz geklappt hat, da hat der irgendeine Fehlermeldung in der switch Zeile angezeigt, die ich so nicht habe lösen können, dafür hat das darauf folgende Beispiel prima geklappt.



  • Warum benutzt ihr immer diesen Tag? Das ist so nichts sagend.



  • 2fast4u schrieb:

    Wunderbar, hat jetzt alles geklappt, was ich wollte, Dank an alle!
    ... das der Beispiel Code vom "DerAltenburger" bei mir nicht so ganz geklappt hat, da hat der irgendeine Fehlermeldung in der switch Zeile angezeigt,...

    Sorry, Ich hatte beim Casten den * nach TImage vergessen.

    ...switch (((TImage*) Sender)->Tag)... 🕶



  • So, bin wieder auf ein "hartnäckiges" Problem gestoßen, was ich mir nicht erklären kann. Soweit ich jetzt durch die Suche rausgefunden habe liegt es wohl am Speicher, oder wir durch Speicherlacks verursacht, aber was ich dagegen tun kann ist mir immer noch ein Rätsel. Mein Problem an einem Beispiel würde wie folgt aussehen:

    TImage *Person1_Bilder[36];
    TImage *Person2_Bilder[36];
    TImage *Person3_Bilder[36];
    

    Also es können alle 36 Felder pro Array beschrieben werden, müssen aber nicht, meistens werden nur so zwischen 1 - 14 felder beschrieben, bzw. ein Bild zugewiesen. So wenn der User auf ein Button klickt, wird eine Funktion aufgerufen, die folgendes enthällt:

    for(x=0;x<max1;x++)
        {delete Person1_Bilder[x];}
    
    for(x=0;x<max2;x++)
        {delete Person2_Bilder[x];}
    
    for(x=0;x<max3;x++)
        {delete Person3_Bilder[x];}
    

    max1, max2 und max3 wird immer mitgezählt, je nachdem wie viele Bilder der User darstellen wollte, von dem zugehörigem Array.
    So und wenn der User jetzt auf diesen besagten Button klickt, kann es mal vorkommen, das alles gut läuft und alle dargestellten Bilder gelöscht werden ohne Probleme, das kann auch noch weitere neustarts des Programms gut gehen, aber ab und zu und manchmal auf öfters kommt immer eine Felermeldung:

    Im Projekt Projekt1.exe ist eine Exception der Klasse EAccessViolation aufgetretten. Meldung 'Zugriffsverletzung bei Adresse xxxxxxxx in Modul 'rtl60.bpl'. Lesen von Adresse yyyyyyyy'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.

    Wenn man auf OK klick und den Prozess trotzdem fortsetzt, kommt nochmal eine abgespeckte version des Fehlers von Windows aus. Nach einem weiteren klick auf das Ok werden eigentlich die Bilder trotzdem gelöscht. Jedoch tritt, wie bereits gesagt, dieser Fehler zufällig mal auf mal nicht, voll komisch.

    Ich hoffe es wurde verstanden und mir kann jemand da weiter helfen.



  • /EDIT : Doppelpost



  • Hallo

    ich denke, das Programm versucht, mit delete eine Instanz zu löschen, die es schon nicht mehr gibt, weil der Zähler nicht korrekt gesetzt wurde.
    Als kleinen Test kannst du ja mal die Speicherinhalte nach dem Löschen zurücksetzen

    for(x=0;x<max1;x++)
        {delete Person1_Bilder[x]; Person1_Bilder[x] = NULL;}
    
    for(x=0;x<max2;x++)
        {delete Person2_Bilder[x]; Person2_Bilder[x] = NULL;}
    
    for(x=0;x<max3;x++)
        {delete Person3_Bilder[x]; Person3_Bilder[x] = NULL;}
    

    denn delete NULL verursacht keinen Fehler im Gegensatz zu delete <irgendwas>

    Am besten aber verwendest du dynamische Arrays, die nur gültige Instanzen enthalten. zum Beispiel TImageList, wenn die Bitmaps gleichgroß sind,
    oder DynamicArray<TImage *> bzw. vector<TImage *>
    Damit kannst du dann auch mehrdimensionale Arrays machen, um die drei Arrays zusammenzufassen.

    bis bald
    akari



  • evtl. hilft auch TObjectList. Die übernimmt wohl auch die Speicherverwaltung.


Anmelden zum Antworten