In my code I've own MyFrame
class where I create wxGridSizer
which contains wxBitmapToggleButton
pointers. After calling MyFrame
constructor everything works fine, but when I need to change sizer content (using one of event functions) I can see only one wxBitmapToggleButton
object.
class MyFrame : public wxFrame {
public:
MyFrame();
private:
// own classes needed in application
GameBoard *gb;
Player* player;
bool lightTheme;
wxGridSizer *gridSizer; // sizer which contains these buttons
std::vector<wxBitmapToggleButton *> cardImages; // stores wxBitmapToggleButtons pointers managed by gridSizer
void OnCardSelect(wxCommandEvent& event); // event function
void displayImages(); // function which adds wxBitmapToggleButtons to sizer
};
MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, "SET Card Game") {
// ...
// init GameBoard, Player and lightTheme
topSizer = new wxBoxSizer(wxVERTICAL);
gridSizer = new wxGridSizer(4, 6, 0, 0);
displayImages(); // create and display wxBitmapToggleButtons in sizer
// ...
// some other layout
topSizer -> Add(gridSizer);
this -> SetSizer(topSizer);
topSizer -> Fit(this);
topSizer -> SetSizeHints(this);
}
void MyFrame::OnCardSelect(wxCommandEvent& event) {
wxBitmapToggleButton *selectedCard = dynamic_cast<wxBitmapToggleButton *>(event.GetEventObject());
player -> toggleChosen(int(selectedCard -> GetId()));
if(player -> readyToCheck()) {
const std::vector<int> chosen = player -> getChosen();
for(int card : chosen) {
cardImages[card] -> SetValue(false);
player -> toggleChosen(card);
}
if(gb -> isOk(chosen)) {
// do some modifications on GameBoard
displayImages();
}
}
}
// most important method, it should display card images stored in GameBoard
void MyFrame::displayImages() {
const std::vector<Card> table = gb -> getTable();
for(wxBitmapToggleButton* ptr : cardImages) {
// delete all old wxBitmapToggleButtons from sizer
gridSizer -> Detach(ptr);
ptr -> Destroy();
}
cardImages.clear();
for(int i = 0; i < table.size(); i++) {
wxBitmap bmp = getCardImage(table[i].getCode(), lightTheme, 0.1); // load image
cardImages.push_back(new wxBitmapToggleButton(this, i, bmp, wxDefaultPosition, wxSize(bmp.GetWidth() + 10, bmp.GetHeight() + 10))); // create wxBitmapTogglebutton from loaded image ...
gridSizer -> Add(cardImages[i], 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5); // ... and add it to sizer
this -> Connect(i, wxEVT_TOGGLEBUTTON, wxCommandEventHandler(MyFrame::OnCardSelect)); // connect created button to event
}
}
These images shows result only after calling constructor, and after calling event function: https://postimg.cc/gallery/uzc2zmii/
I think you just need to call Layout(); at the end of your displayImages() method. As the documentation states:
Call this to force layout of the children anew, e.g. after having added a child to or removed a child (window, other sizer or space) from the sizer
Also, in the displayImages method I think you might be able to just call gridSizer->Clear(true);
instead of using the for loop to clean out the previous contents of the sizer.