wxWidgets: Как изменить и отобразить содержимое sizer

#c #user-interface #wxwidgets

#c #пользовательский интерфейс #wxwidgets

Вопрос:

В моем коде у меня есть собственный 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(wxCommandEventamp; 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(wxCommandEventamp; 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. вы знаете, что должно отображаться? Или вам нужно динамически изменять содержимое? Если это первое — просто создайте дополнительный элемент управления, скройте его, а затем покажите при необходимости.

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

3. Спасибо New Pagodi , это решило проблему! Это моя первая программа в wxWidgets, поэтому я не знал этой функции.

4. @NewPagodi Вы должны дать этот ответ, чтобы его можно было принять…

5. Да, и @username16 должен пометить ответ как принятый.

Ответ №1:

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

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

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