Auf ein dynamisches Array per Button zugreifen



  • Hallo Leute,

    ich bin am Verzweifeln. Ich sitzt hier an meinem Schulprojekt. Tetris.
    Weit bin ich noch nicht gekommen, jedoch erstellt mir mein Programm schonmal ein Spielfeld mit Labeln, die in einem Array von 1 bis 200 angeordnet sind.

    Nun meine Frage: Wie kann ich auf bestimmte Label zugreifen?

    Wenn ich per Button (beispielsweise) die Hintergrundfarbe von Feld 48 (F[48]) ändern will, dann sagt mir mein Programm immer dass F ein nicht deklarierter Bezeichner wäre.

    Hier ist der relevante Code:

    #pragma once
    
    namespace TetrisUltimate {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    
    	/// <summary>
    	/// Zusammenfassung für Form1
    	/// </summary>
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    
    			array <Label ^> ^F = gcnew array <Label ^>(500);
    
    			int a=1;
    			int b=1;
    			int c=1;
    
    			for(a=1; a<=200; a++)
    			{
    				F[a] = gcnew Label(); 
    				F[a]->AutoSize = false; 
    				F[a]->BackColor = System::Drawing::Color::IndianRed; 
    				F[a]->Cursor = System::Windows::Forms::Cursors::Hand; 
    				F[a]->Location = System::Drawing::Point(30*c, 30*b); 
    				F[a]->Size = System::Drawing::Size(30, 30);  
    				F[a]->Name = L"F" + Convert::ToString(a); 
    				F[a]->Text = "";
    				Controls->Add(F[a]);
    
    				if(c==10)
    				{
    					b=b+1;
    					c=1;
    				}
    
    				else {c++;}
    				Application::DoEvents();
    
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~Form1()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    	private: System::Windows::Forms::Label^  lblNext;
    	private: System::Windows::Forms::Label^  lblHold;
    
    	private: System::Windows::Forms::Label^  lblLevel;
    
    	private: System::Windows::Forms::Label^  lblNextName;
    	private: System::Windows::Forms::Label^  lblHoldName;
    	private: System::Windows::Forms::Label^  lblLevelName;
    	private: System::Windows::Forms::Button^  button1;
    	private: System::Windows::Forms::Button^  button2;
    
    	protected: 
    
    	protected: 
    
    	protected: 
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		System::ComponentModel::Container ^components;
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->lblNext = (gcnew System::Windows::Forms::Label());
    			this->lblHold = (gcnew System::Windows::Forms::Label());
    			this->lblLevel = (gcnew System::Windows::Forms::Label());
    			this->lblNextName = (gcnew System::Windows::Forms::Label());
    			this->lblHoldName = (gcnew System::Windows::Forms::Label());
    			this->lblLevelName = (gcnew System::Windows::Forms::Label());
    			this->button1 = (gcnew System::Windows::Forms::Button());
    			this->button2 = (gcnew System::Windows::Forms::Button());
    			this->SuspendLayout();
    			// 
    			// lblNext
    			// 
    			this->lblNext->BackColor = System::Drawing::Color::IndianRed;
    			this->lblNext->Location = System::Drawing::Point(360, 30);
    			this->lblNext->Name = L"lblNext";
    			this->lblNext->Size = System::Drawing::Size(300, 120);
    			this->lblNext->TabIndex = 0;
    			// 
    			// lblHold
    			// 
    			this->lblHold->BackColor = System::Drawing::Color::IndianRed;
    			this->lblHold->Location = System::Drawing::Point(360, 180);
    			this->lblHold->Name = L"lblHold";
    			this->lblHold->Size = System::Drawing::Size(300, 120);
    			this->lblHold->TabIndex = 1;
    			// 
    			// lblLevel
    			// 
    			this->lblLevel->BackColor = System::Drawing::Color::IndianRed;
    			this->lblLevel->Location = System::Drawing::Point(360, 330);
    			this->lblLevel->Name = L"lblLevel";
    			this->lblLevel->Size = System::Drawing::Size(300, 60);
    			this->lblLevel->TabIndex = 2;
    			// 
    			// lblNextName
    			// 
    			this->lblNextName->AutoSize = true;
    			this->lblNextName->BackColor = System::Drawing::Color::IndianRed;
    			this->lblNextName->Font = (gcnew System::Drawing::Font(L"Verdana", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
    				static_cast<System::Byte>(0)));
    			this->lblNextName->ForeColor = System::Drawing::Color::Firebrick;
    			this->lblNextName->Location = System::Drawing::Point(364, 36);
    			this->lblNextName->Name = L"lblNextName";
    			this->lblNextName->Size = System::Drawing::Size(67, 23);
    			this->lblNextName->TabIndex = 4;
    			this->lblNextName->Text = L"NEXT";
    			// 
    			// lblHoldName
    			// 
    			this->lblHoldName->AutoSize = true;
    			this->lblHoldName->BackColor = System::Drawing::Color::IndianRed;
    			this->lblHoldName->Font = (gcnew System::Drawing::Font(L"Verdana", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
    				static_cast<System::Byte>(0)));
    			this->lblHoldName->ForeColor = System::Drawing::Color::Firebrick;
    			this->lblHoldName->Location = System::Drawing::Point(364, 186);
    			this->lblHoldName->Name = L"lblHoldName";
    			this->lblHoldName->Size = System::Drawing::Size(70, 23);
    			this->lblHoldName->TabIndex = 5;
    			this->lblHoldName->Text = L"HOLD";
    			// 
    			// lblLevelName
    			// 
    			this->lblLevelName->AutoSize = true;
    			this->lblLevelName->BackColor = System::Drawing::Color::IndianRed;
    			this->lblLevelName->Font = (gcnew System::Drawing::Font(L"Verdana", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
    				static_cast<System::Byte>(0)));
    			this->lblLevelName->ForeColor = System::Drawing::Color::Firebrick;
    			this->lblLevelName->Location = System::Drawing::Point(364, 336);
    			this->lblLevelName->Name = L"lblLevelName";
    			this->lblLevelName->Size = System::Drawing::Size(75, 23);
    			this->lblLevelName->TabIndex = 6;
    			this->lblLevelName->Text = L"LEVEL";
    			// 
    			// button1
    			// 
    			this->button1->Location = System::Drawing::Point(359, 413);
    			this->button1->Name = L"button1";
    			this->button1->Size = System::Drawing::Size(75, 23);
    			this->button1->TabIndex = 7;
    			this->button1->Text = L"button1";
    			this->button1->UseVisualStyleBackColor = true;
    			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
    			// 
    			// button2
    			// 
    			this->button2->Location = System::Drawing::Point(478, 273);
    			this->button2->Name = L"button2";
    			this->button2->Size = System::Drawing::Size(75, 23);
    			this->button2->TabIndex = 8;
    			this->button2->Text = L"button2";
    			this->button2->UseVisualStyleBackColor = true;
    			this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
    			// 
    			// Form1
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->BackColor = System::Drawing::Color::Firebrick;
    			this->ClientSize = System::Drawing::Size(690, 660);
    			this->Controls->Add(this->button2);
    			this->Controls->Add(this->button1);
    			this->Controls->Add(this->lblLevelName);
    			this->Controls->Add(this->lblHoldName);
    			this->Controls->Add(this->lblNextName);
    			this->Controls->Add(this->lblLevel);
    			this->Controls->Add(this->lblHold);
    			this->Controls->Add(this->lblNext);
    			this->Name = L"Form1";
    			this->Text = L"Tetris";
    			this->ResumeLayout(false);
    			this->PerformLayout();
    
    		}
    #pragma endregion
    
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    			 this->F[48]->BackColor = System::Drawing::Color::Firebrick;			
    		 }
    private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
    
    			}
    		 }
    };
    }
    

    Folgende Fehlermeldung wird ausgespuckt:
    error C2039: 'F': Ist kein Element von 'TetrisUltimate::Form1'
    error C2227: Links von "->BackColor" muss sich ein Zeiger auf Klassen-/Struktur-/Union-/generischen Typ befinden.

    Ich hab echt keine Ahnung was ich da anders machen muss 😕



  • Hi

    1. Ich rate empfehle dir, nicht C++/CLI zu verwenden - nimm z.B. C# oder C++. Siehe auch http://www.c-plusplus.net/forum/263084
    2. Lass die Finger von Application::DoEvents(); - es ist böse! Im Internet findest du genug Artikel warum das nicht gut ist. In deinem Code kannst du es einfach weglassen.
    3. Um in Member-Funktionen (z.B. Form1::button1_Click(..) ) auf F zugreifen zu können, muss F selbst auch Member der Klasse sein.
    Hier ein stark vereinfachtes Bsp. um es zu zeigen:

    public ref class Form1
    {
    public:
      Form1()
      {
        InitializeComponent();
    
        F = gcnew array <Label ^>(500);
        // ...
      }
    
    private:
      System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
      {
        this->F[48]->BackColor = System::Drawing::Color::Firebrick;            
      }
    
    private:
      array <Label ^> ^F; // F ist nun Member der Klasse Form1 und deshalb haben Member-Funktionen darauf Zugriff.
    };
    


  • Danke für die schnelle Antwort 🙂

    Ich hab die Codezeile von dir direkt hinzugefügt und es wurde erfolgreich kompiliert. Das war aber auch schon alles 😕

    Meine tolle Formsanwendung spuckt mir, sobald ich den Knopf drücke, folgende Fehlermeldung aus. "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

    Das DoEvents hab ich rausgenommen. Es funktioniert trotzdem. Danke für den Tipp.
    Unser Informatiklehrer hat gesagt wir müssen das reinnehmen, weil sonst die Schleife eventuell durchlaufen, aber nicht ausgeführt wird. Aber egal. Es geht auch ohne 😛

    Wenn jetzt nur der Button funktionieren würde ...



  • Ohne deinen Code ist es ein wenig schwierig. Ich vermute folgendes:

    Du hast im Konstruktor von Form1 noch die Zeile array <Label ^> ^F = gcnew array <Label ^>(500); stehen. Somit erzeugst du lokal in der Funktion das array F und initialisierst es. Nach verlassen des Konstruktors ist es nicht mehr gültig. Die Member-Variable F wird vermutlich nicht initialisiert, daher auch die Exception.

    Also:

    public ref class Form1
    {
    public:
      Form1()
      {
        InitializeComponent();
    
        // Anstelle von.. 
        array <Label ^> ^F = gcnew array <Label ^>(500);
    
        // muss das her:
        F = gcnew array <Label ^>(500);
        // ...
      }
    // ...
    };
    

Anmelden zum Antworten