Hi,
I'm trying to develop a program with a main window and a dialog.
The general idea is that when I press a button in the dialog the text into a main window ctrltext changes.
I'm confused about how to bind the wxEVT_COMMAND_BUTTON_CLICKED with the main windows function/handler
Thanks for any feedback
Bind Dialog Event with a MainWindow handler Topic is solved
Re: Bind Dialog Event with a MainWindow handler
I personally would not do some crazy passing around variables and exposing the internals of a class.
I would introduce a new event, which would be generated by the dialog and handled in the frame.
It could look like this, where the code passes around an editable string between a wxFrame (MyFrame) and a wxDialog (MyDialog), where MyFrame is the parent of MyDialog shown modal:
1. Declare and define a new wxCommandEvent-derived event (wxUPDATE_FROM_MYDIALOG).
2. In the frame ctor, bind the new event to its handler (MyFrame::OnUpdateFromDialog()).
2. When the frame needs to be updated from the dialog, the dialog sends the new event (MyDialog::OnUpdateMainFrame()), with the string stored in the event.
It would be best to run the code, to see how it works.
I would introduce a new event, which would be generated by the dialog and handled in the frame.
It could look like this, where the code passes around an editable string between a wxFrame (MyFrame) and a wxDialog (MyDialog), where MyFrame is the parent of MyDialog shown modal:
1. Declare and define a new wxCommandEvent-derived event (wxUPDATE_FROM_MYDIALOG).
2. In the frame ctor, bind the new event to its handler (MyFrame::OnUpdateFromDialog()).
2. When the frame needs to be updated from the dialog, the dialog sends the new event (MyDialog::OnUpdateMainFrame()), with the string stored in the event.
Code: Select all
#include <wx/wx.h>
// should be in the header file
wxDECLARE_EVENT(wxUPDATE_FROM_MYDIALOG, wxCommandEvent);
// and this in the source file
wxDEFINE_EVENT(wxUPDATE_FROM_MYDIALOG, wxCommandEvent);
class MyDialog : public wxDialog
{
public:
MyDialog(wxWindow* parent, const wxString& value)
: wxDialog(parent, wxID_ANY, "MyDialog")
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
m_textCtrl = new wxTextCtrl(this, wxID_ANY, value);
mainSizer->Add(m_textCtrl, wxSizerFlags().Expand().DoubleBorder());
wxButton* button = new wxButton(this, wxID_ANY, "Update MyFrame");
button->Bind(wxEVT_BUTTON, &MyDialog::OnUpdateMainFrame, this);
mainSizer->Add(button, wxSizerFlags().Expand().DoubleBorder());
mainSizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Expand().DoubleBorder());
SetSizerAndFit(mainSizer);
}
wxString GetTextValue() const { return m_textCtrl->GetValue(); }
private:
wxTextCtrl* m_textCtrl;
void OnUpdateMainFrame(wxCommandEvent&)
{
wxCommandEvent event(wxUPDATE_FROM_MYDIALOG, GetId());
event.SetString(GetTextValue());
event.SetEventObject(this);
GetParent()->ProcessWindowEvent(event);
}
};
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(nullptr, wxID_ANY, "MyFrame")
{
wxPanel* mainPanel = new wxPanel(this);
wxBoxSizer* mainPanelSizer = new wxBoxSizer(wxVERTICAL);
m_textCtrl = new wxTextCtrl(mainPanel, wxID_ANY, "Change me");
mainPanelSizer->Add(m_textCtrl, wxSizerFlags().Expand().DoubleBorder());
wxButton* button = new wxButton(mainPanel, wxID_ANY, "Show MyDialog...");
button->Bind(wxEVT_BUTTON, &MyFrame::OnShowMyDialog, this);
mainPanelSizer->Add(button, wxSizerFlags().Expand().DoubleBorder());
mainPanel->SetSizer(mainPanelSizer);
Bind(wxUPDATE_FROM_MYDIALOG, &MyFrame::OnUpdateFromDialog, this);
}
private:
wxTextCtrl* m_textCtrl;
void OnShowMyDialog(wxCommandEvent&)
{
MyDialog dlg(this, m_textCtrl->GetValue());
if ( dlg.ShowModal() == wxID_OK )
m_textCtrl->SetValue(dlg.GetTextValue());
}
void OnUpdateFromDialog(wxCommandEvent& event)
{
m_textCtrl->SetValue(event.GetString());
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
Re: Bind Dialog Event with a MainWindow handler
Exactly what I was looking for. Great!
I really understood a lot of things better today
Thank you
I really understood a lot of things better today
Thank you
Re: Bind Dialog Event with a MainWindow handler
Hi,
This is all depends on whether you want to keep dialog open after the button press or close it and return the control to the main frame.
If you want the dialog to belosed and then update the text - you don't need any extra code.
And even if you don't - just call "GetParent()->GetTextCtrl()->SetValue()".
Something like this:
Thank you.
This is all depends on whether you want to keep dialog open after the button press or close it and return the control to the main frame.
If you want the dialog to belosed and then update the text - you don't need any extra code.
And even if you don't - just call "GetParent()->GetTextCtrl()->SetValue()".
Something like this:
Code: Select all
class MyDialog : public wxDialog
{
public:
MyDialog(wxWindow *parent, ...);
void OnButtonClick(wxCommandEvent &event);
private:
wxButton *myButton;
};
MyDialog::MyDialog(wxWindow *parent, ...) : wxDialog( parent, ... )
{
// Create all controls
Bind( wxEVT_BUTTON, &MyDialog::OnButtonClick, this );
}
void MyDialog::OnButtonClick(wxCommandEvent &event)
{
GetParent()->GetTextCtrl()->SetValue( "My new text" );
}
Code: Select all
class MyFrame : public wxFrame
{
public:
MyFrame(...);
wxTextCtrl *GetTextCtrl() { return m_textCtrl; };
private:
wxTextCtrl *m_textCtrl;
}
MyFrame::MyFrame(...) : public wxFrame
{
// Create all controls
}
Re: Bind Dialog Event with a MainWindow handler
This would not work. To make it work, one would have to make even tighter class coupling than in my code. A circular dependency where MyFrame and MyDialog are aware of each other must be introduced and then in the code fragment above wxWindow* returned by GetParent() must be cast to MyFrame*.
But it is simpler then my code and I guess often good enough.
Re: Bind Dialog Event with a MainWindow handler
@PB,
Yes - KISS principle.
And it is almost straightforward.
And if the OP doesn't need the dialog to remain open - the code will be even simpler.
Thank you.
Yes - KISS principle.
And it is almost straightforward.
And if the OP doesn't need the dialog to remain open - the code will be even simpler.
Thank you.
Re: Bind Dialog Event with a MainWindow handler
But it goes against principles of good software design, where tight class coupling is for obvious reasons undesirable. In fact, in a well written software, such scenarios are usually implemented using one of those Model-View-<something> patterns.
In programming, we should not strive for just for (deceivingly) simple. We should strive for working, efficient, and maintainable; where each of the three is important.
The above is just my two cents, and I am certainly no expert on anything.