Pass a value from one class to another!

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
MatFox
In need of some credit
In need of some credit
Posts: 3
Joined: Mon May 18, 2020 8:32 am

Pass a value from one class to another!

Post by MatFox » Mon May 18, 2020 9:30 am

Hello Forum,
It's the first time I use this medium for advice. I have been searching the web for an appropriate solution, but had yet no luck. The issue is with setting a wxStaticText in a - let say class A -, such as:

Code: Select all

textBox = new wxStaticText(parent, wxID_ANY, _("50"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);


from another - let say class B -, such as

Code: Select all

m_radioBox[i]->Bind
		(
			wxEVT_RADIOBUTTON, [&](wxCommandEvent& event)
			{
				// any other code here ...

                                // alternative 1.
                                static int tvalue;
				A::tvalue = event.GetId();

                                // alternative 2. 
                                int pvalue = event.GetId(); 
                                A* k = new A("");
                                k->textBox->SetLabel(mystring << pvalue); 

			} // Lambda
		); // Bind
The variable tvalue is declared as static int of classA and defined outside A.
In alternative 1 I use the static int and call SetLabel( mystring) in A . In alternative 2 I make us of a local variable of B and call SetLabel from B.

Code: Select all

mystring << A::tvalue
textBox->SetLabel(mystring);
Neither approach is working. However, the code compiles no error but the textbox only shows the default value. It doesn't seem to update.
What is the correct approach for this issue.
Any thoughts about this are much appreciated.
Matthias
Last edited by MatFox on Mon May 18, 2020 4:46 pm, edited 1 time in total.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2387
Joined: Sun Jan 03, 2010 5:45 pm

Re: Pass a value from one class to another!

Post by PB » Mon May 18, 2020 10:59 am

I have no idea what you meant to achieve but it looks like this code should not even compile
MatFox wrote:
Mon May 18, 2020 9:30 am

Code: Select all

int pvalue = event.GetId(); 
k->textBox->SetLabel( pvalue); 
wxStaticText::SetLabel() takes a string, not an int.

MatFox wrote:
Mon May 18, 2020 9:30 am

Code: Select all

A* k = new A("");
You probably also do not want to create a new instance of A every time the radio box selection changes, with who knows what side effects


If I wanted to update a control based on event from another control, I would do something like this

Code: Select all

#include <wx/wx.h>
#include <wx/file.h>

class MyDialog : public wxDialog
{
public:
    MyDialog(): wxDialog(nullptr, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
        wxRadioBox* radioBox = nullptr;
        wxArrayString radioBoxChoices;

        radioBoxChoices.push_back("Red Pill");
        radioBoxChoices.push_back("Blue Pill");
        radioBox = new wxRadioBox(this, wxID_ANY, "Select a choice", wxDefaultPosition, wxDefaultSize, radioBoxChoices);
        radioBox->Bind(wxEVT_RADIOBOX, &MyDialog::OnUpdateChoiceDisplayFromRadioBox, this); 
        
        m_choiceDisplay = new wxStaticText(this, wxID_ANY, "");
        UpdateChoiceDisplayText(radioBox->GetString(radioBox->GetSelection()));

        mainSizer->Add(radioBox, wxSizerFlags().Expand().Border());
        mainSizer->Add(m_choiceDisplay, wxSizerFlags().Expand().Border());
        SetSizerAndFit(mainSizer);
    }
private:
    wxStaticText* m_choiceDisplay;

    void UpdateChoiceDisplayText(const wxString& choice)
    {
        m_choiceDisplay->SetLabel(wxString::Format("Your choice is '%s'", choice));
    }

    void OnUpdateChoiceDisplayFromRadioBox(wxCommandEvent& evt)
    {
        // It seems that the text for the selected radio box item can be
        // retrieved simply via evt.GetString(), but it is not documented.

        const wxRadioBox* radioBox = dynamic_cast<wxRadioBox*>(evt.GetEventObject());

        UpdateChoiceDisplayText(radioBox->GetString(evt.GetInt()));

    }
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        MyDialog().ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);

MatFox
In need of some credit
In need of some credit
Posts: 3
Joined: Mon May 18, 2020 8:32 am

Re: Pass a value from one class to another!

Post by MatFox » Mon May 18, 2020 4:44 pm

Hi PB,
many thanks for replying.
The ‘int’ in SetValue is obviously a typing error. In the actual code I use an expression like wxString mystring << pvalue. Sorry for that.
The basic idea was to create a module where I have a couple of 8 radiobuttons to be toggled individually i.e style wxRbSingle.
Afaik wxRadioBox does not provide this feature.
The code compiles fine as said, but nothing is written in the StaticBox.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2387
Joined: Sun Jan 03, 2010 5:45 pm

Re: Pass a value from one class to another!

Post by PB » Mon May 18, 2020 8:41 pm

It would be great if you copy-and-pasted the actual code instead of just randomly typing it in the post. Preferably in the same way I did: i.e., as short as possible with no irrelevant parts but still complete and compilable. For example, it is absolutely unclear what happens when you create an instance of A...

What I wrote before still stands, in particular the part about creating a new instance of A in the event handler. Just creating it every time the event is handled looks suspicious enough, but you even try to create a control without specifying its parent which seems quite odd? TBH, I do not really understand what is the code you posted supposed to do...

Anyway, whether you are using individual wxRadioButtons or wxRadioBox does not matter at all, the principle is still the same:

Code: Select all

#include <wx/wx.h>

#include <vector>

class MyDialog : public wxDialog
{
public:
    MyDialog(): wxDialog(nullptr, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
        std::vector<wxString> choices{"Red Pill", "Green Pill", "Blue Pill"};

        for ( const auto& label : choices )
        {
            wxRadioButton* radioButton = new wxRadioButton(this, wxID_ANY, label,
                wxDefaultPosition, wxDefaultSize, wxRB_SINGLE);
            radioButton->Bind(wxEVT_RADIOBUTTON, &MyDialog::OnRadioButton, this);
            mainSizer->Add(radioButton, wxSizerFlags().Expand().Border());
            m_radioButtons.push_back(radioButton);
        }
        m_radioButtons[0]->SetValue(true);

        mainSizer->AddSpacer(FromDIP(20));

        m_choiceDisplay = new wxStaticText(this, wxID_ANY, "");
        UpdateChoiceDisplayText(m_radioButtons[0]->GetLabelText());
        mainSizer->Add(m_choiceDisplay, wxSizerFlags().Center().DoubleBorder());

        SetInitialSize(FromDIP(wxSize(300, 200)));
        SetSizer(mainSizer);
    }
private:
    std::vector<wxRadioButton*> m_radioButtons;
    wxStaticText* m_choiceDisplay;

    void UpdateChoiceDisplayText(const wxString& choice)
    {
        m_choiceDisplay->SetLabel(wxString::Format("Your choice is '%s'.", choice));
    }

    void OnRadioButton(wxCommandEvent& evt)
    {
        wxString label;

        for ( auto& radioButton : m_radioButtons )
        {
            if ( radioButton->GetId() == evt.GetId() )
            {
                label = radioButton->GetLabelText();
                radioButton->SetValue(true);
            }
            else
                radioButton->SetValue(false);
        }

        UpdateChoiceDisplayText(label);
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        MyDialog().ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);

MatFox
In need of some credit
In need of some credit
Posts: 3
Joined: Mon May 18, 2020 8:32 am

Re: Pass a value from one class to another!

Post by MatFox » Tue May 19, 2020 5:22 pm

Here is the full code. It is a draft so please appologize the bit of a timbered layout. It compiles! What interests me is how the radiobuttons will show their labels in the textbox when activated.

Code: Select all

#include "Communicate.h"

Communicate::Communicate(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(290, 150) )
{

	wxMenu *arr[10];
	for (int i = 0; i < 8; i++)
	{ 
		arr[i] = new wxMenu();
	}
	
	menuBar = new wxMenuBar;		
		
	arr[0]->Append(wxID_EXIT, wxT("&Quit"), "Quit the program");
	arr[1]->Append(wxID_EDIT, wxT("&Quit"), "Edit the file");
	menuBar->Append(arr[0], wxT("&File"));
	menuBar->Append(arr[1], wxT("&Edit"));
	menuBar->Append(arr[2], wxT("&Help"));

	CreateStatusBar();
	SetStatusText("Welcome to the first app!");

	/*wxImage::AddHandler(new wxPNGHandler);
	wxBitmap exit(wxT("new.bmp"), wxBITMAP_TYPE_BMP);
	if (!exit.Ok())
	{
		wxMessageBox(wxT("Sorry, could not load the Bitmap file"));
		return;
	}*/
	
	/************ Toolbar ***********************************************/

	toolBar = CreateToolBar(wxSTAY_ON_TOP|wxBG_STYLE_TRANSPARENT);
	//toolBar->AddTool(wxID_EXIT, wxT("Exit application"), exit);
	wxComboBox* comboBox = new wxComboBox(toolBar, wxID_COMBOBOX);
	toolBar->AddSeparator();
	toolBar->AddControl(comboBox);

	/*********************************************************************/

	Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,	wxCommandEventHandler(Communicate::OnQuit));

	m_parent = new wxPanel(this, wxID_ANY);

	wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);

	wxPanel* m_lp = new wxPanel(m_parent);
	wxPanel* m_rp = new wxPanel(m_parent);
	m_lp->Show();
	hbox->Add(m_lp, 1, wxEXPAND | wxALL, 1);
	hbox->Add(m_rp, 1, wxEXPAND | wxALL, 1);

	m_parent->SetSizer(hbox);
	hbox->Fit(m_parent);

	MyRadioBox *m_rBox = new MyRadioBox(m_lp, 8, 250, 50, wxT("RadioBox1"));
	MyRadioBox *m_rBox2 = new MyRadioBox(m_lp, 8, 350, 50, wxT("RadioBox2"));
	MyRadioBox *m_rBox3 = new MyRadioBox(m_lp, 8, 350, 50, wxT("RadioBox3"));


	/********** set up the sizer for the right hand panel ************/
		
		wxBoxSizer* topLevel = new wxBoxSizer(wxVERTICAL);

		// make a static box
		wxStaticBox* staticBox = new wxStaticBox(m_rp, wxID_STATIC, wxT("&Static Box"));

		// make static box sizer
		wxStaticBoxSizer* staticSizer = new wxStaticBoxSizer(staticBox, wxVERTICAL);

		// add the static sizer to the box sizer
		topLevel->Add(staticSizer, 1, wxALIGN_LEFT | wxALL, 10);

		// make a text control box
		textctrl = new wxTextCtrl(m_rp, -1, wxT(""), wxDefaultPosition, wxSize(250, 150), wxTE_MULTILINE),
		
		// add the text control to the static sizer
		staticSizer->Add(textctrl,
			1,				  // make vertically strechable
			wxEXPAND | wxALL, // make horizontally strechable and border all around
			10);

		m_rp->SetSizer(topLevel);
		topLevel->Fit(m_rp);
		topLevel->SetSizeHints(m_rp);
		/*****************************************************************
		 *
		 *		 arrange widgets in lefthand panel 
		 *                                                               
		/*********  the RadioBox    *************************************/
		
		for (unsigned int i = 0; i < 8; i++) // with the Labels 
		{
			mystring << i;
			choices.Add(mystring);
			mystring = "";
		}

		m_radiobox = new wxRadioBox(m_lp, wxID_ANY, wxT("RadioBox"), wxPoint(50, 50), wxDefaultSize, choices, 0, wxEXPAND | wxRA_VERTICAL | wxRB_SINGLE | wxSIZE_AUTO_WIDTH);

		/*******  and the RadioButton groups ****/
		wxBoxSizer* tLevel = new wxBoxSizer(wxHORIZONTAL);
		wxStaticBox *tBox = new wxStaticBox(m_lp, wxID_ANY, wxT("TextBox"));
		wxStaticBoxSizer *box = new wxStaticBoxSizer(tBox, wxHORIZONTAL);
		m_textBox = new wxStaticText(m_lp, wxID_ANY, _("50"), wxDefaultPosition, wxDefaultSize , wxALIGN_CENTER);
		box->Add(m_textBox, 1, wxEXPAND | wxALL, 5);

		/******** add the widgets to the sizer  *********/
		tLevel->Add(m_radiobox, 1, wxALIGN_LEFT | wxALL, 10);
		tLevel->Add(m_rBox2->radButSizer, 1, wxALIGN_TOP | wxALL, 10);		
		tLevel->Add(m_rBox->radButSizer, 1, wxALIGN_CENTER | wxALL, 10);
		tLevel->Add(m_rBox3->radButSizer, 1, wxALIGN_BOTTOM | wxALL, 10);

		tLevel->Add(box,
			1,
			wxALIGN_LEFT | wxALL,
			10);						

		m_lp->SetSizer(tLevel);
		tLevel->Fit(m_lp);
		/***********************************************************************/
		MyRadioBox* mBox;
		mBox->counter;
		wsprintf(str, L"Id(Communicate)  = %d\n",  mBox->counter);
		OutputDebugString(str);
		mystring << MyRadioBox::counter;
		//textBox->SetLabel((TCHAR)m_rBox->tvalue);
		m_textBox->SetLabel( mystring );
		//textBox->SetLabel("100")
	toolBar->Realize();	
	SetMenuBar(menuBar);
	SetToolBar(toolBar);

	this->Centre();
}

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
	Communicate *communicate = new Communicate(wxT("Widgets communicate"));
	communicate->Show(true);
	return true;
}

