Panel-Array zur Laufzeit erstellen + auf Event reagieren?



  • Hallo,
    ich bin sehr neu in der C++ Programmierung aber kenne mich etwas in Java und C aus. Ich habe nun ein kleines Programm in C++ (mit dem Borland C++ Builder 1) geschrieben, welches zur graphischen Simulation einiger Berechnungen ein 2-dimensionales Array von TPanels erzeugt, Code untenstehend. Jedoch möchte ich auch das Ereignis, dass die Maus über eines bzw. mehrere dieser Panels fährt, reagieren können. Normalerweise ist das kein Problem, und über den Objektinspektor->Ereignisse realisierbar. Jedoch werden meine ca. 4000 Panels erst zur Laufzeit erzeugt (bei FormActivate). Daher weiß ich nicht, wie ich diese Event-Methode schreiben soll.

    Ich würde gerne auf "OnMouseMove" reagieren. Dafür brauche ich dann natürlich die Daten, welches Panel überhaupt reagieren soll. Ich hoffe ich habe mein Problem anschaulich erklärt. Bei Unklarheiten bitte einfach fragen.

    Wäre super, wenn mir da jemand helfen könnte. Wie gesagt, ich bin ein Neuling in C++ und daher ist die graphische Ausgabe mit den Panels sicher auch nicht die eleganteste Lösung meines Problems, sollte für den Anfang jedoch genügen. 🙂

    Hier der Code zur Erzeugung der ca. 4000 Panels: (innerhalt einer verschachtelten For-Schleife)

    pan[i][j] = new TPanel(this);
          		pan[i][j]->Top = j*iHoehe+55;
          		pan[i][j]->Left = i*iBreite+20;
          		pan[i][j]->Height = iHoehe;
          		pan[i][j]->Width = iBreite;
          		pan[i][j]->Parent = this;
                pan[i][j]->Color = clScrollBar;
          		pan[i][j]->Caption = "";
          		pan[i][j]->Show();
    


  • Für den Builder bist du im falschen Forum..



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum VCL (C++ Builder) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hallo

    Zunächst schreibst du du reine OnMouseMove-Methode von Hand (oder durch den OI für eine Dummy-Komponente).
    Die fertige Methode kannst du dann den dynamischen Komponenten einfach zuweisen :

    pan[i][j]->OnMouseMove = MyMouseMove;
    

    Den Aufruf von Show() brauchst du nicht extra noch, den macht die VCL automatisch.

    Sehr effizient scheint mir das Erzeugen von 4000 Komponenten nicht zu sein... aber wenn dein Programm damit zurecht kommt ist es erstmal in Ordnung.

    bis bald
    akari



  • onkelrocker schrieb:

    Jedoch werden meine ca. 4000 Panels erst zur Laufzeit erzeugt (bei FormActivate).

    Dieses Ereignis wird jedes Mal ausgeführt, wenn das Form den Fokus erhält. Schlechter Platz um Komponenten zu instanzieren...



  • hinweiser schrieb:

    onkelrocker schrieb:

    Jedoch werden meine ca. 4000 Panels erst zur Laufzeit erzeugt (bei FormActivate).

    Dieses Ereignis wird jedes Mal ausgeführt, wenn das Form den Fokus erhält. Schlechter Platz um Komponenten zu instanzieren...

    Wo wäre denn ein besserer Platz bzw. was wäre effektiver und schneller, anstatt Panels für die Simulation?

    BTW: Das Programm ist eine Version des Google: Game of Life.



  • Im Konstruktor der Form!?



  • Jansen schrieb:

    Im Konstruktor der Form!?

    void __fastcall TForm1::FormActivate(TObject *Sender)
    Das ist doch der Konstruktor der Form! Oder?



  • Hallo

    Nein das ist nicht der Konstruktor.
    Der Konstruktor ist immer mit dem Namen der Klasse versehen

    TForm::TForm(...)
    

    bis bald
    akari



  • akari schrieb:

    Hallo

    Nein das ist nicht der Konstruktor.
    Der Konstruktor ist immer mit dem Namen der Klasse versehen

    TForm::TForm(...)
    

    bis bald
    akari

    Danke! Also diesen Fehler habe ich behoben. Auch wie ich auf die Maus reagiere funktionert nun. Hierfür habe ich ein Dummy-Panel erstellt und in dessen Aufruf der Methode Panel1MouseMove ermittle ich dann über den Tag die X und Y Koordinate des aktuell betätigten Panels. jedoch ist das ganze langsam und reagiert auf jede Mausbewegung, nicht jedoch bei Klick. Eigentlich soll die Maus natürlich nur reagieren, solange ich die linke Maustaste gedrückt halte. Hat jemand ne Idee, wie ich das mache?



  • Setze beim OnMouseDown-Event eine bool-Variable auf true, so dass du im OnMouseMove weißt, dass die linke Teats gedrückt ist. Bei OnMouseUp setzt du diese Variable wieder zurück.



  • Braunstein schrieb:

    Setze beim OnMouseDown-Event eine bool-Variable auf true, so dass du im OnMouseMove weißt, dass die linke Teats gedrückt ist. Bei OnMouseUp setzt du diese Variable wieder zurück.

    Hab ich schon probiert, funktioniert aber nicht, schätze dass er solange ich die linke Maustate gedrückt halte nicht mehr aus der OnMouseDown Event-Routine rauskommt. Kann das sein?



  • Nein, das kann nicht sein. Wie hast du es denn probiert?



  • Braunstein schrieb:

    Nein, das kann nicht sein. Wie hast du es denn probiert?

    Eigentlich wie Du gesagt hast. Ich habe für das eine Dummy-Panel auch noch die beiden Events "OnMouseDown" und "OnMouseUp" hinzugefügt und darin setze ich eine globale Variable auf einen bestimmten wert, welchen ich dann in der "OnMouseMove"-Routine abfrage und dementsprechend bei mouse down reagiere, und ansonsten nicht. Dabei tut sich nichts.



  • Setze mal Breakpoints in alle 3 Events und schau nach ob die angesprungen werden. Deine bool Variable sollte nicht global sonder besser ein member deiner Form sein (private). Außerdem solltest du sie im Konstruktor der Form initialisieren.



  • Braunstein schrieb:

    Setze mal Breakpoints in alle 3 Events und schau nach ob die angesprungen werden. Deine bool Variable sollte nicht global sonder besser ein member deiner Form sein (private). Außerdem solltest du sie im Konstruktor der Form initialisieren.

    Hab ich gemacht. Die OnMouseDown bzw. Up Events werden nie angesprungen. Sobald ich mit der Maus über eines der Panels fahre springt er in das OnMouseMove-Event hinein. Ich komme gar nicht zum Klicken.

    Was ich aber hinbekommen habe ist, dass ich bei OnMouseKlick eine BoolVariable invertiere, also beim 1. Klick fängts an zu Zeichnen, beim 2. Klick hörts wieder auf. Würde das jedoch gerne so hinbekommen, dass er nur während die Maustaste gedrückt gehalten wird auch wirklich reagiert.



  • Sind die MouseDown und Up-Events auch ordentlich zugewiesen? D.h. hast du die mit dem Objektinspektor erstellt?
    Bei mir funktioniert das einwandfrei.



  • Braunstein schrieb:

    Sind die MouseDown und Up-Events auch ordentlich zugewiesen? D.h. hast du die mit dem Objektinspektor erstellt?
    Bei mir funktioniert das einwandfrei.

    Jep, die habe ich mit dem Objektinspektor erstellt und weise sie in der verschachtelten Schleife den Panels folgendermaßen zu:

    panel[i][j]->OnMouseDown = Panel1MouseDown

    Es reagiert jeweils nur das einzige Panel, über dem ich gerade Klicke. Egal über wie viele andere ich auch noch drüber fahre, passiert nichts mehr, bis ich loslasse und wieder klicke, dann reagiert wieder ein Panel.

    Habe nun nochmals rumprobiert und dabei gemerkt, dass das ganze funktioniert! Jedoch mit der rechten Maustaste, nicht mit der Linken. Wie kann ich das nun wieder ändern?

    Ich habe innerhalb des OnMouseMove-Events eine testweise Ausgabe integriert und kann nun deutlich sehen, in die Routine springt er sowohl bei rechten als auch bei linkem Klick der Maustaste hinein. Jedoch zeichnen tut er nur beim Drücken der rechten Taste. Verstehe das nicht!



  • Ohne deinen Code zu kennen kann ich da keine weiteren Hinweise geben.



  • Braunstein schrieb:

    Ohne deinen Code zu kennen kann ich da keine weiteren Hinweise geben.

    Oki hier einige Codeschnipsel:

    Im Konstruktor generiere ich die Panels:

    for (int i = 0; i < iZeilen; i++)
        {
    		for (int j = 0; j < iSpalten; j++)                                      //Panels auf Oberflaeche erzeugen
            {
            	pan[i][j] = new TPanel(this);
          		pan[i][j]->Top = i*iHoehe+55;
          		pan[i][j]->Left = j*iBreite+20;
          		pan[i][j]->Height = iHoehe;
          		pan[i][j]->Width = iBreite;
          		pan[i][j]->Parent = this;
                pan[i][j]->Color = clScrollBar;
          		pan[i][j]->Caption = "";
                pan[i][j]->Tag = tag;
                pan[i][j]->OnMouseMove = Panel1MouseMove;
                pan[i][j]->OnClick = Panel1Click;
                pan[i][j]->OnMouseDown = Panel1MouseDown;
                pan[i][j]->OnMouseUp = Panel1MouseUp;
                tag++;
            }//end for
        }//End for
    
    Events für Panel1 (Dummy-Panel):
    
    void __fastcall TForm1::Panel1MouseDown(TObject *Sender, TMouseButton Button,
    	TShiftState Shift, int X, int Y)
    {
        maus = 1;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Panel1MouseUp(TObject *Sender, TMouseButton Button,
    	TShiftState Shift, int X, int Y)
    {
        maus = 0;
    }
    

    maus = Integer. 0 = nicht gedrückt, 1 = maustaste gedrückt.

    Event OnMouseMove:

    void __fastcall TForm1::Panel1MouseMove(TObject *Sender, TShiftState Shift,
    	int X, int Y)
    {
    	AnsiString str, str2;
        int zeile, spalte;
        //static int tmp;							//test
        TPanel *panelint = ((TPanel *)(Sender));
        int zs = panelint->Tag;
        //Label5->Caption = maus;		//Test
        if (maus)
        {
        	//tmp++;                      	//Test
            //Label7->Caption = tmp;          	//Test
        	zeile = giveMeI(zs);
        	spalte = giveMeJ(zs, zeile);
    		if (!modus)
        	{
        		pan[zeile][spalte]->Color = farbe;
        		iFeld[zeile][spalte] = 1;
        	}//end if
            if (modus)
            {
            	pan[zeile][spalte]->Color = clScrollBar;
        		iFeld[zeile][spalte] = 0;
            }//end if
        	str = (AnsiString) spalte;
        	str2 = (AnsiString) zeile;
        	Label11->Caption = str;
        	Label13->Caption = str2;
        }//end if
    }//End panel1 mouse move
    

    Wie gesagt, bei rechter Maustaste funktionierts, nur bei linker Maustaste reagiert nur 1 einziges Panel.


Anmelden zum Antworten