Zugriff auf Steuerelemente einer Klasse aus einer andern Klasse heraus
-
Servus,
wie der threadtitel vermuten lässt, möchte ich gerne aus einer klasse heraus auf die elemente einer anderen klasse zugreifen. Soweit eigentlich kein Problem.
Ich habe die Klasse Coordinator, welche die einzelnen Klassen aufruft und verwaltet.
Als erstes starte der Coordinator die Klasse GUI und zeichnet mein Programm.
Wenn nun in der Klasse GUI der Eventhandler für einen bestimmten Button ausgelöst wird, startet der Coordinator entsprechend weitere Klassen. Unter anderem die Klasse SIM. Nun möchte ich von SIM (über den Coordinator?) auf die Elemente von GUI zugreifen. Mensch klingt das kompliziert
Ich habe also der GUI eine public methode gegeben die den Inhalt meiner Textbox ändern soll. So dann erstmal nen bisschen Quelltext, erläuterung danach.coord.h
ref class coordinator { /* constructor */ public: coordinator(void); /* destructor */ public: ~coordinator(); /* methods */ public: void startGUI(void); void startSim(void); };
coord.cpp
void coordinator::startGUI() { Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); Application::Run(gcnew GUI()); } void coordinator::startSIM() { createSIM start; start.test(); }
Sim.h
ref class SIM { public: createSIM(void); virtual ~createSIM(void); public: void test(void); };
Sim.cpp
void Sim::test() { GUI Progress; Progress.ChangeProgressbar(); Progress.ChangeTextBox("hallo"); }
GUI.h
public ref class GUI : public System::Windows::Forms::Form { public: GUI(void) { InitializeComponent(); } protected: ~GUI() { if (components) { delete components; } } private: System::Windows::Forms::Button^ IDC_Start; private: System::Windows::Forms::Button^ IDC_Settings; public: System::Windows::Forms::ProgressBar^ progressBar1; private: System::Windows::Forms::Button^ IDC_Load; private: System::Windows::Forms::OpenFileDialog^ openFileDialog1; public: System::Windows::Forms::TextBox^ IDC_InfoBox; private: System::Windows::Forms::Button^ IDC_close; protected: private: System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code void InitializeComponent(void) { //lass ich mal weg } #pragma endregion private: System::Void IDC_Start_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void IDC_Settings_Click(System::Object^ sender, System::EventArgs^ e); public: System::Void ChangeProgressbar(); public: System::Void ChangeTextBox(String^); private: System::Void GUI_Load(System::Object^ sender, System::EventArgs^ e); private: System::Void IDC_Load_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void IDC_close_Click(System::Object^ sender, System::EventArgs^ e) { this->Close(); } }; }
GUI.cpp
Void GUI::ChangeProgressbar() { GUI::progressBar1->PerformStep(); } Void GUI::ChangeTextBox(String^ input) { GUI::IDC_InfoBox->Text = input; }
So, wie man ja sieht, versuch ich auf einige Methoden der GUI-Klasse ( ChangeProgressbar(); und ChangeTextBox(String^);) aus der SIM-Klasse heraus zu starten.
Der Compiler gibt mir soweit auch keine Fehlermeldung aus. Allerdings wird nix gändert. Wenn ich bei Visual Schritt für Schritt durchgehe, sehe ich sogar wie sich der Value IDC_InfoBox->Text ändert. Das selbe bei der Progressbar, allerdings nur dort und nicht in der AnwendungWoran kann das liegen?
Brauch dringend hilfe
-
Muss Funktion void test(){ nicht void SIM::test(){ hissen ?
-
Du musst dem Objekt der Klasse SIM die Instanz der GUI Klasse übergeben.
Eine Möglichkeit wäre, das GUI Objekt im coordinator als Member zu halten (anstatt eine gcnew GUI() and Application::Run(..) zu übergeben, und dieses GUI Objekt dann dem SIM Objekt zu übergeben.
-
sat_gast schrieb:
Muss Funktion void test(){ nicht void SIM::test(){ hissen ?
Das stimmt natürlich, hatte es falsch abgeschrieben
Habs gleich mal oben korrigiert!
-
(Untergeordnete) Klassen sollten nie auf GUI-Klassen direkt zugreifen, sondern die Kommunikation sollte dann über Events ablaufen, s. z.B. http://functionx.com/vccli/general/events.htm
-
Th69 schrieb:
(Untergeordnete) Klassen sollten nie auf GUI-Klassen direkt zugreifen, sondern die Kommunikation sollte dann über Events ablaufen, s. z.B. http://functionx.com/vccli/general/events.htm
Ich hab mir das angeschaut und jetzt einen event hinzugefügt. Zu besseren übersicht hab ich die Änderungen auskommentiert, d.h. sie sind grün!
GUI.h#pragma once namespace test { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::IO; using namespace msclr::interop; //public delegate void ChangeTextEventHandler(String^ input); public ref class GUI : public System::Windows::Forms::Form { public: event ChangeTextEventHandler ^ OnChangeText; GUI(void) { InitializeComponent(); } protected: ~GUI() { if (components) { delete components; } } private: System::Windows::Forms::Button^ IDC_Start; private: System::Windows::Forms::Button^ IDC_Settings; private: System::Windows::Forms::ProgressBar^ progressBar1; private: System::Windows::Forms::Button^ IDC_Load; private: System::Windows::Forms::OpenFileDialog^ openFileDialog1; private: System::Windows::Forms::TextBox^ IDC_InfoBox; private: System::Windows::Forms::Button^ IDC_close; protected: private: System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code void InitializeComponent(void) { //OnChangeText += gcnew ChangeTextEventHandler(&GUI::ChangeTextBox); this->IDC_Start = (gcnew System::Windows::Forms::Button()); this->IDC_Settings = (gcnew System::Windows::Forms::Button()); this->progressBar1 = (gcnew System::Windows::Forms::ProgressBar()); this->IDC_Load = (gcnew System::Windows::Forms::Button()); this->openFileDialog1 = (gcnew System::Windows::Forms::OpenFileDialog()); this->IDC_InfoBox = (gcnew System::Windows::Forms::TextBox()); this->IDC_close = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // IDC_Start // this->IDC_Start->Enabled = false; this->IDC_Start->Location = System::Drawing::Point(12, 12); this->IDC_Start->Name = L"IDC_Start"; this->IDC_Start->Size = System::Drawing::Size(75, 23); this->IDC_Start->TabIndex = 0; this->IDC_Start->Text = L"Start"; this->IDC_Start->UseVisualStyleBackColor = true; this->IDC_Start->Click += gcnew System::EventHandler(this, &GUI::IDC_Start_Click); // // IDC_Settings // this->IDC_Settings->Location = System::Drawing::Point(12, 54); this->IDC_Settings->Name = L"IDC_Settings"; this->IDC_Settings->Size = System::Drawing::Size(75, 23); this->IDC_Settings->TabIndex = 1; this->IDC_Settings->Text = L"Settings"; this->IDC_Settings->UseVisualStyleBackColor = true; this->IDC_Settings->Click += gcnew System::EventHandler(this, &GUI::IDC_Settings_Click); // // progressBar1 // this->progressBar1->Location = System::Drawing::Point(12, 97); this->progressBar1->Maximum = 100; this->progressBar1->Name = L"progressBar1"; this->progressBar1->Size = System::Drawing::Size(281, 23); this->progressBar1->Step = 1; this->progressBar1->TabIndex = 2; // // IDC_Load // this->IDC_Load->Location = System::Drawing::Point(141, 11); this->IDC_Load->Name = L"IDC_Load"; this->IDC_Load->Size = System::Drawing::Size(75, 23); this->IDC_Load->TabIndex = 3; this->IDC_Load->Text = L"Load Circuit"; this->IDC_Load->UseVisualStyleBackColor = true; this->IDC_Load->Click += gcnew System::EventHandler(this, &GUI::IDC_Load_Click); // // openFileDialog1 // this->openFileDialog1->FileName = L"openFileDialog1"; // // IDC_InfoBox // this->IDC_InfoBox->Location = System::Drawing::Point(13, 127); this->IDC_InfoBox->Multiline = true; this->IDC_InfoBox->Name = L"IDC_InfoBox"; this->IDC_InfoBox->Size = System::Drawing::Size(280, 161); this->IDC_InfoBox->TabIndex = 4; // // IDC_close // this->IDC_close->Location = System::Drawing::Point(218, 309); this->IDC_close->Name = L"IDC_close"; this->IDC_close->Size = System::Drawing::Size(75, 23); this->IDC_close->TabIndex = 5; this->IDC_close->Text = L"Close"; this->IDC_close->UseVisualStyleBackColor = true; this->IDC_close->Click += gcnew System::EventHandler(this, &GUI::IDC_close_Click); // // GUI // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(309, 359); this->Controls->Add(this->IDC_close); this->Controls->Add(this->IDC_InfoBox); this->Controls->Add(this->IDC_Load); this->Controls->Add(this->progressBar1); this->Controls->Add(this->IDC_Settings); this->Controls->Add(this->IDC_Start); this->Name = L"GUI"; this->Text = L"TEST"; this->Load += gcnew System::EventHandler(this, &GUI::GUI_Load); this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void IDC_Start_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void IDC_Settings_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void ChangeProgressbar(); //public: static System::Void ChangeTextBox(String^ input); private: System::Void GUI_Load(System::Object^ sender, System::EventArgs^ e) { if(!File::Exists("option.ini")) { MessageBox::Show("This is the first start, please check the Settings"); Settings^ open = gcnew Settings; open->ShowDialog(this); } } private: System::Void IDC_Load_Click(System::Object^ sender, System::EventArgs^ e); private: System::Void IDC_close_Click(System::Object^ sender, System::EventArgs^ e) { this->Close(); } }; }
GUI.cpp
Void GUI::ChangeTextBox(String^ input) { GUI::IDC_InfoBox->Text = input; }
Sim.cpp
void SIM::test() { GUI Progress; //Progress.OnChangeText("hallo"); }
Wenn ich jetzt kompiliere, sagt er mir das ->Text auf eine Struktur / Union / Klasse zeigen muss. Das heißt in der Funktion Void Gui::ChangeTextBox(String^ input) kennt er die IDC_InfoBox nicht mehr
Zudem meckert er das er auf "Test::GUI::OnChangeText::raise": nicht mehr zugegreifen kann. Obwohl doch das Event public ist. Ich seh hier grad echt nicht mehr den Fehler. Vlt. könntet ihr mir ein kleines Code-Beispiel geben zum nachvollziehen...
Hab mir jetzt auch nen Buch zu dem Thema geordert, allerdings wird das noch ein paar Tage dauern bis das hier ist. Und ich würde gerne an dem Programm weitermachenVielen Dank schon mal!
-
Kannst Du das Projekt mal als Download anbieten oder per Mail schicken.
Kann nicht wirklich nachvollziehen was Du da genau vor hast, kann aber auch an meiner letzten Kietznacht liegen.
-
Hat sich erledigt!
Für alle die das auch mal betreffen sollte hier die Lösung:
Einfach dieprivate: static System::Windows::Forms::TextBox^ IDC_InfoBox;
sowie die
public: static System::Void ChangeTextBox(String^ input);
auf static setzen und schon hat man aus beliebiger klasse heraus zugriff indem man einfach Klasse::Funktion(); aufruft. Also bei mir wär das GUI::ChangeTextBox(String^ input);
Vielen Dank noch mal an die Helfer und bis zum nächsten Problem
-
Und wiedereinmal wurde static fälschlicherweise als Lösung angesehen...
static ist in diesem Kontext keine Lösung. Die Lösung ist wie am Anfang der Diskussion erwähnt die Referenz zu übergeben.Simon