2

ボタンを介して gridsizer 内のコントロールの行を動的に追加および削除する wxWidgets GUI をコーディングしています。

コントロールの各行には、次のイベントをトリガーする「削除」ボタンがあります。

  • コントロールをサイザーから削除します
  • コントロールを非表示にします
  • ボタンの削除イベントのバインドを解除します
  • コントロールが再利用可能なコントロール プールで使用可能であることを示します (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);
}

ところで、この GUI の目的は、読み込まれた XML ファイルにプロパティの検索フィルターを追加することです。

4

1 に答える 1