如何在C语言GTK应用中创建类Discord风格的顶部栏组件?
实现GTK中Discord风格顶部栏的方案
1. 关闭系统默认标题栏
先隐藏窗口自带的系统标题栏,改用自定义组件替代:
GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); // 关闭系统装饰标题栏 gtk_window_set_decorated(window, FALSE);
2. 构建顶部栏容器
用水平布局的GtkBox作为顶部栏主容器,通过CSS设置深色背景、固定高度,匹配Discord视觉风格:
GtkWidget *titlebar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_size_request(titlebar, -1, 38); // 设置和Discord接近的高度 // 加载自定义样式 GtkCssProvider *css_provider = gtk_css_provider_new(); gtk_css_provider_load_from_data(css_provider, ".titlebar { background-color: #202225; border-bottom: 1px solid #000; }" ".titlebar button { background: transparent; border: none; color: #fff; padding: 8px 12px; }" ".titlebar button:hover { background-color: #36393f; }", -1, NULL); gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); gtk_widget_add_css_class(titlebar, "titlebar");
3. 拆分顶部栏三大区域
将水平容器拆分为左、中、右三个模块,分别对应Discord的「Logo/应用名」「导航栏」「功能/窗口控制按钮」:
左侧:Logo与应用名
GtkWidget *left_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); gtk_box_append(GTK_BOX(titlebar), left_box); // 添加应用图标(替换为你的自定义图标) GtkWidget *logo = gtk_image_new_from_icon_name("applications-internet"); gtk_box_append(GTK_BOX(left_box), logo); // 添加应用名称标签 GtkWidget *app_name = gtk_label_new("MyApp"); gtk_widget_add_css_class(app_name, "app-name"); gtk_css_provider_load_from_data(css_provider, ".app-name { color: #fff; font-weight: bold; padding: 0 8px; }", -1, NULL); gtk_box_append(GTK_BOX(left_box), app_name);
中间:导航按钮区
用GtkBox放置导航按钮,模拟Discord的频道切换效果:
GtkWidget *middle_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_append(GTK_BOX(titlebar), middle_box); gtk_widget_set_hexpand(middle_box, TRUE); // 让中间区域占据剩余空间 // 添加导航按钮 GtkWidget *home_btn = gtk_button_new_with_label("首页"); gtk_widget_add_css_class(home_btn, "nav-btn"); gtk_box_append(GTK_BOX(middle_box), home_btn); GtkWidget *msg_btn = gtk_button_new_with_label("消息"); gtk_widget_add_css_class(msg_btn, "nav-btn"); gtk_box_append(GTK_BOX(middle_box), msg_btn); // 导航按钮样式设置 gtk_css_provider_load_from_data(css_provider, ".nav-btn { color: #b9bbbe; background: transparent; border: none; padding: 0 16px; }" ".nav-btn:hover { color: #fff; background-color: #36393f; }" ".nav-btn.active { color: #fff; border-bottom: 2px solid #7289da; }", -1, NULL);
右侧:功能与窗口控制按钮
添加设置、最小化、最大化、关闭按钮,并绑定对应功能:
GtkWidget *right_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_append(GTK_BOX(titlebar), right_box); // 设置按钮 GtkWidget *settings_btn = gtk_button_new_from_icon_name("preferences-system"); gtk_widget_add_css_class(settings_btn, "titlebar-btn"); gtk_box_append(GTK_BOX(right_box), settings_btn); // 最小化按钮 GtkWidget *min_btn = gtk_button_new_from_icon_name("window-minimize"); gtk_widget_add_css_class(min_btn, "titlebar-btn"); g_signal_connect(min_btn, "clicked", G_CALLBACK(gtk_window_iconify), window); gtk_box_append(GTK_BOX(right_box), min_btn); // 最大化按钮 GtkWidget *max_btn = gtk_button_new_from_icon_name("window-maximize"); gtk_widget_add_css_class(max_btn, "titlebar-btn"); g_signal_connect(max_btn, "clicked", G_CALLBACK(gtk_window_maximize), window); gtk_box_append(GTK_BOX(right_box), max_btn); // 关闭按钮(hover时显示红色背景) GtkWidget *close_btn = gtk_button_new_from_icon_name("window-close"); gtk_widget_add_css_class(close_btn, "titlebar-btn"); gtk_widget_set_name(close_btn, "close-btn"); g_signal_connect(close_btn, "clicked", G_CALLBACK(gtk_window_destroy), window); gtk_css_provider_load_from_data(css_provider, "#close-btn:hover { background-color: #f04747; }", -1, NULL); gtk_box_append(GTK_BOX(right_box), close_btn);
4. 实现窗口拖拽功能
因为隐藏了系统标题栏,需要给自定义顶部栏添加拖拽移动、双击最大化/还原的功能:
static gboolean on_titlebar_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkWindow *window = GTK_WINDOW(data); if (event->button == GDK_BUTTON_PRIMARY) { gtk_window_begin_move_drag(window, event->button, event->root_x, event->root_y, event->time); } return TRUE; } static gboolean on_titlebar_double_click(GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkWindow *window = GTK_WINDOW(data); if (event->button == GDK_BUTTON_PRIMARY) { gtk_window_is_maximized(window) ? gtk_window_unmaximize(window) : gtk_window_maximize(window); } return TRUE; } // 绑定事件 g_signal_connect(titlebar, "button-press-event", G_CALLBACK(on_titlebar_press), window); g_signal_connect(titlebar, "double-click-event", G_CALLBACK(on_titlebar_double_click), window);
5. 整合到主窗口
将自定义标题栏绑定到窗口,添加主内容区域并启动GTK主循环:
gtk_window_set_titlebar(window, titlebar); // 主内容区域 GtkWidget *main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_window_set_child(window, main_box); // 显示所有组件 gtk_widget_show(window); gtk_widget_show_all(main_box); gtk_main();
内容的提问来源于stack exchange,提问作者vlad
相关产品推荐
相关产品推荐

