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

GTK3(C语言)生成同组单选按钮列表的问题求助

GTK3 C语言单选按钮组创建问题

在Linux环境下使用GTK3与C语言开发UI时,尝试生成同属一组的单选按钮列表,遇到如下问题:

  • 按逻辑创建第一个单选按钮时传入NULL让GTK自动创建组,后续按钮传入该组指针加入同一组
  • 运行后按钮0始终处于选中状态无法取消,其余按钮均可独立切换,未真正归为同一组

原问题代码

生成单选按钮列表的函数

void make_projects_list(GtkWidget *projects_grid)
{
    int n = 20;
        
    GSList *group;
    for (int i =0; i<n; i++)
    {
        GtkWidget *radio;
        char label[3];
        snprintf(label, 3, "%d", i);
        if (i==0)
        {   
            radio = gtk_radio_button_new_with_label(NULL, label);
            group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
        }
        else
        { 
            radio = gtk_radio_button_new_with_label(group, label);
        }

        gtk_grid_insert_row(GTK_GRID(projects_grid), i);
        gtk_grid_attach(GTK_GRID(projects_grid), radio, 1, i, 1,1); 
    }
}

完整可复现代码

#include<gtk/gtk.h>
#include<stdio.h>

void make_projects_list(GtkWidget *projects_grid)
{
    int n = 20;

    GSList *group;
    for (int i =0; i<n; i++)
    {
        GtkWidget *radio;
        char label[3];
        snprintf(label, 3, "%d", i);
        if (i==0)
        {
            radio = gtk_radio_button_new_with_label(NULL, label);
            group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
        }
        else
        {
            radio = gtk_radio_button_new_with_label(group, label);
        }

        gtk_grid_insert_row(GTK_GRID(projects_grid), i);
        gtk_grid_attach(GTK_GRID(projects_grid), radio, 1, i, 1,1);
    }
}

int main(int argc, char *argv[])
{
    GtkBuilder *builder;

    GtkWidget *window;  
    GtkWidget *grid;

    GError *error = NULL;
    gtk_init(&argc, &argv);
    
    builder = gtk_builder_new();
    if (gtk_builder_add_from_file(builder, "build.ui", &error) == 0)
    {
        g_printerr("Error loading file: %s\n", error->message);
        g_clear_error(&error);
        return 1;
    }
    
    window = GTK_WIDGET (gtk_builder_get_object(builder, "window"));
    grid = GTK_WIDGET (gtk_builder_get_object(builder, "grid"));

    gtk_builder_connect_signals(builder, NULL);

    make_projects_list(grid);

    gtk_widget_show_all(window);

    gtk_main();
    
    return 0;
}

build.ui 文件内容

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkWindow" id="window">
    <property name="can-focus">False</property>
    <child>
      <object class="GtkScrolledWindow" id="scrolled_window">
        <property name="visible">True</property>
        <property name="can-focus">True</property>
        <property name="shadow-type">in</property>
        <child>
          <object class="GtkViewport" id="viewport">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <child>
              <!-- n-columns=1 n-rows=1 -->
              <object class="GtkGrid" id="grid">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <child>
                  <placeholder/>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

问题原因与解决方案

核心问题

GTK的单选按钮组通过动态GSList维护,每次向组中添加新按钮时,该列表会被更新(新按钮会被加入列表)。原代码仅在创建第一个按钮时获取组指针,后续按钮始终使用初始的组列表(仅包含第一个按钮),导致新按钮实际创建了独立的新组,而非加入目标组。

修复代码

修改make_projects_list函数,在创建每个按钮后更新group指针为最新的组列表,还可简化逻辑无需单独处理第一个按钮:

void make_projects_list(GtkWidget *projects_grid)
{
    int n = 20;
        
    GSList *group = NULL;
    for (int i =0; i<n; i++)
    {
        GtkWidget *radio;
        char label[3];
        snprintf(label, 3, "%d", i);
        radio = gtk_radio_button_new_with_label(group, label);
        
        // 更新组指针为最新的组列表
        group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));

        gtk_grid_insert_row(GTK_GRID(projects_grid), i);
        gtk_grid_attach(GTK_GRID(projects_grid), radio, 1, i, 1,1); 
    }
}

修复说明

  • 初始group设为NULL,第一个按钮创建时GTK会自动生成新组
  • 每次创建新按钮后,调用gtk_radio_button_get_group获取最新的组列表,确保下一个按钮加入的是包含所有已创建按钮的组

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:32:09