这似乎并不像我希望的那么简单:
使用wxWidgets(2.8稳定系列),我有一个wxGrid(不是子类),自定义"数据适配器"作为wxGridTableBase派生类.
wxGrid* grid = new wxGrid (this, ID_TABLE);
grid->SetTable (new TableAdapter (foo, bar, baz));
grid->EnableEditing (false);
sizer->Add(grid, wxSizerFlags (1).Expand());
Run Code Online (Sandbox Code Playgroud)
我找不到的"简单"的东西是在底层数据模型发生变化时刷新网格的一种方法.简单地调用wxWindow :: Update(pGrid->Update())显然不足以让网格调用底层的wxGridTableBase实现?
wxGrid* const grid = (wxGrid* const) FindWindow (ID_TABLE);
if (NULL != grid) {
grid->Update ();
grid->AutoSizeColumns ();
}
Run Code Online (Sandbox Code Playgroud)
特别是,此网格充当列表,并且将通过相同或(可能)另一个进程异步添加和删除行 - 它是可由多个联网系统中的任何一个更新的共享数据列表.网格/列表本身实际上是只读的; 其他控件用于添加和删除项,每行都有一个布尔类型属性,也可以切换.
似乎新行未添加到视图中,删除行将导致wx绘图代码中的间歇性SEGV.
由于动态/异步更新机制,我希望避免不断删除并重新添加网格到窗口,因为我确信会导致各种闪烁和肮脏......所以,我会摔倒如果我绝对必须这样做,那就回去尝试一些类似暴力的东西,但我更倾向于避免它.
不幸的是,尽管被标记为"稳定版本",但wxGrid文档似乎主要由Yet to be written标签组成.
更新:
我开始怀疑这是容器布局问题.在绘制网格时,网格的底部(最后一行)实际上可以围绕wxFrame窗口部分的wxStaticBox框架以及框架状态行的一部分重叠.添加和删除行似乎不会强制重新布局容器; 我正在尝试打电话Layout等.理想情况下,这应该是一个滚动区域,但wxGrid 仍应在其包含的Sizer中"约束".
布局实际上包含一个静态框,其中包含一个垂直框,第一个元素是一个水平的按钮框,然后是网格,如下所示:
--[ Static Box ]------------------------
| |
| [Button] [Button] [Button] |
| |
| ----------------------------------- |
| | | A | B | C | |
| |-----------------------------------| |
| | 1 | 1a | 1b | 1c | |
| ----------------------------------- |
| |
----------------------------------------
Run Code Online (Sandbox Code Playgroud)
很抱歉,公司政策禁止我发布截图:-(
如果重要的话,这是(目前)在Fedora 16(x86_64)上的wxGTK-2.8.12,虽然我在使用EPEL(Fedora)软件包的CentOS5/RHEL5上看到相同的行为.
经过多次实验,强制刷新的"正确"方式看起来像这样:
bool
CDynamicWxGridTable::AppendRows(const size_t IGNORED _)
{
wxGrid *grid = GetView();
if (pGrid != NULL)
{
const int iNumRecords = GetNumberRows();
const int iGridRows = grid->GetNumberRows();
const int iNeedRows = iNumRecords - iGridRows;
if (iNeedRows)
{
grid->BeginBatch();
grid->ClearSelection();
if (grid->IsCellEditControlEnabled())
{
grid->DisableCellEditControl();
}
{
wxGridTableMessage pop(this,
wxGRIDTABLE_NOTIFY_ROWS_DELETED,
0, iGridRows);
grid->ProcessTableMessage(pop);
}
{
wxGridTableMessage push(this,
wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
iNumRecords);
grid->ProcessTableMessage(push);
}
grid->AutoSize();
grid->ForceRefresh();
grid->EndBatch();
}
}
return true;
}
bool
CDynamicWxGridTable::DeleteRows(const size_t IGNORED pos,
const size_t IGNORED rows)
{
return AppendRows(0);
}
Run Code Online (Sandbox Code Playgroud)
这些在我的(5Hz)更新例程中通过抓取grid并调用其 ->AppendRows(1)方法来调用,该方法又调用wxTableBase-derived类的::AppendRows成员.
不幸的是,由于我是从异步的,动态更新的记录中提取的,因此对于行属性,wxGrid缓存系统仍在"打击"我(如果一行更改,其GetAttr值应该更改,它不会动态刷新,因为上面只测试了应该存在的行数与实际存在的行数.然而,这是一个相对较小的错误,我希望通过其他方式克服它.
"关键"部分似乎是通过ProcessTableMessage... 合成删除/追加行消息到wxGridTable系统...没有它,wxGrid缓存似乎没有注意到表大小的变化.
顺便提一下,通过在::GetValue(const int row, const int column)方法中放置保护来检查有效值,可以减轻因丢失行而导致的崩溃:
if (row < 0 || row > GetNumberRows()) { return L"×"; }
if (col < 0 || col > LAST_COLUMN) { return L"×"; }
Run Code Online (Sandbox Code Playgroud)
然而,在添加上面的疯狂消息注入逻辑之后,似乎没有显示这些"×"值.
| 归档时间: |
|
| 查看次数: |
7397 次 |
| 最近记录: |