I have a dialog window which features some dynamic controls. Basically, upon construction I pass it a pointer to a structure, within this structure is a container of std::pair<wxString,wxString>. For each of these, I need another row of three controls to be created, a wxTextCtrl, wxChoice and a wxButton.
This part works, based on the available items in the container, I successfully create these upon dialog construction. I also use a wxTextValidator to connect the wxTextCtrl with the first wxString in the pair. So if there's three pairs in the container, I'd have three wxTextCtrls created, and each has a validator to it's respective wxString.
Upon wxID_OK of the dialog, the text validators work and my original structure, which I passed to it as a pointer, contains the correct data.
However, I've also added a button to my dialog which should allow the creation of new std::pair<wxString,wxString> records in the container. If I do this, upon wxID_OK, the app crashes. DrMingW makes it appear that the pointer to the wxString is invalid, but that can't be possible because I'm creating a new record in my container when the button is clicked, and pointing the wxTextValidator to this newly created record. It's stored outside the dialog so it isn't being invalidated upon closing the dialog.
My Data Structure:
struct StoryNodeData
{
wxString title;
wxString text;
std::vector<std::pair<wxString,wxString>> options;
};
My Dialog header:
#ifndef STORYDIALOG_H
#define STORYDIALOG_H
#include "flowchart.hpp"
#include <map>
//(*Headers(StoryDialog)
#include <wx/bmpbuttn.h>
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/dialog.h>
#include <wx/gbsizer.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
//*)
class StoryDialog: public wxDialog
{
public:
StoryDialog(wxWindow* parent,StoryNodeData* data, wxArrayString titles,wxWindowID id=wxID_ANY,const wxPoint& pos=wxDefaultPosition,const wxSize& size=wxDefaultSize);
virtual ~StoryDialog();
void HandleOptionDelete(wxCommandEvent& e);
//(*Declarations(StoryDialog)
wxButton* OptionButton;
wxFlexGridSizer* OptionsSizer;
wxScrolledWindow* OptionsWindow;
wxTextCtrl* EventTextCtrl;
wxTextCtrl* TitleTextCtrl;
//*)
protected:
//(*Identifiers(StoryDialog)
static const long ID_TEXTCTRL1;
static const long ID_TEXTCTRL2;
static const long ID_BUTTON1;
static const long ID_TEXTCTRL3;
static const long ID_CHOICE1;
static const long ID_BITMAPBUTTON1;
static const long ID_SCROLLEDWINDOW1;
//*)
private:
//(*Handlers(StoryDialog)
void OnNewOptionButtonClick(wxCommandEvent& event);
void OnBitmapButton1Click(wxCommandEvent& event);
//*)
std::map<wxObject*,std::tuple<wxTextCtrl*, wxChoice*, std::size_t>> m_optionCtrls;
StoryNodeData* m_data;
wxArrayString m_titles;
void ConstructOption(wxString* text, wxString* title);
DECLARE_EVENT_TABLE()
};
#endif
And the dialog implementation:
#include "StoryDialog.h"
#include <wx/artprov.h>
#include <wx/valgen.h>
//(*InternalHeaders(StoryDialog)
#include <wx/artprov.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/intl.h>
#include <wx/string.h>
//*)
//(*IdInit(StoryDialog)
const long StoryDialog::ID_TEXTCTRL1 = wxNewId();
const long StoryDialog::ID_TEXTCTRL2 = wxNewId();
const long StoryDialog::ID_BUTTON1 = wxNewId();
const long StoryDialog::ID_TEXTCTRL3 = wxNewId();
const long StoryDialog::ID_CHOICE1 = wxNewId();
const long StoryDialog::ID_BITMAPBUTTON1 = wxNewId();
const long StoryDialog::ID_SCROLLEDWINDOW1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(StoryDialog,wxDialog)
//(*EventTable(StoryDialog)
//*)
END_EVENT_TABLE()
StoryDialog::StoryDialog(wxWindow* parent,StoryNodeData* data, wxArrayString titles,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
//(*Initialize(StoryDialog)
wxBitmapButton* BitmapButton1;
wxChoice* Choice1;
wxFlexGridSizer* FlexGridSizer1;
wxGridBagSizer* GridBagSizer1;
wxStaticBoxSizer* StaticBoxSizer1;
wxStdDialogButtonSizer* StdDialogButtonSizer1;
wxTextCtrl* TextCtrl1;
Create(parent, wxID_ANY, _("New Event"), wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP|wxCAPTION|wxRESIZE_BORDER|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxSIMPLE_BORDER, _T("wxID_ANY"));
GridBagSizer1 = new wxGridBagSizer(0, 0);
GridBagSizer1->AddGrowableCol(0);
GridBagSizer1->AddGrowableRow(1);
TitleTextCtrl = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE,&data->title), _T("ID_TEXTCTRL1"));
GridBagSizer1->Add(TitleTextCtrl, wxGBPosition(0, 0), wxDefaultSpan, wxALL|wxEXPAND, 5);
EventTextCtrl = new wxTextCtrl(this, ID_TEXTCTRL2, wxEmptyString, wxDefaultPosition, wxSize(259,138), wxTE_MULTILINE|wxVSCROLL, wxTextValidator(wxFILTER_NONE,&data->text), _T("ID_TEXTCTRL2"));
GridBagSizer1->Add(EventTextCtrl, wxGBPosition(1, 0), wxDefaultSpan, wxALL|wxEXPAND, 5);
StdDialogButtonSizer1 = new wxStdDialogButtonSizer();
StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_OK, wxEmptyString));
StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));
StdDialogButtonSizer1->Realize();
GridBagSizer1->Add(StdDialogButtonSizer1, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5);
StaticBoxSizer1 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Options"));
FlexGridSizer1 = new wxFlexGridSizer(2, 1, 0, 0);
FlexGridSizer1->AddGrowableCol(0);
FlexGridSizer1->AddGrowableRow(1);
OptionButton = new wxButton(this, ID_BUTTON1, _("New Option"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
FlexGridSizer1->Add(OptionButton, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
OptionsWindow = new wxScrolledWindow(this, ID_SCROLLEDWINDOW1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxVSCROLL, _T("ID_SCROLLEDWINDOW1"));
OptionsSizer = new wxFlexGridSizer(0, 3, 0, 0);
OptionsSizer->AddGrowableCol(0);
TextCtrl1 = new wxTextCtrl(OptionsWindow, ID_TEXTCTRL3, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL3"));
OptionsSizer->Add(TextCtrl1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Choice1 = new wxChoice(OptionsWindow, ID_CHOICE1, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1"));
OptionsSizer->Add(Choice1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
BitmapButton1 = new wxBitmapButton(OptionsWindow, ID_BITMAPBUTTON1, wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator, _T("ID_BITMAPBUTTON1"));
OptionsSizer->Add(BitmapButton1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
OptionsWindow->SetSizer(OptionsSizer);
OptionsSizer->Fit(OptionsWindow);
OptionsSizer->SetSizeHints(OptionsWindow);
FlexGridSizer1->Add(OptionsWindow, 1, wxALL|wxEXPAND, 5);
StaticBoxSizer1->Add(FlexGridSizer1, 1, wxEXPAND, 5);
GridBagSizer1->Add(StaticBoxSizer1, wxGBPosition(0, 1), wxGBSpan(2, 1), wxALL|wxEXPAND, 5);
SetSizer(GridBagSizer1);
GridBagSizer1->Fit(this);
GridBagSizer1->SetSizeHints(this);
Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&StoryDialog::OnNewOptionButtonClick);
//*)
OptionsWindow->SetScrollRate(5,5);
OptionsWindow->DestroyChildren();
Bind(wxEVT_BUTTON, &StoryDialog::HandleOptionDelete, this);
m_data = data;
m_titles = titles;
// construct the existing options
for(auto itr = m_data->options.begin(); itr != m_data->options.end(); ++itr)
{
auto title = &((*itr).first);
auto text = &((*itr).second);
ConstructOption(text,title);
}
}
StoryDialog::~StoryDialog()
{
//(*Destroy(StoryDialog)
//*)
}
void StoryDialog::HandleOptionDelete(wxCommandEvent& e)
{
auto b = e.GetEventObject();
auto itr = m_optionCtrls.find(b);
if(m_optionCtrls.end() != itr)
{
auto button = itr->first;
auto pa = itr->second;
m_optionCtrls.erase(itr);
OptionsSizer->Detach(std::get<0>(pa));
OptionsSizer->Detach(std::get<1>(pa));
OptionsSizer->Detach(reinterpret_cast<wxBitmapButton*>(button));
std::get<0>(pa)->Destroy();
std::get<1>(pa)->Destroy();
reinterpret_cast<wxBitmapButton*>(button)->Destroy();
auto index = std::get<2>(pa);
auto itr = m_data->options.begin() + index;
m_data->options.erase(itr);
}
OptionsSizer->Layout();
OptionsWindow->SetSizer(OptionsSizer);
SendSizeEvent();
e.Skip(true);
}
void StoryDialog::OnNewOptionButtonClick(wxCommandEvent& event)
{
m_data->options.push_back(std::make_pair("",""));
auto itr = m_data->options.end()-1;
auto text = &((*(itr)).second);
auto title = &((*(itr)).first);
ConstructOption(text,title);
}
void StoryDialog::ConstructOption(wxString* text, wxString* title)
{
long tId = wxNewId();
long cId = wxNewId();
long bId = wxNewId();
auto optionTextCtrl = new wxTextCtrl(OptionsWindow, tId, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE,text));
OptionsSizer->Add(optionTextCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
auto optionTitleCtrl = new wxChoice(OptionsWindow, cId, wxDefaultPosition, wxDefaultSize, m_titles, 0, wxGenericValidator(title));
OptionsSizer->Add(optionTitleCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
auto deleteButtonCtrl = new wxBitmapButton(OptionsWindow, bId, wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator);
OptionsSizer->Add(deleteButtonCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
OptionsSizer->Layout();
OptionsWindow->SetSizer(OptionsSizer);
SendSizeEvent();
m_optionCtrls[deleteButtonCtrl] = std::make_tuple(optionTextCtrl,optionTitleCtrl,m_optionCtrls.size()-1);
}
You'll note that the way I create the dynamic controls is the same regardless of whether it's based on the data provided, or the user adding new data through the controls. The only difference is when adding new ones, I first create the records in the container
Pointers to elements of std::vector<> can (and will) be invalidated when the vector contents changes, e.g. when you append more elements to it, so you can't do it like this.
Instead you need to use a container that is not going to move its values (e.g. std::[unordered_]map<>) or store unique_ptr<>s in your vector.
Related
I am following the Hello World tutorial for WxSmith using CodeBlocks 20.03 and wxWidgets 3.1 in Ubuntu 20.04. This is later confirmed to also happen in Windows 10 using the same CodeBlocks and wxWidgets. I have it working up to this point:
Search for border size and change it from 5 to 0.
So far, the Resource view is as follows:
Moving on:
Since we will also use sizers to manage items added into wxPanel, we have to repeat the addition of wxBoxSize into wxPanel. After the sizer is in its place, switch back into the Standard tab on the palette and add a wxStaticText control.
What I understand is that I have to add another wxBoxsizer into the wxPanel object, and put a wxStaticText object into it. I then build the code using the gear button, which gives no error. Then I run it with the play button, and it throws an error:
I would like to ask what I have done wrong. This video doesn't have the outer wxBoxSizer and it works.
I would like to ask what I have done wrong, and how I can make it work according to the tutorial?
Further scouring the web shows someone running into this exact problem more than 9 years ago here. This is failing code from me:
/***************************************************************
* Name: testMain.cpp
* Purpose: Code for Application Frame
* Author: ()
* Created: 2022-12-27
* Copyright: ()
* License:
**************************************************************/
#include "wx_pch.h"
#include "testMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(testFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(testFrame)
const long testFrame::ID_STATICTEXT1 = wxNewId();
const long testFrame::ID_BUTTON1 = wxNewId();
const long testFrame::ID_PANEL1 = wxNewId();
const long testFrame::idMenuQuit = wxNewId();
const long testFrame::idMenuAbout = wxNewId();
const long testFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(testFrame,wxFrame)
//(*EventTable(testFrame)
//*)
END_EVENT_TABLE()
testFrame::testFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(testFrame)
wxBoxSizer* BoxSizer1;
wxBoxSizer* BoxSizer2;
wxMenu* Menu1;
wxMenu* Menu2;
wxMenuBar* MenuBar1;
wxMenuItem* MenuItem1;
wxMenuItem* MenuItem2;
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxSize(960,320), wxTAB_TRAVERSAL, _T("ID_PANEL1"));
BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
StaticText1 = new wxStaticText(Panel1, ID_STATICTEXT1, _("Label"), wxDefaultPosition, wxSize(120,60), 0, _T("ID_STATICTEXT1"));
BoxSizer2->Add(StaticText1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button1 = new wxButton(Panel1, ID_BUTTON1, _("Label"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
BoxSizer2->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Panel1->SetSizer(BoxSizer2);
SetSizer(BoxSizer2);
Layout();
BoxSizer1->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(BoxSizer1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
BoxSizer1->Fit(this);
BoxSizer1->SetSizeHints(this);
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnAbout);
//*)
}
testFrame::~testFrame()
{
//(*Destroy(testFrame)
//*)
}
void testFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void testFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
And this is the working code from that link:
#include "wx_pch.h"
#include "testMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(testFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(testFrame)
const long testFrame::ID_STATICTEXT1 = wxNewId();
const long testFrame::ID_BUTTON1 = wxNewId();
const long testFrame::ID_PANEL1 = wxNewId();
const long testFrame::idMenuQuit = wxNewId();
const long testFrame::idMenuAbout = wxNewId();
const long testFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(testFrame,wxFrame)
//(*EventTable(testFrame)
//*)
END_EVENT_TABLE()
testFrame::testFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(testFrame)
wxBoxSizer* BoxSizer1;
wxBoxSizer* BoxSizer2;
wxMenu* Menu1;
wxMenu* Menu2;
wxMenuBar* MenuBar1;
wxMenuItem* MenuItem1;
wxMenuItem* MenuItem2;
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
SetClientSize(wxSize(491,450));
BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
StaticText1 = new wxStaticText(Panel1, ID_STATICTEXT1, _("Label"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
BoxSizer2->Add(StaticText1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button1 = new wxButton(Panel1, ID_BUTTON1, _("Label"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
BoxSizer2->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Panel1->SetSizer(BoxSizer2);
BoxSizer2->Fit(Panel1);
BoxSizer2->SetSizeHints(Panel1);
BoxSizer1->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(BoxSizer1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
SetSizer(BoxSizer1);
Layout();
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnAbout);
//*)
}
testFrame::~testFrame()
{
//(*Destroy(testFrame)
//*)
}
void testFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void testFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
Comparing the two, the root of the problem is from these 4 lines (working code on the right):
The code works after commenting out the 4 lines on the left, and copying the ones on the right over. Now it appears that these lines set the relationships between elements. Could someone explain to me what they mean (right and wrong), and what I can do to get the correct ones generated? I followed the instructions the best I can, and apparently something was not done right. The working code has THE SAME graphical layout as mine. Only the generated code is different in crucial places. I couldn't find any more detailed video or instructions that could help getting it right in the first place.
After adding the first swBoxSizer and the wxPanel, this is what is shown in the preview window:
The tiny object induces me to set the size to the wxPanel object to make it visible and easy to work on. However this triggers a change in the generated code. The panel's size is no longer wxDefaultSize but wxSize(960,320) as seen in the failing code above. In order to avoid this, I must not change the size and use the tool Insert new widgets into current selection which looks like this:
After that, another swBoxSizer and swStaticText are added sequentially. swButton is added last using the original Insert new widget by pointing with mouse tool.
This is the working code that is generated:
#include "wx_pch.h"
#include "testMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(testFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(testFrame)
const long testFrame::ID_STATICTEXT1 = wxNewId();
const long testFrame::ID_BUTTON1 = wxNewId();
const long testFrame::ID_PANEL1 = wxNewId();
const long testFrame::idMenuQuit = wxNewId();
const long testFrame::idMenuAbout = wxNewId();
const long testFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(testFrame,wxFrame)
//(*EventTable(testFrame)
//*)
END_EVENT_TABLE()
testFrame::testFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(testFrame)
wxBoxSizer* BoxSizer1;
wxBoxSizer* BoxSizer2;
wxMenu* Menu1;
wxMenu* Menu2;
wxMenuBar* MenuBar1;
wxMenuItem* MenuItem1;
wxMenuItem* MenuItem2;
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
StaticText1 = new wxStaticText(Panel1, ID_STATICTEXT1, _("Label"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
BoxSizer2->Add(StaticText1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button1 = new wxButton(Panel1, ID_BUTTON1, _("Label"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
BoxSizer2->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Panel1->SetSizer(BoxSizer2);
BoxSizer2->Fit(Panel1);
BoxSizer2->SetSizeHints(Panel1);
BoxSizer1->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(BoxSizer1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
BoxSizer1->Fit(this);
BoxSizer1->SetSizeHints(this);
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testFrame::OnAbout);
//*)
}
testFrame::~testFrame()
{
//(*Destroy(testFrame)
//*)
}
void testFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void testFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
This is a pitfall that can discourage beginners trying to learn the framework. I hope this will help anybody who finds this post.
I know that our questions put on evidence our knowledge, so be gentle please :). This is one of mine in C++. Well, here we go.
I'm trying to change from codeblocks the font of a StaticBoxSizer. I can change the font of the wxStaticBox in the properties section but I'm having a hard time finding a way to access the same thing for the wxStaticBoxSizer FROM wxSmith in codeBlocks.
I tried without success to acces the staticBox within the sizer. What's worst, i dont know how to access any of the wxSmith's elements from the code editor.
All hints are welcomed and thank you in advance.
Edit:
I know for sure that there's nothing wrong with the IDE but here's the header and here the cpp.
I noticed that the sizers are not declared in the headers but in the constructor's implementation of the dialog. I try to access the sizer in the constructor but to no avail.
The links works to me but here are the contents of the files directly. I simplified the code to include the minimum of elements.
header:
/***************************************************************
* Name: sizerTestMain.h
* Purpose: Defines Application Frame
* Author: RainMaker ()
* Created: 2015-11-11
* Copyright: RainMaker ()
* License:
**************************************************************/
#ifndef SIZERTESTMAIN_H
#define SIZERTESTMAIN_H
//(*Headers(sizerTestFrame)
#include <wx/sizer.h>
#include <wx/menu.h>
#include <wx/button.h>
#include <wx/frame.h>
#include <wx/statusbr.h>
//*)
class sizerTestFrame: public wxFrame
{
public:
sizerTestFrame(wxWindow* parent,wxWindowID id = -1);
virtual ~sizerTestFrame();
private:
//(*Handlers(sizerTestFrame)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnButton1Click(wxCommandEvent& event);
void OnButton3Click(wxCommandEvent& event);
//*)
//(*Identifiers(sizerTestFrame)
static const long ID_BUTTON1;
static const long ID_BUTTON2;
static const long ID_BUTTON3;
static const long idMenuQuit;
static const long idMenuAbout;
static const long ID_STATUSBAR1;
//*)
//(*Declarations(sizerTestFrame)
wxButton* Button1;
wxButton* Button2;
wxButton* Button3;
wxStatusBar* StatusBar1;
//*)
DECLARE_EVENT_TABLE()
};
#endif // SIZERTESTMAIN_H
and this is the cpp
/***************************************************************
* Name: sizerTestMain.cpp
* Purpose: Code for Application Frame
* Author: RainMaker ()
* Created: 2015-11-11
* Copyright: RainMaker ()
* License:
**************************************************************/
#include "wx_pch.h"
#include "sizerTestMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(sizerTestFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(sizerTestFrame)
const long sizerTestFrame::ID_BUTTON1 = wxNewId();
const long sizerTestFrame::ID_BUTTON2 = wxNewId();
const long sizerTestFrame::ID_BUTTON3 = wxNewId();
const long sizerTestFrame::idMenuQuit = wxNewId();
const long sizerTestFrame::idMenuAbout = wxNewId();
const long sizerTestFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(sizerTestFrame,wxFrame)
//(*EventTable(sizerTestFrame)
//*)
END_EVENT_TABLE()
sizerTestFrame::sizerTestFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(sizerTestFrame)
wxMenuItem* MenuItem2;
wxMenuItem* MenuItem1;
wxMenu* Menu1;
wxStaticBoxSizer* theSizer;
wxMenuBar* MenuBar1;
wxFlexGridSizer* FlexGridSizer1;
wxMenu* Menu2;
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
FlexGridSizer1 = new wxFlexGridSizer(0, 3, 0, 0);
theSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("I want to change this title"));
Button1 = new wxButton(this, ID_BUTTON1, _("with this"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
theSizer->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button2 = new wxButton(this, ID_BUTTON2, _("or this"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
theSizer->Add(Button2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
FlexGridSizer1->Add(theSizer, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button3 = new wxButton(this, ID_BUTTON3, _("Or this"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON3"));
FlexGridSizer1->Add(Button3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(FlexGridSizer1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
FlexGridSizer1->Fit(this);
FlexGridSizer1->SetSizeHints(this);
Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&sizerTestFrame::OnButton1Click);
Connect(ID_BUTTON3,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&sizerTestFrame::OnButton3Click);
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&sizerTestFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&sizerTestFrame::OnAbout);
//*)
}
sizerTestFrame::~sizerTestFrame()
{
//(*Destroy(sizerTestFrame)
//*)
}
void sizerTestFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void sizerTestFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
void sizerTestFrame::OnButton1Click(wxCommandEvent& event)
{
}
void sizerTestFrame::OnButton3Click(wxCommandEvent& event)
{
}
I solved my problem ! !
This is what did.
1 - I noticed that the sizer was not included in the header so I looked for the ways to include it from wxSmith. The magic came from the "isMember" checkBox in the properties table. It seems that this is the way of including it to the header and then accessing it.
2 - I created a member function at the end of the constructor:
void IbDialogue::setFonts();
3 - In the function implementation, I accessed the wxStaticBox of the wxStaticBoxSizer and set it like this:
wxFont* nf = new wxFont;
StaticBoxSizer7->GetStaticBox()->SetFont(nf->Bold());
And VOILĂ€ the font is mastered ! ! !
for (int i=0; i<1000000; i++)
cout<<(HA HA HA HA);
I pretend to "grab" and process the events: EVT_TEXT from wxTextCtrl and EVT_BUTTON from wxID_APPLY.
I try handling the events with Event Tables and I can't? Why?
The source code:
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class Dialog : public wxDialog
{
public:
Dialog(wxWindow *parent, const wxString &title);
private:
void OnNameChange(wxCommandEvent &event);
void OnApply(wxCommandEvent &event);
wxDECLARE_EVENT_TABLE();
wxTextCtrl *m_name;
};
enum
{
ID_NAME = 1
};
Dialog::Dialog(wxWindow *parent, const wxString &title) :
wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
SetSizer(vbox);
wxFlexGridSizer *flexGrid = new wxFlexGridSizer(2, 2, 5, 5);
wxStaticText *label = new wxStaticText(this, wxID_ANY, "&Name:");
flexGrid->Add(label);
m_name = new wxTextCtrl(this, ID_NAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
flexGrid->Add(m_name, 1, wxEXPAND);
label = new wxStaticText(this, wxID_ANY, "&Description:");
flexGrid->Add(label);
m_description = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
flexGrid->Add(m_description, 1, wxEXPAND);
flexGrid->AddGrowableRow(1, 1);
flexGrid->AddGrowableCol(1, 1);
vbox->Add(flexGrid, 1, wxALL | wxEXPAND, 15);
vbox->Add(CreateSeparatedButtonSizer(wxAPPLY | wxCANCEL), 0, wxEXPAND | wxALL, 5);
}
void Dialog::OnNameChange(wxCommandEvent &event)
{
m_description->AppendText("Hello\n");
}
void Dialog::OnApply(wxCommandEvent &event)
{
m_description->AppendText("Apply\n");
}
wxBEGIN_EVENT_TABLE(Dialog, wxDialog)
EVT_TEXT(ID_NAME, Dialog::OnNameChange)
EVT_BUTTON(wxID_APPLY, Dialog::OnApply)
wxEND_EVENT_TABLE()
It's only possible to handle the events dynamically?
Bind(wxEVT_TEXT, &Dialog::OnNameChange, this, m_name->GetId());
The code as shown absolutely should work. It's not self-contained, so I can't test it, but there must be something else not shown here preventing it from working. Please try to make a SSCCE if you still can't isolate the problem yourself.
I have a trouble with adding 4 or more wxBoxSizer (or any other type of Sizer objects) in C++ GUI application. This is my first time creating a GUI application using wxWidgets and I am using Code::Blocks as the IDE. Please help me If anybody had this problem before and resolved it.
Below is the complete program.
Main frame class implementaions:
/***************************************************************
* Name: testWXWProjectMain.h
* Purpose: Defines Application Frame
* Author: test ()
* Created: 2014-01-22
* Copyright: test ()
* License:
**************************************************************/
#ifndef TESTWXWPROJECTMAIN_H
#define TESTWXWPROJECTMAIN_H
//(*Headers(testWXWProjectFrame)
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/menu.h>
#include <wx/panel.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
//*)
class testWXWProjectFrame: public wxFrame
{
public:
testWXWProjectFrame(wxWindow* parent,wxWindowID id = -1);
virtual ~testWXWProjectFrame();
private:
//(*Handlers(testWXWProjectFrame)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
//*)
//(*Identifiers(testWXWProjectFrame)
static const long ID_BUTTON1;
static const long ID_BUTTON2;
static const long ID_PANEL2;
static const long ID_PANEL1;
static const long ID_MENUITEM1;
static const long idMenuAbout;
static const long ID_STATUSBAR1;
//*)
//(*Declarations(testWXWProjectFrame)
wxPanel* Panel1;
wxStatusBar* StatusBar1;
wxButton* Button1;
wxButton* Button2;
wxPanel* Panel2;
//*)
DECLARE_EVENT_TABLE()
};
#endif // TESTWXWPROJECTMAIN_H
####################################################
/***************************************************************
* Name: testWXWProjectMain.cpp
* Purpose: Code for Application Frame
* Author: test ()
* Created: 2014-01-22
* Copyright: test ()
* License:
**************************************************************/
#include "testWXWProjectMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(testWXWProjectFrame)
#include <wx/string.h>
#include <wx/intl.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(testWXWProjectFrame)
const long testWXWProjectFrame::ID_BUTTON1 = wxNewId();
const long testWXWProjectFrame::ID_BUTTON2 = wxNewId();
const long testWXWProjectFrame::ID_PANEL2 = wxNewId();
const long testWXWProjectFrame::ID_PANEL1 = wxNewId();
const long testWXWProjectFrame::ID_MENUITEM1 = wxNewId();
const long testWXWProjectFrame::idMenuAbout = wxNewId();
const long testWXWProjectFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(testWXWProjectFrame,wxFrame)
//(*EventTable(testWXWProjectFrame)
//*)
END_EVENT_TABLE()
testWXWProjectFrame::testWXWProjectFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(testWXWProjectFrame)
wxMenuItem* MenuItem2;
wxMenuItem* MenuItem1;
wxBoxSizer* BoxSizer3;
wxMenu* Menu1;
wxBoxSizer* BoxSizer2;
wxBoxSizer* BoxSizer4;
wxBoxSizer* BoxSizer1;
wxMenuBar* MenuBar1;
wxMenu* Menu2;
Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
Panel2 = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxSize(236,171), wxTAB_TRAVERSAL, _T("ID_PANEL2"));
BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
Button1 = new wxButton(Panel2, ID_BUTTON1, _("button 1"), wxDefaultPosition, wxSize(121,27), 0, wxDefaultValidator, _T("ID_BUTTON1"));
BoxSizer4->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Button2 = new wxButton(Panel2, ID_BUTTON2, _("button2"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
BoxSizer4->Add(Button2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Panel2->SetSizer(BoxSizer4);
SetSizer(BoxSizer4);
Layout();
BoxSizer2->Add(Panel2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
BoxSizer1->Add(BoxSizer2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxSize(262,206), wxTAB_TRAVERSAL, _T("ID_PANEL1"));
BoxSizer3->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
BoxSizer1->Add(BoxSizer3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
SetSizer(BoxSizer1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, ID_MENUITEM1, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
BoxSizer1->Fit(this);
BoxSizer1->SetSizeHints(this);
Connect(ID_MENUITEM1,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testWXWProjectFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testWXWProjectFrame::OnAbout);
//*)
}
testWXWProjectFrame::~testWXWProjectFrame()
{
//(*Destroy(testWXWProjectFrame)
//*)
}
void testWXWProjectFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void testWXWProjectFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
Application class:
/***************************************************************
* Name: testWXWProjectApp.h
* Purpose: Defines Application Class
* Author: test ()
* Created: 2014-01-22
* Copyright: test ()
* License:
**************************************************************/
#ifndef TESTWXWPROJECTAPP_H
#define TESTWXWPROJECTAPP_H
#include <wx/app.h>
class testWXWProjectApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // TESTWXWPROJECTAPP_H
/***************************************************************
* Name: testWXWProjectApp.cpp
* Purpose: Code for Application Class
* Author: test ()
* Created: 2014-01-22
* Copyright: test ()
* License:
**************************************************************/
#include "testWXWProjectApp.h"
//(*AppHeaders
#include "testWXWProjectMain.h"
#include <wx/image.h>
//*)
IMPLEMENT_APP(testWXWProjectApp);
bool testWXWProjectApp::OnInit()
{
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
testWXWProjectFrame* Frame = new testWXWProjectFrame(0);
Frame->Show();
SetTopWindow(Frame);
}
//*)
return wxsOK;
}
Debug:
Adding source dir: /home/nisshanka/projects/codes/testWXWProject/
Adding source dir: /home/nisshanka/projects/codes/testWXWProject/
Adding file: /home/nisshanka/projects/codes/testWXWProject/bin/Debug/testWXWProject
Changing directory to: /home/nisshanka/projects/codes/testWXWProject/.
Set variable: LD_LIBRARY_PATH=.:/usr/local/lib:/usr/lib64:
Starting debugger: /usr/bin/gdb -nx -fullname -quiet -args /home/nisshanka/projects/codes/testWXWProject/bin/Debug/testWXWProject
done
Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector
Setting breakpoints
Debugger name and version: GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:26
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
Continuing...
Program received signal SIGSEGV, Segmentation fault.
In wxSizer::GetMinSize() () (/usr/local/lib/libwx_gtk2_core-2.8.so.0)
#20 0x0000000000409d06 in testWXWProjectApp::OnInit (this=0x630840) at /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
/home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27:626:beg:0x409d06
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
#20 0x0000000000409d06 in testWXWProjectApp::OnInit (this=0x630840) at /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
/home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27:626:beg:0x409d06
Continuing...
Program terminated with signal SIGSEGV, Segmentation fault.
Debugger finished with status 0
I tried with different sizers too but always giving the segmentation fault. if I use 3 sizers then it doesn't have any problem.
Thanks.
You can't set a sizer to multiple wxWindows. For example, in testWXWProjectFrame::testWXWProjectFrame, you have
Panel2->SetSizer(BoxSizer4);
SetSizer(BoxSizer4);
This will set the same sizer to Panel2, which is created as a child of the frame, and to the frame itself. Generally, you need to create one box sizer for each container (wxPanel, wxFrame) and associate that sizer with the container using wxWindow::SetSizer. Additionally, if a sizer is created for a particular container, e.g. Panel2, then only the children of Panel2 may be added to that sizer (or a sizer that itself only contains children of Panel2.
In your code, these relations are all mixed up. Also, why do you first set BoxSizer4 as the frame's sizer and then, at the end of the method, replace it with BoxSizer1?
I also suggest that you use meaningful names for your variables. It's quite hard to read the source code if it contains names like BoxSizer1 and Panel2. Additionally, I have sometimes found it helpful to write the control / sizer hierarchy as a tree like this:
Frame (BoxSizer4)
Panel2 (BoxSizer4)
Button1
Button2
Panel1 (BoxSizer3)
This makes it easier to check that you add the right controls to the right sizers, and set the sizers to the containers correctly. Here, you can quickly spot that BoxSizer4 is set to two controls where one is a child of the other - this will cause a crash such as the one you are seeing.
Hi I am am trying to catch mouse movements for a MouseOver function in an app created with Code::Blocks using the wxSmith plugin. I have stumbled upon a puzzling problem. EVT_MOUSEWHEEL calling the function in the EventTable works well, but all other macros have no result at all. And the mousewheel is not really want I want (I just used it to test...) This is for Windows.
Here is a the basic problem code (mostly generated by the fantastic wxSmith plugin)
MouseMain.h
#include <wx/frame.h>
#include <wx/statusbr.h>
//*)
class MouseFrame: public wxFrame
{
public:
MouseFrame(wxWindow* parent,wxWindowID id = -1);
virtual ~MouseFrame();
private:
//(*Handlers(MouseFrame)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnButton1Click(wxCommandEvent& event);
void MouseOver(wxMouseEvent& event);
//*)
//(*Identifiers(MouseFrame)
static const long ID_BUTTON1;
static const long ID_STATICBITMAP1;
static const long ID_PANEL1;
static const long idMenuQuit;
static const long idMenuAbout;
static const long ID_STATUSBAR1;
//*)
//(*Declarations(MouseFrame)
wxButton* Button1;
wxStaticBitmap* StaticBitmap1;
wxPanel* Panel1;
wxStatusBar* StatusBar1;
//*)
DECLARE_EVENT_TABLE()
};
#endif // MOUSEMAIN_H
...and MouseMain.cpp
#include "wx_pch.h"
#include "MouseMain.h"
#include <wx/msgdlg.h>
//(*InternalHeaders(MouseFrame)
#include <wx/bitmap.h>
#include <wx/intl.h>
#include <wx/image.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(MouseFrame)
const long MouseFrame::ID_BUTTON1 = wxNewId();
const long MouseFrame::ID_STATICBITMAP1 = wxNewId();
const long MouseFrame::ID_PANEL1 = wxNewId();
const long MouseFrame::idMenuQuit = wxNewId();
const long MouseFrame::idMenuAbout = wxNewId();
const long MouseFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(MouseFrame,wxFrame)
EVT_RIGHT_DCLICK(MouseFrame::MouseOver)
EVT_MOUSEWHEEL(MouseFrame::MouseOver)
EVT_MOTION(MouseFrame::MouseOver)
EVT_RIGHT_DOWN(MouseFrame::MouseOver)
//(*EventTable(MouseFrame)
//*)
END_EVENT_TABLE()
MouseFrame::MouseFrame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(MouseFrame)
wxMenuItem* MenuItem2;
wxMenuItem* MenuItem1;
wxMenu* Menu1;
wxMenuBar* MenuBar1;
wxFlexGridSizer* FlexGridSizer1;
wxMenu* Menu2;
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
Panel1 = new wxPanel(this, ID_PANEL1, wxPoint(144,392), wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
FlexGridSizer1 = new wxFlexGridSizer(0, 3, 0, 0);
Button1 = new wxButton(Panel1, ID_BUTTON1, _("TheButton"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
FlexGridSizer1->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
StaticBitmap1 = new wxStaticBitmap(Panel1, ID_STATICBITMAP1, wxNullBitmap, wxDefaultPosition, wxSize(159,189), wxSUNKEN_BORDER, _T("ID_STATICBITMAP1"));
FlexGridSizer1->Add(StaticBitmap1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
Panel1->SetSizer(FlexGridSizer1);
FlexGridSizer1->Fit(Panel1);
FlexGridSizer1->SetSizeHints(Panel1);
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&MouseFrame::OnButton1Click);
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&MouseFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&MouseFrame::OnAbout);
//*)
}
MouseFrame::~MouseFrame()
{
//(*Destroy(MouseFrame)
//*)
}
void MouseFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void MouseFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
void MouseFrame::OnButton1Click(wxCommandEvent& event)
{
}
void MouseFrame::MouseOver(wxMouseEvent& event){
wxMessageBox(_("MouseOver event!"));
}
MouseApp.h
#ifndef MOUSEAPP_H
#define MOUSEAPP_H
#include <wx/app.h>
class MouseApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // MOUSEAPP_H
So my big question:
Why are EVT_MOTION, EVT_RIGHT_DOWN or EVT_RIGHT_DCLICK not calling MouseFrame::MouseOver(wxMouseEvent& event) in the way EVT_MOUSEWHEEL does?
I figured it out: whenever you have one child of a wxFrame, wxWidgets automatically assumes you want it to cover the entire area of the wxFrame.
Because of this, there is no portion of the frame visible - hence none of the events make it to your handler.
As for solutions, you could always have the wxPanel handle the events.
Edit: Since you mentioned wxSmith, you could go to the events tab of the management pane {} and put the event handling code in the mouse events there instead of the wxFrame.