Pular para o conteúdo

wxWidgets Cheat Sheet

Overview

wxWidgets is a free, open-source C++ library for building cross-platform graphical user interfaces. Unlike frameworks that draw their own widgets, wxWidgets uses each platform’s native GUI toolkit — Win32 on Windows, Cocoa on macOS, and GTK on Linux — resulting in applications that look and feel truly native on each operating system. The library has been actively developed since 1992, making it one of the most mature cross-platform GUI frameworks available.

wxWidgets provides an extensive set of controls, dialogs, device contexts for drawing, printing support, sockets, threads, clipboard access, drag-and-drop, and database connectivity. It supports both frame-based and dialog-based applications, MDI (multiple document interface), and custom widget development. The library is used in production by notable applications and supports C++17 and later standards. Language bindings exist for Python (wxPython), Perl, Ruby, and other languages.

Installation

# macOS
brew install wxwidgets

# Ubuntu/Debian
sudo apt install libwxgtk3.2-dev wx-common wx3.2-headers

# Fedora
sudo dnf install wxGTK3-devel

# Arch Linux
sudo pacman -S wxwidgets-gtk3

# Windows (vcpkg)
vcpkg install wxwidgets

# Build from source
git clone https://github.com/wxWidgets/wxWidgets.git
cd wxWidgets
git submodule update --init
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . -j$(nproc)
sudo cmake --install .

# Verify installation
wx-config --version
wx-config --cxxflags
wx-config --libs

Basic Application

// main.cpp
#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    bool OnInit() override;
};

class MyFrame : public wxFrame
{
public:
    MyFrame();

private:
    void OnHello(wxCommandEvent& event);
    void OnExit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
};

// Event table
enum {
    ID_Hello = 1
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(ID_Hello, MyFrame::OnHello)
    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
    MyFrame* frame = new MyFrame();
    frame->Show(true);
    return true;
}

MyFrame::MyFrame()
    : wxFrame(nullptr, wxID_ANY, "Hello wxWidgets", wxDefaultPosition, wxSize(800, 600))
{
    // Menu bar
    wxMenu* menuFile = new wxMenu;
    menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", "Say hello");
    menuFile->AppendSeparator();
    menuFile->Append(wxID_EXIT);

    wxMenu* menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);

    wxMenuBar* menuBar = new wxMenuBar;
    menuBar->Append(menuFile, "&File");
    menuBar->Append(menuHelp, "&Help");
    SetMenuBar(menuBar);

    // Status bar
    CreateStatusBar();
    SetStatusText("Welcome to wxWidgets!");

    // Center on screen
    Centre();
}

void MyFrame::OnHello(wxCommandEvent& event)
{
    wxLogMessage("Hello from wxWidgets!");
}

void MyFrame::OnExit(wxCommandEvent& event)
{
    Close(true);
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxMessageBox("wxWidgets sample application",
                 "About", wxOK | wxICON_INFORMATION);
}

Common Controls

ControlDescription
wxStaticTextLabel / static text
wxTextCtrlText input (single/multi line)
wxButtonPush button
wxToggleButtonToggle button
wxCheckBoxCheckbox
wxRadioButtonRadio button
wxRadioBoxRadio button group
wxChoice / wxComboBoxDropdown selection
wxListBoxList selection
wxListCtrlMulti-column list
wxTreeCtrlHierarchical tree
wxSliderValue slider
wxSpinCtrlNumeric spinner
wxGaugeProgress bar
wxStaticBitmapImage display
wxNotebookTabbed pages
wxSplitterWindowResizable split panes
wxGridSpreadsheet-like grid

Building a Form