and the .h-file

#pragma once
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/x.h>
#endif // !WX_PRECOMP

#define wxID_COMBOBOX 510

class Communicate : public wxFrame
{
public:	
	
	Communicate(const wxString& title);
	
	wxRadioBox* m_radiobox;
	wxMenuBar* menuBar;
	wxToolBar* toolBar;
	wxMenu *file, *edit, *help;
	//LeftPanel*  m_lp; 
	//LeftPanel *m_lp = new LeftPanel(this);
	//RightPanel *m_rp;
	wxPanel *m_parent;
	wxString mystring;
	wxArrayString choices;
	int n;	
	//wxStaticText* m_textBox = new wxStaticText(m_lp, wxID_ANY, "");
	
private:
	wxTextCtrl *textctrl;
	wxStaticText* m_textBox;
	
	void aFunc()
	{
		Close(true);
	}
	void OnQuit(wxCommandEvent& event) { aFunc(); }
	TCHAR str[100];
	int i;
};

class MyRadioBox : public wxRadioButton
{
public:

	MyRadioBox() {};
	MyRadioBox(wxWindow *parent, int n, int x, int y, const wxString& kLabel)
	{		
		dx = x;
		dy = y;	
		
		style = wxRB_SINGLE | wxRB_GROUP;
		radButBox = new wxStaticBox(parent, wxID_ANY, kLabel);
		radButSizer = new wxStaticBoxSizer(radButBox, wxVERTICAL);
		for (i = 0; i < n; i++)
		{
			if (i > 0) style = wxRB_GROUP;
			mystring << i;
			choices.Add(mystring);
			m_radioBox[i] = static_cast<MyRadioBox*>(new wxRadioButton(parent, 50 + i, mystring, wxPoint(dx, dy * (i + 1)), wxDefaultSize, style));

			radButSizer->Add(m_radioBox[i]);
			mystring = "";
			m_radioBox[i]->SetValue(false);
			m_radioBox[i]->Bind
			(
				wxEVT_RADIOBUTTON, [=](wxCommandEvent& event)
				{
					// any other code here ...
					//Communicate::tvalue = event.GetId();
					//mystring << Communicate::tvalue;

					MyRadioBox::pvalue = event.GetId();
					mystring << pvalue;			
					
					//k->textBox->SetLabel(mystring);
					wsprintf(str, L"Id(MyRadioBox) = %d\n",MyRadioBox::pvalue);
					OutputDebugString(str);					
					onRadioButton();
				} // Lambda
			); // Bind
			
		}
	} // constructor
	
	wxStaticBoxSizer* radButSizer;
	static int counter;
	static int pvalue;
	Communicate* c;

	void onRadioButton() {
		
		++counter;
		wsprintf(str, L"Id(MyRadioBox) = %d\n", counter);
		//wsprintf(str, L"Id(MyRadioBox) = %d\n", tvalue);
		OutputDebugString(str);
		
	}

	
private:	
	int n, i;	
	int ident[10];
	long style;
	int dx, dy;
	TCHAR str[100];
	MyRadioBox *m_radioBox[10];
	wxString mystring;
	wxArrayString choices;
	wxStaticBox* radButBox;
		
	void buttonToggle() { wxMessageBox(wxT("Hier"), wxT("RadioButton"), wxOK | wxICON_INFORMATION); }
};

int MyRadioBox::pvalue;
int MyRadioBox::counter;

class  MyApp : public wxApp
{
public:
	virtual bool OnInit();
};
Best wishes
Last edited by DavidHart on Tue May 19, 2020 6:27 pm, edited 1 time in total.
Reason: Added code-tags

Post Reply