c++listviewwxwidgetssizer

resizing wxListView with sizer


I'm struggling to resize my wxListView when resizing my wxFrame. I managed to resize ListView's parent panel and wxButton in the same panel also moves with resizing the window as intended.

BluetoothConnectFrame::BluetoothConnectFrame(const wxString& title, const wxPoint& pos, const wxSize& size, Frame* parent) 
    : wxFrame(NULL, wxID_ANY, title, pos, size), 
        bleConnector(std::make_unique<BluetoothConnector>()),
        mainPanel(new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(size.x, size.y / 4 * 3), wxTAB_TRAVERSAL, "Main Panel")),
        sizer (new wxBoxSizer(wxVERTICAL))

{
bledevListView = std::make_unique<wxListView>(new wxListView(mainPanel, ID_Bluetooth,
     wxPoint(size.GetWidth() - size.GetWidth() + 20, size.GetHeight() - size.GetHeight() + 20),
     wxSize(size.GetWidth() - 50, size.GetHeight() / 2)));

    bledevListView->AppendColumn("Address");
    bledevListView->SetColumnWidth(0, getBLEListViewSize().x/ 2);
    bledevListView->AppendColumn("Name");
    bledevListView->SetColumnWidth(1, getBLEListViewSize().x / 2); 

    stopDiscButton = new wxButton(mainPanel, wxID_ANY, "Stop discovery", wxPoint(0,0), STOPDISCSIZE,         wxBU_LEFT, wxDefaultValidator, "Stop disc");

    sizer->Add(bledevListView.get(), 1 ,wxEXPAND, 1);
    sizer->Add(stopDiscButton );
    mainPanel->SetSizer(sizer);
}

wxSizeEvent function

void BluetoothConnectFrame::OnSize(wxSizeEvent & e) {
   size = e.GetSize();
   mainPanel->SetSize(getMainPanelSize());
   sizer->Layout();
}

Printing out bledevListView size in OnSize event would print the correct values. However the UI does not update the ListView to match these values. I have tried using SetSize(), Update(), Refresh() on bledevListView and also tried resizing wxListView without using wxSizer but nothing would work. Any tips?


Solution

  • As others have noted in comments, you can do layout yourself explicitly in wxEVT_SIZE handler or (and this is the exclusive or) use sizers. To do the latter, start by removing your OnSize() handler for the frame entirely. What you may still want to have is an wxEVT_SIZE handler for the list view itself, which could resize its columns as you want.

    Second problem in the code you show is even worse: you give ownership of wxListView to a unique_ptr<>. Unless you call release() on it at some later time, this is very wrong: all GUI elements are owned by wxWidgets and will be deleted by it. You need to use raw pointers or, if you prefer, non-owning smart pointer type (observer_ptr<>) for all wxWindow-derived objects in your program (but this also applies to sizers and, basically, anything that you "give" to the framework to be managed by it).