wxWidgets: как изменить и отобразить контент sizer - PullRequest
0 голосов
/ 22 апреля 2019

В моем коде есть собственный класс MyFrame, в котором я создаю wxGridSizer, который содержит wxBitmapToggleButton указатели. После вызова конструктора MyFrame все работает нормально, но когда мне нужно изменить содержимое sizer (используя одну из функций события), я вижу только один wxBitmapToggleButton объект.

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
    }
}

Эти изображения показывают результат только после вызова конструктора и после вызова функции события: https://postimg.cc/gallery/uzc2zmii/

1 Ответ

1 голос
/ 24 апреля 2019

Я думаю, вам просто нужно вызвать Layout (); в конце вашего метода displayImages ().Как указано в документации:

Вызовите это, чтобы заново выстроить расположение дочерних элементов, например, после добавления дочернего элемента или удаления дочернего элемента (окна, другого размера или пространства) из классификатора

Кроме того, в методе displayImages я думаю, что вы можете просто вызвать gridSizer->Clear(true); вместо использования цикла for для очистки предыдущего содержимого классификатора.

...