You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ViewData结构体用GTK创建标签失败,无显示无报错

问题分析与解决

问题描述

定义了如下结构体:

struct ViewData {
    int ID;
    std::string Name;
    std::string Mode;
    std::string Status;
    std::string Type;
};

使用以下函数处理该结构体的3组数据时,既不绘制标签也无错误提示,无法正常显示所有标签:

for (std::size_t i = 0; i < parsedData.size(); ++i) {
    const ViewData& data = parsedData[i];
    // Create widgets for ID, Name, Mode, Status, and Type
    std::cout << "\nProcessing data ID: " << data.ID << std::endl;

    Gtk::Label idLabelWidget, nameLabelWidget, modeLabelWidget, statusLabelWidget, typeLabelWidget;
    Gtk::Label idValueLabelWidget, nameValueLabelWidget, modeValueLabelWidget, statusValueLabelWidget, typeValueLabelWidget;

    cout << "Label Creation at: " << data.ID;

    idLabelWidget.set_text("ID:");
    nameLabelWidget.set_text("Name:");
    modeLabelWidget.set_text("Mode:");
    statusLabelWidget.set_text("Status:");
    typeLabelWidget.set_text("Type:");

    cout << "Label Names at: " << data.ID;

    idValueLabelWidget.set_label(std::to_string(data.ID));
    nameValueLabelWidget.set_label(data.Name);
    modeValueLabelWidget.set_label(data.Mode);
    statusValueLabelWidget.set_label(data.Status);
    typeValueLabelWidget.set_label(data.Type);

    cout << "Label Values at: " << data.ID;
    // Add labels to the grid
    grid.attach(idLabelWidget,          0, row, 1, 1);
    grid.attach(idValueLabelWidget,     1, row, 1, 1);
    idLabelWidget.show(); 
    idValueLabelWidget.show();
    cout << "ID SET at: " << data.ID;

    grid.attach(nameLabelWidget,        2, row, 1, 1);
    grid.attach(nameValueLabelWidget,   3, row, 1, 1);
    cout << "NAME SET at: " << data.ID;

    grid.attach(modeLabelWidget,        4, row, 1, 1);
    grid.attach(modeValueLabelWidget,   5, row, 1, 1);
    cout << "MODE SET at: " << data.ID;

    grid.attach(statusLabelWidget,      6, row, 1, 1);
    grid.attach(statusValueLabelWidget, 7, row, 1, 1);
    cout << "STATUS SET at: " << data.ID;

    grid.attach(typeLabelWidget,        8, row, 1, 1);
    grid.attach(typeValueLabelWidget,   9, row, 1, 1);
    cout << "TYPE SET at: " << data.ID << endl;
    //box.pack_start(grid, Gtk::PACK_SHRINK); // Add grid to box
    cout << "************************************ at: " << data.ID << endl << std::flush;
    row += 2; // Increment row for next set of widgets
}

尝试将Gtk::Label移到循环外时,仅显示第一个元素,处理第二个元素时触发grid.attach的断言错误,调整行位置后问题依旧。

核心原因与解决办法

1. 局部Widget生命周期失效

循环内定义的Gtk::Label是局部变量,每次循环结束后这些对象会被销毁。Gtk容器(如Gtk::Grid)不会自动接管Widget的内存所有权,一旦Widget被销毁,容器内的引用就失效,自然无法显示。

解决方式:
使用Gtk::manage包装Widget,让容器接管其所有权;或用智能指针管理Widget生命周期,确保Widget在容器存续期间不会被销毁。示例:

// 用Gtk::manage创建Widget,容器会自动管理内存
auto idLabelWidget = Gtk::manage(new Gtk::Label("ID:"));
auto idValueLabelWidget = Gtk::manage(new Gtk::Label(std::to_string(data.ID)));

grid.attach(*idLabelWidget, 0, row, 1, 1);
grid.attach(*idValueLabelWidget, 1, row, 1, 1);
idLabelWidget->show();
idValueLabelWidget->show();

2. 循环外复用Widget导致的冲突

将Label移到循环外后,同一个Widget只能属于一个父容器,第二次调用grid.attach时,Widget已存在父容器,触发断言错误。

解决方式:
每个循环迭代必须创建新的Widget实例,不能复用同一个对象。

3. 其他必要检查

  • 取消注释box.pack_start(grid, Gtk::PACK_SHRINK),确保grid被添加到上层容器,且上层容器已正确加入窗口;
  • 可调用grid.show_all()替代逐个调用Widget的show(),避免遗漏显示操作。

内容的提问来源于stack exchange,提问作者RBGA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:23:36