MyFrame::MyFrame()
    : wxFrame(nullptr, wxID_ANY, "Registration", wxDefaultPosition, wxSize(400, 500))
{
    wxPanel* panel = new wxPanel(this);
    
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
    
    // Title
    wxStaticText* title = new wxStaticText(panel, wxID_ANY, "Registration Form");
    wxFont titleFont = title->GetFont();
    titleFont.SetPointSize(18);
    titleFont.SetWeight(wxFONTWEIGHT_BOLD);
    title->SetFont(titleFont);
    mainSizer->Add(title, 0, wxALL | wxALIGN_CENTER, 15);
    
    // Form grid
    wxFlexGridSizer* formSizer = new wxFlexGridSizer(2, 10, 10);
    formSizer->AddGrowableCol(1, 1);
    
    // Name field
    formSizer->Add(new wxStaticText(panel, wxID_ANY, "Name:"), 0, wxALIGN_CENTER_VERTICAL);
    m_nameCtrl = new wxTextCtrl(panel, wxID_ANY);
    formSizer->Add(m_nameCtrl, 1, wxEXPAND);
    
    // Email field
    formSizer->Add(new wxStaticText(panel, wxID_ANY, "Email:"), 0, wxALIGN_CENTER_VERTICAL);
    m_emailCtrl = new wxTextCtrl(panel, wxID_ANY);
    formSizer->Add(m_emailCtrl, 1, wxEXPAND);
    
    // Password field
    formSizer->Add(new wxStaticText(panel, wxID_ANY, "Password:"), 0, wxALIGN_CENTER_VERTICAL);
    m_passwordCtrl = new wxTextCtrl(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD);
    formSizer->Add(m_passwordCtrl, 1, wxEXPAND);
    
    // Country dropdown
    formSizer->Add(new wxStaticText(panel, wxID_ANY, "Country:"), 0, wxALIGN_CENTER_VERTICAL);
    wxArrayString countries;
    countries.Add("United States");
    countries.Add("United Kingdom");
    countries.Add("Germany");
    countries.Add("Japan");
    m_countryChoice = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, countries);
    m_countryChoice->SetSelection(0);
    formSizer->Add(m_countryChoice, 1, wxEXPAND);
    
    mainSizer->Add(formSizer, 0, wxEXPAND | wxALL, 15);
    
    // Terms checkbox
    m_termsCheck = new wxCheckBox(panel, wxID_ANY, "I agree to the terms");
    mainSizer->Add(m_termsCheck, 0, wxLEFT | wxBOTTOM, 15);
    
    // Buttons
    wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
    btnSizer->AddStretchSpacer();
    wxButton* cancelBtn = new wxButton(panel, wxID_CANCEL, "Cancel");
    wxButton* submitBtn = new wxButton(panel, wxID_OK, "Submit");
    btnSizer->Add(cancelBtn, 0, wxRIGHT, 10);
    btnSizer->Add(submitBtn, 0);
    mainSizer->Add(btnSizer, 0, wxEXPAND | wxALL, 15);
    
    panel->SetSizer(mainSizer);
    
    // Bind events
    submitBtn->Bind(wxEVT_BUTTON, &MyFrame::OnSubmit, this);
    cancelBtn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { Close(); });
}

Sizers (Layout Management)

// wxBoxSizer - horizontal or vertical
wxBoxSizer* vSizer = new wxBoxSizer(wxVERTICAL);
vSizer->Add(ctrl1, 0, wxALL, 5);          // Fixed size, 5px margin
vSizer->Add(ctrl2, 1, wxEXPAND | wxALL, 5);  // Expandable
vSizer->AddStretchSpacer();               // Flexible space

// wxFlexGridSizer - flexible grid
wxFlexGridSizer* grid = new wxFlexGridSizer(2, 5, 5);  // 2 cols, 5px gaps
grid->AddGrowableCol(1, 1);  // Column 1 grows
grid->Add(label, 0, wxALIGN_CENTER_VERTICAL);
grid->Add(input, 1, wxEXPAND);

// wxGridBagSizer - precise grid placement
wxGridBagSizer* bag = new wxGridBagSizer(5, 5);
bag->Add(title, wxGBPosition(0, 0), wxGBSpan(1, 2), wxEXPAND);
bag->Add(label, wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
bag->Add(input, wxGBPosition(1, 1), wxDefaultSpan, wxEXPAND);

// wxStaticBoxSizer - labeled group
wxStaticBoxSizer* group = new wxStaticBoxSizer(wxVERTICAL, panel, "Settings");
group->Add(checkbox1, 0, wxALL, 5);
group->Add(checkbox2, 0, wxALL, 5);

// Apply sizer
panel->SetSizer(mainSizer);
mainSizer->Fit(this);  // Resize window to fit content

Event Handling

// Method 1: Bind (modern, preferred)
button->Bind(wxEVT_BUTTON, &MyFrame::OnButtonClick, this);
textCtrl->Bind(wxEVT_TEXT, &MyFrame::OnTextChanged, this);

// Lambda binding
button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
    wxMessageBox("Button clicked!");
});

// Method 2: Event table (traditional)
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_BUTTON(ID_MyButton, MyFrame::OnButtonClick)
    EVT_TEXT(ID_MyText, MyFrame::OnTextChanged)
    EVT_CLOSE(MyFrame::OnClose)
    EVT_SIZE(MyFrame::OnSize)
    EVT_TIMER(ID_Timer, MyFrame::OnTimer)
wxEND_EVENT_TABLE()

// Common events
void MyFrame::OnButtonClick(wxCommandEvent& event) { }
void MyFrame::OnTextChanged(wxCommandEvent& event) {
    wxString text = event.GetString();
}
void MyFrame::OnClose(wxCloseEvent& event) {
    if (wxMessageBox("Quit?", "Confirm", wxYES_NO) == wxYES)
        Destroy();
    else
        event.Veto();
}
void MyFrame::OnSize(wxSizeEvent& event) {
    wxSize size = event.GetSize();
    event.Skip();  // Allow default processing
}

Dialogs

// Message box
wxMessageBox("Operation complete!", "Success", wxOK | wxICON_INFORMATION);

int result = wxMessageBox("Save changes?", "Confirm",
                          wxYES_NO | wxCANCEL | wxICON_QUESTION);
