Я кодирую графический интерфейс wxWidgets, который включает динамическое добавление и удаление строк элементов управления внутри gridsizer с помощью кнопок.
В каждом ряду элементов управления есть кнопка «удалить», которая запускает событие, которое:
- Удаляет элементы управления из их размера
- Скрывает элементы управления
- Отменяет событие кнопки удаления
- Помечает элементы управления как доступные в пулах повторно используемых элементов управления (я повторно использую элементы управления, потому что wxWidgets не любит удалять данные во время выполнения)
Теперь я не думаю, что отвязка события внутри самого обработчика событий - это хорошо. Есть ли лучший способ добиться такого поведения?
вот как я динамически создаю свои элементы управления
bool filtermanager::add()
{
if (!grid || !box || !form || !bsizer)
return false;
dbgcode(log->d(tag, "add: adding a new filter row"));
// add and index filter in the filter map and refresh layout
filter *flt = new filter(this, box, grid);
filters[flt->removebutton()->GetId()] = flt;
refreshlayout();
return true;
}
filtermanager::filter::filter(filtermanager *parent,
wxStaticBox *box, wxGridSizer *grid)
: parent(parent), grid(grid)
{
controlpool *ctl = parent->ctl;
// initialize filter row elements
property = ctl->makeComboBox(box, "property");
value = ctl->makeTextCtrl(box, "value");
button = ctl->makeButton(box, "Remove");
// add filter row to the grid sizer
grid->SetRows(grid->GetRows() + 1);
grid->Add(property, 0, wxALL | wxEXPAND, 0);
grid->Add(value, 0, wxALL | wxEXPAND, 0);
grid->Add(button, 0, wxALL | wxEXPAND, 0);
// bind remove button
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &filtermanager::OnRemoveClicked, parent);
}
это обработчик события:
void filtermanager::OnRemoveClicked(wxCommandEvent &e)
{
wxButton *b = dynamic_cast<wxButton *>(e.GetEventObject());
filter *flt = filters[b->GetId()];
dbgcode(log->d(tag,
strfmt() << "OnRemoveClicked: remove button event caught" <<
" property=" << flt->propertycombo() <<
" value=" << flt->valuetext() <<
" button=" << flt->removebutton())
);
removebyflt(flt);
}
void filtermanager::removebyflt(filter *flt)
{
int id = flt->id();
// dealloc filter from the map
delete filters[id];
filters[id] = NULL;
filters.erase(id);
}
filtermanager::filter::~filter()
{
controlpool *ctl = parent->ctl;
// unbind button
button->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &filtermanager::OnRemoveClicked, parent);
// remove the filter from the gui
if (!grid->Detach(property))
parent->log->e(tag, "~filter: failed to remove property from sizer");
if (!grid->Detach(value))
parent->log->e(tag, "~filter: failed to remove value from sizer");
if (!grid->Detach(button))
parent->log->e(tag, "~filter: failed to remove button from sizer");
grid->SetRows(grid->GetRows() - 1);
// refresh panels as usual
parent->refreshlayout();
ctl->free(property);
ctl->free(value);
ctl->free(button);
}
Кстати, целью этого графического интерфейса является добавление фильтров поиска свойств в загруженном XML-файле.