I'm new to wxWidgets and I wanted to make a simple GUI application (on ubuntu) for reference.
I created a simple window, added some buttons and in a button event handler I want to update a wxStaticText
object's text on screen to indicate which button has been pressed.
However when I call the SetLabel
or SetLabelText
functions that wxStaticText
inherits, then I get a segmentation fault.
Maybe I'm missing something and wxStaticText is just not able to have their label set and I need another control. But I couldn't find anything like that in the class list.
I'm using wxWidgets 3.1.4 from the codelite repositories.
MainFrame.cpp
#include "MainFrame.h"
#include <iostream>
// segfaults/bugs with simple constants, needs to be static
static const char* TITLE;
const int MainFrame::PX = 30;
const int MainFrame::PY = 30;
const int MainFrame::SX = 400;
const int MainFrame::SY = 300;
MainFrame::MainFrame()
: wxFrame(nullptr, static_cast<wxWindowID>(IDs::MainFrame), wxString(TITLE), wxPoint(PX, PY), wxSize(SX, SY))
{
// create bar
// no need to call delete. new is overloaded for wx elements.
menuBar = new wxMenuBar();
// create menues
menuFile = new wxMenu();
// menuitems file
menuItemClose = new wxMenuItem(menuFile, static_cast<int>(IDs::MenuItemClose), "Exit", "Close the application");
Connect(menuItemClose->GetId(), wxEVT_MENU, wxCommandEventHandler(MainFrame::onClickMenuItemClose));
menuFile->Append(menuItemClose);
// construct menu bar from menues
menuBar->Append(menuFile, "File");
this->SetMenuBar(menuBar);
// misc
lbl_Text = new wxStaticText(this, wxID_ANY, "Press a button!");
// create sizers
gridSizer = new wxGridSizer(1, 5, wxSize(5,5));
boxSizer = new wxBoxSizer(wxVERTICAL);
boxSizer->Add(lbl_Text,
0, // make vectically un-stretchable
wxALL, // implicit top alignment, border all around
10 // border 10 px
);
boxSizer->Add(gridSizer, 1, wxEXPAND, 0);
this->SetSizerAndFit(boxSizer);
// create buttons
v_btn_Buttons = std::make_unique<std::vector<wxButton*>>(5);
for (int i = 0; i < 5; i++)
{
wxString txt = wxString(fmt::format("Button{0}", (i+1)).c_str());
std::cout << "Creating Button #" << i+1 << ", with label: " << txt << std::endl;
wxButton* btn = new wxButton(this, static_cast<int>(IDs::Button1) + i, txt);
btn->Connect(wxEVT_BUTTON, wxCommandEventHandler(MainFrame::onClickButton));
v_btn_Buttons->push_back(btn);
gridSizer->Add(btn);
}
}
MainFrame::~MainFrame()
{
}
void MainFrame::onClickMenuItemClose(wxCommandEvent& evt)
{
Close();
// no call of evt.Skip() because we're done with it.
}
void MainFrame::onClickButton(wxCommandEvent& evt)
{
wxString txt = wxString(fmt::format(
"Pressed Button #{0} (ID: {1})",
evt.GetId() - static_cast<int>(IDs::Button1),
evt.GetId()
));
lbl_Text->SetLabelText(txt);
}
MainFrame.h
#pragma once
#include "pch.h"
class MainFrame : public wxFrame
{
private:
// constants
const char* TITLE = "My awesome title!";
static const int PX;
static const int PY;
static const int SX;
static const int SY;
private:
// member variables
private:
// Layout and Windows
// layout using sizers
/*
* +-----------------+
* | MENU |
* +-----------------+
* |+---------------+|
* ||BoxSizer (col) ||
* ||TextLabel ||
* |+---------------+|
* ||+-------------+||
* |||GridSizer |||
* |||BTN|BTN|... |||
* ||+-------------+||
* |+---------------+|
* +-----------------+
*/
// wxMenuBar { wxMenu {wxMenuItem,...}, ... }
wxMenuBar* menuBar = nullptr;
wxMenu* menuFile = nullptr;
wxMenuItem* menuItemClose = nullptr;
wxBoxSizer* boxSizer = nullptr;
wxGridSizer* gridSizer = nullptr;
wxStaticText* lbl_Text = nullptr;
std::unique_ptr<std::vector<wxButton*>> v_btn_Buttons = nullptr;
protected:
// Event handlers
void onClickMenuItemClose(wxCommandEvent& evt);
void onClickButton(wxCommandEvent& evt);
public:
MainFrame();
virtual ~MainFrame();
// used to identify elements
// can be extracted from events
enum class IDs : wxWindowID
{
MainFrame = 10000,
MenuItemClose = 10100,
Button1 = 10500,
Button2,
Button3,
Button4,
Button5
};
};
pch.h:
#pragma once
#include <wx/wx.h>
#include <vector>
#include <memory> // smart pointers
// will be in c++20 as
// #include <format>
#include <fmt/format.h>
main.cpp
#include "pch.h"
#include "MainFrame.h"
// application class
class Main : public wxApp
{
public:
// function called at the application initialization
virtual bool OnInit();
};
IMPLEMENT_APP(Main);
bool Main::OnInit()
{
// create a new frame and set it as the top most application window
MainFrame* mainFrame = new MainFrame();
SetTopWindow(mainFrame);
// show main frame
mainFrame->Show();
// enter the application's main loop
return true;
}
Compiled with
/bin/sh -c '/usr/bin/make -j4 -e -f Makefile'
----------Building project:[ wxTest - Debug ]----------
make[1]: Entering directory '/home/paul/Documents/Projects/wxTest'
/usr/bin/g++-10 -c pch.h -I/usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.1-unofficial3 -I/usr/include/wx-3.1-unofficial -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread
pch.h:1:9: warning: #pragma once in main file
1 | #pragma once
| ^~~~
make[1]: Leaving directory '/home/paul/Documents/Projects/wxTest'
make[1]: Entering directory '/home/paul/Documents/Projects/wxTest'
/usr/bin/g++-10 -include pch.h -c "/home/paul/Documents/Projects/wxTest/MainFrame.cpp" -g -O0 -pedantic -W -std=c++20 -fcoroutines -Wall -I/usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.1-unofficial3 -I/usr/include/wx-3.1-unofficial -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread -o ../build-Debug/wxTest/MainFrame.cpp.o -I.
/usr/bin/g++-10 -include pch.h -c "/home/paul/Documents/Projects/wxTest/main.cpp" -g -O0 -pedantic -W -std=c++20 -fcoroutines -Wall -I/usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.1-unofficial3 -I/usr/include/wx-3.1-unofficial -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread -o ../build-Debug/wxTest/main.cpp.o -I.
/home/paul/Documents/Projects/wxTest/main.cpp:13:20: warning: extra ';' [-Wpedantic]
13 | IMPLEMENT_APP(Main);
| ^
/home/paul/Documents/Projects/wxTest/MainFrame.cpp: In member function 'void MainFrame::onClickMenuItemClose(wxCommandEvent&)':
/home/paul/Documents/Projects/wxTest/MainFrame.cpp:63:54: warning: unused parameter 'evt' [-Wunused-parameter]
63 | void MainFrame::onClickMenuItemClose(wxCommandEvent& evt)
| ~~~~~~~~~~~~~~~~^~~
/usr/bin/g++-10 -o ../build-Debug/bin/wxTest @../build-Debug/wxTest/ObjectsList.txt -L. -lfmt -L/usr/lib/x86_64-linux-gnu -pthread -lwx_gtk3u_unofficial3_xrc-3.1 -lwx_gtk3u_unofficial3_html-3.1 -lwx_gtk3u_unofficial3_qa-3.1 -lwx_gtk3u_unofficial3_core-3.1 -lwx_baseu_unofficial3_xml-3.1 -lwx_baseu_unofficial3_net-3.1 -lwx_baseu_unofficial3-3.1
make[1]: Leaving directory '/home/paul/Documents/Projects/wxTest'
====0 errors, 3 warnings, total time: 00:00:18 seconds====
I get the following stacktrace when I click a button:
0 0x0000555555950050 ??
1 0x0000555555566e85 MainFrame::onClickButton /home/paul/Documents/Projects/wxTest/MainFrame.cpp 77
2 0x00007ffff758f091 wxEvtHandler::ProcessEventIfMatchesId /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../include/wx/app.h 462
3 0x00007ffff758f091 wxEvtHandler::ProcessEventIfMatchesId /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1400
4 0x00007ffff758f52e wxEvtHandler::SearchDynamicEventTable /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1897
5 0x00007ffff758f8b4 wxEvtHandler::TryHereOnly /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1618
6 0x00007ffff758f95f wxEvtHandler::TryBeforeAndHere /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../include/wx/event.h 3927
7 0x00007ffff758f95f wxEvtHandler::ProcessEventLocally /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1555
8 0x00007ffff758fa61 wxEvtHandler::ProcessEvent /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1528
9 0x00007ffff7590f8b wxEvtHandler::SafelyProcessEvent /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/common/event.cpp 1646
10 0x00007ffff7be5db0 wxWindowBase::HandleWindowEvent /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../include/wx/window.h 852
11 0x00007ffff7a1ba02 wxgtk_button_clicked_callback /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.4/objs_gtk_sh/../src/gtk/button.cpp 38
12 0x00007ffff62dba56 ??
13 0x00007ffff62fab28 g_signal_emit_valist
14 0x00007ffff62fb0d3 g_signal_emit
15 0x00007ffff68f92ae ??
16 0x00007ffff68f9318 ??
17 0x00007ffff62db802 g_closure_invoke
18 0x00007ffff62ef962 ??
19 0x00007ffff62fab9e g_signal_emit_valist
20 0x00007ffff62fb0d3 g_signal_emit
21 0x00007ffff68f7754 ??
22 0x00007ffff6ba8a71 ??
23 0x00007ffff62dba56 ??
24 0x00007ffff62fab28 g_signal_emit_valist
25 0x00007ffff62fb0d3 g_signal_emit
26 0x00007ffff69bff5c ??
27 0x00007ffff62dec56 g_cclosure_marshal_VOID__BOXEDv
28 0x00007ffff62dba56 ??
29 0x00007ffff62fab28 g_signal_emit_valist
30 0x00007ffff62fb0d3 g_signal_emit
31 0x00007ffff69bcfa2 ??
32 0x00007ffff69be5eb ??
33 0x00007ffff69c15d6 ??
34 0x00007ffff6988bb0 gtk_event_controller_handle_event
35 0x00007ffff6b4b0fd ??
36 0x00007ffff6ba248b ??
37 0x00007ffff62db802 g_closure_invoke
38 0x00007ffff62eef96 ??
39 0x00007ffff62fa45d g_signal_emit_valist
40 0x00007ffff62fb0d3 g_signal_emit
41 0x00007ffff6b4cbb3 ??
42 0x00007ffff6a080b8 ??
43 0x00007ffff6a0a36b gtk_main_do_event
44 0x00007ffff66f2f79 ??
45 0x00007ffff6726106 ??
46 0x00007ffff61effbd g_main_context_dispatch
47 0x00007ffff61f0240 ??
48 0x00007ffff61f0533 g_main_loop_run
49 0x00007ffff6a0930d gtk_main
50 0x00007ffff79b0e95 wxGUIEventLoop::DoRun /home/david/devel/packages/wx/3.1.4/wxwidgets3.1-3.1.