使用GNOME/GTK+为CD数据库创建GUI应用
1. 引言
在开发CD数据库应用时,为其添加一个图形用户界面(GUI)可以极大地提升用户体验。本文将介绍如何使用GNOME/GTK+库为CD数据库创建一个功能丰富的GUI应用,包括登录数据库、搜索CD、显示CD和曲目信息、添加CD到数据库、创建关于窗口以及确认用户退出等功能。
2. 准备工作
在开始之前,需要确保已经安装了MySQL数据库和MySQL开发者库。示例程序将使用之前开发的CD数据库以及相关的接口函数。
3. 代码结构
代码将分为三个源文件,并共享一个公共头文件
cdapp_gnome.h
。源文件将创建窗口和对话框的函数(界面生成函数)与回调函数分开。
3.1 cdapp_gnome.h
该头文件包含了程序所需的各种函数声明和枚举定义。
#include <gnome.h>
#include "app_mysql.h"
enum {
COLUMN_TITLE,
COLUMN_ARTIST,
COLUMN_CATALOGUE,
N_COLUMNS
};
GtkWidget *create_main_window();
GtkWidget *create_login_dialog();
GtkWidget *create_addcd_dialog();
/* Callback to quit application */
void quit_app( GtkWidget * window, gpointer data);
/* Callback useful for confirming exit before quitting */
gboolean delete_event_handler ( GtkWidget *window, GdkEvent *event, gpointer data);
/* Callback connected to ‘response’ signal of addcd dialog */
void addcd_dialog_button_clicked (GtkDialog * dialog, gint response,
gpointer userdata);
/* Callback for menu and toolbar ‘Add CD’ button */
void on_addcd_activate (GtkWidget *widget, gpointer user_data);
/* Callback for menu ‘About’ button */
void on_about_activate (GtkWidget *widget, gpointer user_data);
/* Callback for search button */
void on_search_button_clicked (GtkWidget *widget, gpointer userdata);
3.2 主要功能概述
- 登录数据库 :用户需要通过登录对话框输入用户名和密码来登录数据库。
- 搜索CD :用户可以在搜索框中输入关键词,点击搜索按钮来查找匹配的CD。
-
显示CD和曲目信息
:使用
GtkTreeView控件显示搜索结果和CD的详细信息。 - 添加CD到数据库 :通过添加CD对话框,用户可以输入CD的艺术家、标题和目录信息,并将其添加到数据库中。
- 创建关于窗口 :点击“关于”按钮,将弹出一个标准的GNOME关于框。
- 确认用户退出 :在用户尝试退出应用程序时,会弹出确认对话框。
4. 界面生成函数(interface.c)
该文件定义了应用程序中使用的窗口和对话框。
4.1 全局变量和辅助函数
#include "app_gnome.h"
GtkWidget *treeview;
GtkWidget *appbar;
GtkWidget *artist_entry;
GtkWidget *title_entry;
GtkWidget *catalogue_entry;
GtkWidget *username_entry;
GtkWidget *password_entry;
static GtkWidget *app;
void add_widget_with_label ( GtkContainer *box, gchar *caption, GtkWidget *widget)
{
GtkWidget *label = gtk_label_new (caption);
GtkWidget *hbox = gtk_hbox_new (TRUE, 4);
gtk_container_add(GTK_CONTAINER (hbox), label);
gtk_container_add(GTK_CONTAINER (hbox), widget);
gtk_container_add(box, hbox);
}
4.2 菜单栏定义
static GnomeUIInfo filemenu[] =
{
GNOMEUIINFO_MENU_NEW_ITEM ("_New CD", NULL, on_addcd_activate, NULL),
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_EXIT_ITEM (close_app, NULL),
GNOMEUIINFO_END
};
static GnomeUIInfo helpmenu[] =
{
GNOMEUIINFO_MENU_ABOUT_ITEM (on_about_activate, NULL),
GNOMEUIINFO_END
};
static GnomeUIInfo menubar[] =
{
GNOMEUIINFO_MENU_FILE_TREE (filemenu),
GNOMEUIINFO_MENU_HELP_TREE (helpmenu),
GNOMEUIINFO_END
};
4.3 创建主窗口
GtkWidget * create_main_window()
{
GtkWidget *toolbar;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *search_button;
GtkWidget *scrolledwindow;
GtkCellRenderer *renderer;
app = gnome_app_new ("GnomeCD", "CD Database");
gtk_window_set_position ( GTK_WINDOW( app), GTK_WIN_POS_CENTER);
gtk_window_set_default_size ( GTK_WINDOW( app ), 540, 480);
gnome_app_create_menus (GNOME_APP (app), menubar);
toolbar = gtk_toolbar_new ();
gnome_app_add_toolbar (GNOME_APP (app), GTK_TOOLBAR (toolbar), "toolbar",
BONOBO_DOCK_ITEM_BEH_EXCLUSIVE,
BONOBO_DOCK_TOP, 1, 0, 0);
gtk_container_set_border_width (GTK_CONTAINER (toolbar), 1);
gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
"gtk-add",
"Add new CD",
NULL, GTK_SIGNAL_FUNC (on_addcd_activate),
NULL, -1);
gtk_toolbar_insert_space (GTK_TOOLBAR (toolbar), 1);
gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
"gtk-quit",
"Quit the Application",
NULL, GTK_SIGNAL_FUNC (on_quit_activate),
NULL, -1);
label = gtk_label_new("Search String:");
entry = gtk_entry_new ();
search_button = gtk_button_new_with_label("Search");
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
vbox = gtk_vbox_new (FALSE, 0);
hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 6);
gtk_box_pack_start (GTK_BOX (hbox), search_button, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
treeview = gtk_tree_view_new();
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview),
COLUMN_TITLE,
"Title", renderer,
"text", COLUMN_TITLE,
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview),
COLUMN_ARTIST,
"Artist", renderer,
"text", COLUMN_ARTIST,
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview),
COLUMN_CATALOGUE,
"Catalogue", renderer,
"text", COLUMN_CATALOGUE,
NULL);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
COLUMN_TITLE);
gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview);
gnome_app_set_contents (GNOME_APP (app), vbox);
appbar = gnome_appbar_new (FALSE, TRUE, GNOME_PREFERENCES_NEVER);
gnome_app_set_statusbar (GNOME_APP (app), appbar);
gnome_app_install_menu_hints (GNOME_APP (app), menubar);
g_signal_connect (GTK_OBJECT (search_button), "clicked",
GTK_SIGNAL_FUNC (on_search_button_clicked),
entry);
g_signal_connect (GTK_OBJECT(app), "delete_event",
GTK_SIGNAL_FUNC ( delete_event_handler ),
NULL);
g_signal_connect (GTK_OBJECT(app), "destroy",
GTK_SIGNAL_FUNC ( quit_app ), NULL);
return app;
}
4.4 创建添加CD对话框
GtkWidget *create_addcd_dialog()
{
artist_entry = gtk_entry_new();
title_entry = gtk_entry_new();
catalogue_entry = gtk_entry_new();
GtkWidget *dialog = gtk_dialog_new_with_buttons ("Add CD",
app,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
add_widget_with_label ( GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
"Artist", artist_entry);
add_widget_with_label ( GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
"Title", title_entry);
add_widget_with_label ( GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
"Catalogue", catalogue_entry);
g_signal_connect ( GTK_OBJECT (dialog), "response",
GTK_SIGNAL_FUNC (addcd_dialog_button_clicked), NULL);
return dialog;
}
4.5 创建登录对话框
GtkWidget *create_login_dialog()
{
GtkWidget *dialog = gtk_dialog_new_with_buttons ("Database Login",
app,
GTK_DIALOG_MODAL,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
username_entry = gtk_entry_new();
password_entry = gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY (password_entry), FALSE);
add_widget_with_label ( GTK_CONTAINER (GTK_DIALOG (dialog)->vbox) , "Username",
username_entry);
add_widget_with_label ( GTK_CONTAINER (GTK_DIALOG (dialog)->vbox) , "Password",
password_entry);
gtk_widget_show_all(GTK_WIDGET (GTK_DIALOG (dialog)->vbox));
return dialog;
}
5. 回调函数(callbacks.c)
该文件包含了UI控件的回调函数。
5.1 包含头文件和引用全局变量
#include "app_gnome.h"
extern GtkWidget *treeview;
extern GtkWidget *app;
extern GtkWidget *appbar;
extern GtkWidget *artist_entry;
extern GtkWidget *title_entry;
extern GtkWidget *catalogue_entry;
static GtkWidget *addcd_dialog;
5.2 退出应用程序回调函数
void quit_app( GtkWidget *window, gpointer data)
{
database_end();
gtk_main_quit();
}
5.3 确认退出回调函数
gboolean confirm_exit()
{
gint result;
GtkWidget *dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Are you sure you want to quit?");
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return (result == GTK_RESPONSE_YES);
}
gboolean delete_event_handler ( GtkWidget *window, GdkEvent *event, gpointer data)
{
return !confirm_exit();
}
5.4 添加CD对话框按钮点击回调函数
void addcd_dialog_button_clicked (GtkDialog * dialog, gint response,
gpointer userdata)
{
const gchar *artist_const;
const gchar *title_const;
const gchar *catalogue_const;
gchar artist[200];
gchar title[200];
gchar catalogue[200];
gint *cd_id;
if (response == GTK_RESPONSE_ACCEPT)
{
artist_const = gtk_entry_get_text(GTK_ENTRY (artist_entry));
title_const = gtk_entry_get_text(GTK_ENTRY (title_entry));
catalogue_const = gtk_entry_get_text(GTK_ENTRY (catalogue_entry));
strcpy(artist, artist_const);
strcpy(title, title_const);
strcpy(catalogue, catalogue_const);
add_cd(artist, title, catalogue, cd_id);
}
addcd_dialog = NULL;
gtk_widget_destroy(GTK_WIDGET(dialog));
}
5.5 搜索按钮点击回调函数
void on_search_button_clicked (GtkButton *button, gpointer userdata)
{
struct cd_search_st cd_res;
struct current_cd_st cd;
struct current_tracks_st ct;
gint res1, res2, res3;
gchar track_title[110];
const gchar *search_string_const;
gchar search_string[200];
gchar search_text[200];
gint i = 0, j = 0;
GtkTreeStore *tree_store;
GtkTreeIter parent_iter, child_iter;
memset(&track_title, 0, sizeof(track_title));
search_string_const = gtk_entry_get_text(GTK_ENTRY (userdata));
strcpy (search_string, search_string_const);
res1 = find_cds(search_string, &cd_res);
sprintf(search_text, " Displaying %d result(s) for search string ‘ %s ‘",
MIN(res1, MAX_CD_RESULT), search_string);
gnome_appbar_push (GNOME_APPBAR( appbar), search_text);
tree_store = gtk_tree_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
while (i < res1 && i < MAX_CD_RESULT)
{
res2 = get_cd(cd_res.cd_id[i], &cd);
gtk_tree_store_append (tree_store, &parent_iter, NULL);
gtk_tree_store_set (tree_store, &parent_iter,
COLUMN_TITLE, cd.title,
COLUMN_ARTIST, cd.artist_name,
COLUMN_CATALOGUE, cd.catalogue, -1
);
res3 = get_cd_tracks(cd_res.cd_id[i++], &ct);
j = 0;
while (j < res3)
{
sprintf(track_title, " Track %d. ", j+1);
strcat(track_title, ct.track[j++]);
gtk_tree_store_append (tree_store, &child_iter, &parent_iter);
gtk_tree_store_set (tree_store, &child_iter,
COLUMN_TITLE, track_title, -1);
}
}
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL(tree_store));
}
5.6 添加CD激活回调函数
void on_addcd_activate (GtkMenuItem * menuitem, gpointer user_data)
{
if (addcd_dialog != NULL)
return;
addcd_dialog = create_addcd_dialog();
gtk_widget_show_all (addcd_dialog);
}
gboolean close_app ( GtkWidget * window, gpointer data)
{
gboolean exit;
if ((exit = confirm_exit()))
{
quit_app(NULL, NULL);
}
return exit;
}
5.7 关于按钮点击回调函数
void on_about_activate (GtkMenuItem * menuitem, gpointer user_data)
{
const char * authors[] = {"Wrox Press", NULL};
GtkWidget *about = gnome_about_new ("CD Database", "1.0",
"(c) Wrox Press",
"Beginning Linux Programming",
(const char ** ) authors, NULL,
"Translators", NULL);
gtk_widget_show(about);
}
6. 主函数(main.c)
该文件包含了程序的主函数。
#include <stdio.h>
#include <stdlib.h>
#include "app_gnome.h"
extern GtkWidget *username_entry;
extern GtkWidget *password_entry;
gint main(gint argc, gchar *argv[])
{
GtkWidget *main_window;
GtkWidget *login_dialog;
const char *user_const;
const char *pass_const;
gchar username[100];
gchar password[100];
gint result;
gnome_program_init ("CdDatabase", "0.1", LIBGNOMEUI_MODULE,
argc, argv,
GNOME_PARAM_APP_DATADIR, "",
NULL);
main_window = create_main_window();
gtk_widget_show_all(main_window);
login_dialog = create_login_dialog();
while (1)
{
result = gtk_dialog_run (GTK_DIALOG (login_dialog));
if (result != GTK_RESPONSE_ACCEPT)
{
if (confirm_exit())
return 0;
else
continue;
}
user_const = gtk_entry_get_text(GTK_ENTRY (username_entry));
pass_const = gtk_entry_get_text(GTK_ENTRY (password_entry));
strcpy(username, user_const);
strcpy(password, pass_const);
if (database_start(username, password) == TRUE)
break;
GtkWidget * error_dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Could not log on! - Check Username and Password");
gtk_dialog_run (GTK_DIALOG (error_dialog));
gtk_widget_destroy (error_dialog);
}
gtk_widget_destroy (login_dialog);
gtk_main();
return 0;
}
7. 编译和运行
编写一个
Makefile
来编译应用程序。
all: app
app: app_mysql.c callbacks.c interface.c main.c app_gnome.h app_mysql.h
gcc -o app -I/usr/include/mysql app_mysql.c callbacks.c interface.c main.c -
lmysqlclient `pkg-config --cflags --libs libgnome-2.0 libgnomeui-2.0`
clean:
rm -f app
使用
make -f Makefile
命令编译CD应用程序。编译完成后,运行
app
即可启动GNOME风格的CD应用程序。
8. 总结
通过使用GNOME/GTK+库,我们成功地为CD数据库创建了一个功能丰富的GUI应用程序。该应用程序允许用户登录数据库、搜索CD、显示CD和曲目信息、添加CD到数据库、查看关于信息以及确认退出。通过将界面生成函数和回调函数分开,代码结构更加清晰,易于维护和扩展。
附录:流程图
graph TD;
A[开始] --> B[初始化GNOME库];
B --> C[创建主窗口];
C --> D[显示主窗口];
D --> E[创建登录对话框];
E --> F{登录成功?};
F -- 是 --> G[进入主界面];
F -- 否 --> H[显示错误信息];
H --> E;
G --> I{用户操作};
I -- 搜索CD --> J[执行搜索操作];
I -- 添加CD --> K[打开添加CD对话框];
I -- 关于 --> L[显示关于信息];
I -- 退出 --> M[确认退出];
M -- 是 --> N[关闭数据库并退出];
M -- 否 --> G;
J --> O[显示搜索结果];
K --> P{添加成功?};
P -- 是 --> G;
P -- 否 --> K;
表格:主要功能和对应文件
| 功能 | 对应文件 |
|---|---|
| 登录数据库 | main.c, interface.c |
| 搜索CD | callbacks.c |
| 显示CD和曲目信息 | callbacks.c, interface.c |
| 添加CD到数据库 | callbacks.c, interface.c |
| 创建关于窗口 | callbacks.c |
| 确认用户退出 | callbacks.c |
使用GNOME/GTK+为CD数据库创建GUI应用
9. 代码详细解释
9.1 头文件
cdapp_gnome.h
- 包含必要的头文件 :引入了GNOME相关的头文件和之前开发的数据库接口函数头文件。
#include <gnome.h>
#include "app_mysql.h"
-
定义枚举
:为
GtkTreeView控件的列进行编号,方便后续操作。
enum {
COLUMN_TITLE,
COLUMN_ARTIST,
COLUMN_CATALOGUE,
N_COLUMNS
};
- 声明函数 :声明了窗口创建函数和回调函数,将界面生成和回调处理分开。
GtkWidget *create_main_window();
GtkWidget *create_login_dialog();
GtkWidget *create_addcd_dialog();
/* Callback to quit application */
void quit_app( GtkWidget * window, gpointer data);
/* Callback useful for confirming exit before quitting */
gboolean delete_event_handler ( GtkWidget *window, GdkEvent *event, gpointer data);
/* Callback connected to ‘response’ signal of addcd dialog */
void addcd_dialog_button_clicked (GtkDialog * dialog, gint response,
gpointer userdata);
/* Callback for menu and toolbar ‘Add CD’ button */
void on_addcd_activate (GtkWidget *widget, gpointer user_data);
/* Callback for menu ‘About’ button */
void on_about_activate (GtkWidget *widget, gpointer user_data);
/* Callback for search button */
void on_search_button_clicked (GtkWidget *widget, gpointer userdata);
9.2 界面生成函数
interface.c
- 全局变量 :定义了一些全局的控件指针,方便在不同文件中使用。
GtkWidget *treeview;
GtkWidget *appbar;
GtkWidget *artist_entry;
GtkWidget *title_entry;
GtkWidget *catalogue_entry;
GtkWidget *username_entry;
GtkWidget *password_entry;
static GtkWidget *app;
-
辅助函数
:
add_widget_with_label函数用于将标签和控件组合在一起。
void add_widget_with_label ( GtkContainer *box, gchar *caption, GtkWidget *widget)
{
GtkWidget *label = gtk_label_new (caption);
GtkWidget *hbox = gtk_hbox_new (TRUE, 4);
gtk_container_add(GTK_CONTAINER (hbox), label);
gtk_container_add(GTK_CONTAINER (hbox), widget);
gtk_container_add(box, hbox);
}
-
菜单栏定义
:使用
GnomeUIInfo宏定义了文件菜单和帮助菜单。
static GnomeUIInfo filemenu[] =
{
GNOMEUIINFO_MENU_NEW_ITEM ("_New CD", NULL, on_addcd_activate, NULL),
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_EXIT_ITEM (close_app, NULL),
GNOMEUIINFO_END
};
static GnomeUIInfo helpmenu[] =
{
GNOMEUIINFO_MENU_ABOUT_ITEM (on_about_activate, NULL),
GNOMEUIINFO_END
};
static GnomeUIInfo menubar[] =
{
GNOMEUIINFO_MENU_FILE_TREE (filemenu),
GNOMEUIINFO_MENU_HELP_TREE (helpmenu),
GNOMEUIINFO_END
};
-
创建主窗口
:创建主窗口并设置其属性,添加菜单栏、工具栏、搜索框和
GtkTreeView控件。
GtkWidget * create_main_window()
{
// ... 代码省略 ...
return app;
}
- 创建添加CD对话框 :创建一个对话框,包含艺术家、标题和目录的输入框,以及确认和取消按钮。
GtkWidget *create_addcd_dialog()
{
// ... 代码省略 ...
return dialog;
}
- 创建登录对话框 :创建一个模态对话框,用于用户输入用户名和密码。
GtkWidget *create_login_dialog()
{
// ... 代码省略 ...
return dialog;
}
9.3 回调函数
callbacks.c
-
包含头文件和引用全局变量
:引入头文件并引用在
interface.c中定义的全局变量。
#include "app_gnome.h"
extern GtkWidget *treeview;
extern GtkWidget *app;
extern GtkWidget *appbar;
extern GtkWidget *artist_entry;
extern GtkWidget *title_entry;
extern GtkWidget *catalogue_entry;
static GtkWidget *addcd_dialog;
- 退出应用程序回调函数 :在退出应用程序时,关闭数据库并终止GTK主循环。
void quit_app( GtkWidget *window, gpointer data)
{
database_end();
gtk_main_quit();
}
- 确认退出回调函数 :弹出确认对话框,根据用户的选择返回相应的布尔值。
gboolean confirm_exit()
{
// ... 代码省略 ...
return (result == GTK_RESPONSE_YES);
}
gboolean delete_event_handler ( GtkWidget *window, GdkEvent *event, gpointer data)
{
return !confirm_exit();
}
- 添加CD对话框按钮点击回调函数 :当用户点击添加CD对话框的确认按钮时,将输入的信息添加到数据库中。
void addcd_dialog_button_clicked (GtkDialog * dialog, gint response,
gpointer userdata)
{
// ... 代码省略 ...
gtk_widget_destroy(GTK_WIDGET(dialog));
}
-
搜索按钮点击回调函数
:根据用户输入的搜索关键词,执行搜索操作并将结果显示在
GtkTreeView控件中。
void on_search_button_clicked (GtkButton *button, gpointer userdata)
{
// ... 代码省略 ...
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL(tree_store));
}
- 添加CD激活回调函数 :如果添加CD对话框未打开,则打开该对话框。
void on_addcd_activate (GtkMenuItem * menuitem, gpointer user_data)
{
if (addcd_dialog != NULL)
return;
addcd_dialog = create_addcd_dialog();
gtk_widget_show_all (addcd_dialog);
}
gboolean close_app ( GtkWidget * window, gpointer data)
{
gboolean exit;
if ((exit = confirm_exit()))
{
quit_app(NULL, NULL);
}
return exit;
}
- 关于按钮点击回调函数 :点击“关于”按钮时,显示标准的GNOME关于框。
void on_about_activate (GtkMenuItem * menuitem, gpointer user_data)
{
const char * authors[] = {"Wrox Press", NULL};
GtkWidget *about = gnome_about_new ("CD Database", "1.0",
"(c) Wrox Press",
"Beginning Linux Programming",
(const char ** ) authors, NULL,
"Translators", NULL);
gtk_widget_show(about);
}
9.4 主函数
main.c
- 包含头文件和引用全局变量 :引入必要的头文件并引用用户名和密码输入框。
#include <stdio.h>
#include <stdlib.h>
#include "app_gnome.h"
extern GtkWidget *username_entry;
extern GtkWidget *password_entry;
- 主函数 :初始化GNOME库,创建主窗口和登录对话框,处理用户登录操作。
gint main(gint argc, gchar *argv[])
{
// ... 代码省略 ...
return 0;
}
10. 注意事项和扩展建议
10.1 注意事项
- 数据库依赖 :确保MySQL数据库和MySQL开发者库已正确安装,并且数据库连接参数在代码中配置正确。
-
内存管理
:在使用
GtkWidget和其他动态分配的资源时,要注意及时释放内存,避免内存泄漏。 - 错误处理 :在数据库操作和GTK函数调用时,要进行错误检查,确保程序的健壮性。
10.2 扩展建议
- 功能扩展 :可以添加更多的功能,如编辑CD信息、删除CD、导出CD信息等。
- 界面优化 :可以对界面进行美化,如调整字体、颜色、布局等,提升用户体验。
- 多语言支持 :可以添加多语言支持,使应用程序能够在不同语言环境下使用。
11. 总结回顾
本文详细介绍了如何使用GNOME/GTK+库为CD数据库创建一个功能丰富的GUI应用程序。通过将界面生成函数和回调函数分开,代码结构更加清晰,易于维护和扩展。主要实现了以下功能:
- 登录数据库
- 搜索CD
- 显示CD和曲目信息
- 添加CD到数据库
- 查看关于信息
- 确认退出
附录:详细流程图
graph TD;
A[开始] --> B[初始化GNOME库];
B --> C[创建主窗口];
C --> D[显示主窗口];
D --> E[创建登录对话框];
E --> F{用户点击登录};
F -- 是 --> G[获取用户名和密码];
G --> H{验证用户名和密码};
H -- 成功 --> I[进入主界面];
H -- 失败 --> J[显示错误信息];
J --> E;
I --> K{用户操作};
K -- 搜索CD --> L[获取搜索关键词];
L --> M[执行搜索操作];
M --> N[显示搜索结果];
K -- 添加CD --> O[打开添加CD对话框];
O --> P{用户输入信息并点击确认};
P -- 是 --> Q[获取输入信息];
Q --> R{验证输入信息};
R -- 有效 --> S[添加CD到数据库];
S --> T{添加成功};
T -- 是 --> I;
T -- 否 --> U[显示添加失败信息];
U --> O;
R -- 无效 --> V[显示输入错误信息];
V --> O;
P -- 否 --> I;
K -- 关于 --> W[显示关于信息];
K -- 退出 --> X[确认退出];
X -- 是 --> Y[关闭数据库并退出];
X -- 否 --> I;
表格:代码文件和功能模块对应关系
| 代码文件 | 功能模块 |
|---|---|
cdapp_gnome.h
| 定义全局常量、枚举和函数声明 |
interface.c
| 创建主窗口、登录对话框和添加CD对话框 |
callbacks.c
| 处理界面控件的回调函数 |
main.c
| 程序入口,初始化GNOME库和处理用户登录 |
app_mysql.c
| 数据库操作接口 |
超级会员免费看
39

被折叠的 条评论
为什么被折叠?