if (result == wxYES) { /* save */ }

// File dialog
wxFileDialog openDialog(this, "Open File", "", "",
    "Text files (*.txt)|*.txt|All files (*.*)|*.*",
    wxFD_OPEN | wxFD_FILE_MUST_EXIST);

if (openDialog.ShowModal() == wxID_OK) {
    wxString path = openDialog.GetPath();
}

// Save dialog
wxFileDialog saveDialog(this, "Save File", "", "document.txt",
    "Text files (*.txt)|*.txt", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

// Directory dialog
wxDirDialog dirDialog(this, "Choose directory", "",
    wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);

// Color picker
wxColourDialog colorDialog(this);
if (colorDialog.ShowModal() == wxID_OK) {
    wxColour color = colorDialog.GetColourData().GetColour();
}

// Text input dialog
wxTextEntryDialog textDialog(this, "Enter value:", "Input", "default");
if (textDialog.ShowModal() == wxID_OK) {
    wxString value = textDialog.GetValue();
}

// Progress dialog
wxProgressDialog progress("Processing", "Please wait...",
    100, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
for (int i = 0; i <= 100; i++) {
    if (!progress.Update(i, wxString::Format("Step %d of 100", i)))
        break;  // User cancelled
    wxMilliSleep(50);
}

Configuration (Build System)

# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(myapp LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(wxWidgets REQUIRED COMPONENTS core base adv)
include(${wxWidgets_USE_FILE})

add_executable(myapp
    src/main.cpp
    src/mainframe.cpp
    src/mainframe.h
)

target_link_libraries(myapp PRIVATE ${wxWidgets_LIBRARIES})

# Windows: hide console window
if(WIN32)
    set_target_properties(myapp PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
# Build with CMake
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . -j$(nproc)

# Build with wx-config directly
g++ -o myapp main.cpp $(wx-config --cxxflags --libs)

# With additional libraries
g++ -o myapp main.cpp $(wx-config --cxxflags --libs core,base,adv,aui)

Advanced Usage

// Custom drawing with wxDC
void MyPanel::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
    
    dc.SetBackground(*wxWHITE_BRUSH);
    dc.Clear();
    
    dc.SetPen(wxPen(*wxBLUE, 2));
    dc.SetBrush(*wxLIGHT_GREY_BRUSH);
    dc.DrawRectangle(50, 50, 200, 100);
    
    dc.SetFont(wxFont(14, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
    dc.DrawText("Hello wxWidgets", 70, 85);
    
    dc.SetPen(wxPen(*wxRED, 3));
    dc.DrawCircle(400, 200, 50);
    
    dc.DrawLine(0, 0, GetSize().GetWidth(), GetSize().GetHeight());
}

// Timer
class MyFrame : public wxFrame {
    wxTimer m_timer;
    
    MyFrame() : wxFrame(...), m_timer(this, wxID_ANY) {
        m_timer.Start(1000);  // 1 second interval
        Bind(wxEVT_TIMER, &MyFrame::OnTimer, this);
    }
    
    void OnTimer(wxTimerEvent& event) {
        SetStatusText(wxDateTime::Now().FormatTime());
    }
};

// Threading
class WorkerThread : public wxThread {
    wxEvtHandler* m_handler;
public:
    WorkerThread(wxEvtHandler* handler) : wxThread(wxTHREAD_DETACHED), m_handler(handler) {}
    
    void* Entry() override {
        for (int i = 0; i <= 100; i++) {
            wxThreadEvent event(wxEVT_THREAD, wxID_ANY);
            event.SetInt(i);
            wxQueueEvent(m_handler, event.Clone());
            wxMilliSleep(100);
        }
        return nullptr;
    }
};

// Drag and drop
class MyDropTarget : public wxFileDropTarget {
    bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) override {
        for (const auto& file : filenames) {
            wxLogMessage("Dropped: %s", file);
        }
        return true;
    }
};
panel->SetDropTarget(new MyDropTarget());

Troubleshooting

IssueSolution
”wxWidgets not found”Check wx-config --prefix; set wxWidgets_ROOT_DIR in CMake
GTK warnings on LinuxInstall libwxgtk3.2-dev; ensure GTK3 development headers installed
macOS dark mode issuesUpdate to wxWidgets 3.2+; use system colors instead of hardcoded
Sizer layout wrongCall Layout() or Fit() after adding controls; check flags
Events not firingVerify event binding; check event.Skip() for propagation
Unicode display issuesEnsure wxUSE_UNICODE is enabled (default in 3.x)
Static linking failsBuild wxWidgets as static: cmake -DwxBUILD_SHARED=OFF
High DPI blurryEnable DPI awareness in manifest (Windows); use FromDIP() for sizes
Crash on destructionCheck parent-child ownership; avoid manual delete of parented widgets
Memory leak warningsUse wxSizerFlags; ensure all new’d objects have parent windows