#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.