目录
主要思路
界面设计(以主界面为例)
后端注册
设计总结
后端登录
设计思路
界面展示
主界面
登录界面
注册界面
源代码(详细注释)
Makefile
gtk_window.c(前端)
beautify.c(样式美化)
rear_end.c(后端)
项目完整源码可移步到:
更多文章和源码在我的个人博客:首页 (niuniu65.top)
如需咨询请添加个人微信:a15135158368
欢迎叨扰,互相交流
创建主窗口:
使用
gtk_window_new(GTK_WINDOW_TOPLEVEL)
创建一个主窗口,并设置窗口的标题和默认尺寸。设置窗口居中显示并允许调整大小。
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(main_window), "管理员界面"); gtk_window_set_default_size(GTK_WINDOW(main_window), 1024, 600); gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER);
使用 Overlay 容器进行叠加布局:
创建一个
GtkOverlay
容器,将其作为主窗口的子控件。Overlay 容器允许在同一窗口中叠加多个控件,如背景图片和网格布局。
overlay = gtk_overlay_new(); gtk_container_add(GTK_CONTAINER(main_window), overlay);
添加背景图片:
在 Overlay 容器中添加背景图片,使其充满整个窗口。
使用
gtk_overlay_add_overlay()
将图片添加到 Overlay 容器,并设置图片水平和垂直填充。background_image = gtk_image_new_from_file("background.jpg"); gtk_overlay_add_overlay(GTK_OVERLAY(overlay), background_image); gtk_widget_set_halign(background_image, GTK_ALIGN_FILL); gtk_widget_set_valign(background_image, GTK_ALIGN_FILL);
网格布局的创建与配置:
创建一个
GtkGrid
网格布局,设置行间距和列间距,并为布局设置边框宽度。网格布局用于放置标题和按钮,使界面布局整齐有序。
grid = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(grid), 20); gtk_grid_set_column_spacing(GTK_GRID(grid), 30); gtk_container_set_border_width(GTK_CONTAINER(grid), 30);
设置主标题:
创建一个标签作为主标题,使用
gtk_label_set_markup()
设置字体和颜色样式。将标题添加到网格布局中,并使其跨越多列,以突出显示。
main_title = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(main_title), "森林火灾监控预警系统"); gtk_grid_attach(GTK_GRID(grid), main_title, 0, 0, 3, 2);
创建登录和注册按钮:
分别创建登录和注册按钮,并自定义按钮的颜色和字体大小。
将按钮添加到网格布局中,并设置其位置。
login_button = gtk_button_new_with_label("登录"); customize_button_style(login_button, "#00FFFF", 28, TRUE); gtk_grid_attach(GTK_GRID(grid), login_button, 0, 3, 1, 1); register_button = gtk_button_new_with_label("注册"); customize_button_style(register_button, "#00FFFF", 28, TRUE); gtk_grid_attach(GTK_GRID(grid), register_button, 2, 3, 1, 1);
将网格布局添加到 Overlay 容器中:
将已经配置好的网格布局添加到 Overlay 容器中,并设置其居中显示。
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), grid); gtk_widget_set_halign(grid, GTK_ALIGN_CENTER); gtk_widget_set_valign(grid, GTK_ALIGN_CENTER);
信号连接:
连接窗口关闭信号以退出程序,并为按钮点击事件绑定相应的回调函数。
g_signal_connect(main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(login_button, "clicked", G_CALLBACK(main_window_to_login_window), NULL); g_signal_connect(register_button, "clicked", G_CALLBACK(main_window_to_register_window), NULL);
打开数据库连接:
通过
sqlite3_open()
函数打开一个 SQLite 数据库连接,确保在操作之前已经连接到数据库。sqlite3* db; sqlite3_open("user.db", &db);
获取用户输入:
使用
gtk_entry_get_text()
获取用户在注册界面输入的 ID、密码和验证码,使用gtk_label_get_text()
获取当前显示的验证码。const gchar* id = gtk_entry_get_text(GTK_ENTRY(register_entry_id)); const gchar* paswd = gtk_entry_get_text(GTK_ENTRY(register_entry_paswd)); const gchar* yzm_new = gtk_entry_get_text(GTK_ENTRY(register_entry_yzm)); const gchar* yzm_old = gtk_label_get_text(GTK_LABEL(register_yzm));
检查 ID 是否已注册:
通过查询数据库,检查用户输入的 ID 是否已经存在。使用
sqlite3_get_table()
执行查询,结果存储在table
中。char sql1[256] = ""; snprintf(sql1, sizeof(sql1), "SELECT paswd FROM user WHERE id=\"%s\";", id); sqlite3_get_table(db, sql1, &table, &row, &column, &errmsg);
验证输入信息:
ID 和密码长度检查:如果 ID 或密码长度小于或等于 6 位,弹出错误对话框,并清空输入框。
验证码验证:如果用户输入的验证码与显示的验证码不匹配,弹出错误对话框,并清空输入框。
if (strlen(id) <= 6) { // 错误对话框和清空操作 } else if (strlen(paswd) <= 6) { // 错误对话框和清空操作 } else if (strcmp(yzm_new, yzm_old) != 0) { // 错误对话框和清空操作 }
插入新用户数据到数据库:
如果 ID 和密码符合要求,并且验证码正确,将用户输入的数据插入到数据库中。使用
sqlite3_exec()
执行插入操作。如果插入成功,弹出“注册成功”对话框,隐藏注册窗口并显示登录窗口。
snprintf(sql, sizeof(sql), "INSERT INTO user VALUES(\"%s\", \"%s\");", id, paswd); sqlite3_exec(db, sql, NULL, NULL, &errmsg); if (errmsg != NULL) { // 错误处理 } else { // 注册成功对话框和窗口切换 }
处理 ID 已注册的情况:
如果查询结果表明 ID 已经存在,弹出错误对话框,提示用户该 ID 已经被注册。
清空输入框并重新生成验证码。
if (row != 0) { GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "该ID已经被注册!"); // 错误对话框和清空操作 }
关闭数据库连接:
在函数的最后,确保数据库连接被关闭,防止资源泄漏。
sqlite3_close(db);
设计总结
该函数的设计集中在用户输入的验证和数据库操作上。
通过检查用户输入的 ID 是否已被注册,然后通过验证输入的长度和验证码来确保数据的有效性
如果所有验证通过,将数据插入数据库并切换窗口。
获取用户输入的信息
在登录功能中,首先通过
gtk_entry_get_text
获取用户在 ID、密码、验证码输入框中的输入内容。代码示例:
const gchar *id = gtk_entry_get_text(GTK_ENTRY(login_entry_id)); const gchar *paswd = gtk_entry_get_text(GTK_ENTRY(login_entry_paswd)); const gchar *yzm_new = gtk_entry_get_text(GTK_ENTRY(login_entry_yzm)); const gchar *yzm_old = gtk_label_get_text(GTK_LABEL(login_yzm));
打开数据库
使用
sqlite3_open
打开 SQLite 数据库文件user.db
以便在后续操作中进行用户信息的查询和验证。代码示例:
sqlite3 *db; sqlite3_open("user.db", &db);
生成查询语句
根据用户输入的 ID,生成查询 SQL 语句,查询数据库中是否存在对应的用户及其密码。
代码示例:
char sql[100] = ""; sprintf(sql, "SELECT paswd FROM user WHERE id=\"%s\";", id);
执行查询
使用
sqlite3_get_table
执行查询语句,并将查询结果存储在表格中以进行后续的密码和验证码验证。代码示例:
char **table = NULL; int row, column; char *errmsg = NULL; sqlite3_get_table(db, sql, &table, &row, &column, &errmsg);
验证用户 ID 是否存在
如果查询结果中没有返回行数据(
row == 0
),表示用户输入的 ID 尚未注册,此时清空输入框并重新生成验证码。代码示例:
if (row == 0) { gtk_entry_set_text(GTK_ENTRY(login_entry_id), ""); gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); do_yzm(GTK_LABEL(login_yzm)); gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); sqlite3_close(db); return; }
验证密码是否正确
对比用户输入的密码与数据库中存储的密码。如果不匹配,清空密码输入框并重新生成验证码。
代码示例:
else if (strcmp(paswd, table[1]) == 0) { // 密码匹配,继续验证验证码 } else { printf("密码错误\n"); gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); do_yzm(GTK_LABEL(login_yzm)); gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); sqlite3_close(db); }
验证验证码
如果密码正确,进一步验证用户输入的验证码是否与显示的验证码匹配。如果匹配,表示登录成功,隐藏登录窗口并显示功能窗口。
代码示例:
if (strcmp(yzm_new, yzm_old) != 0) { printf("验证码错误\n"); gtk_entry_set_text(GTK_ENTRY(login_entry_id), ""); gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); do_yzm(GTK_LABEL(login_yzm)); gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); sqlite3_close(db); return; } else { // 登录成功,切换窗口 gtk_widget_hide(login_window); gtk_widget_show_all(function_window); }
关闭数据库
在函数结束前,确保关闭数据库连接以避免资源泄漏。
代码示例:
sqlite3_close(db);
# 链接库
LIBS = `pkg-config --cflags --libs gtk+-3.0` -lsqlite3 -lpango-1.0 -lgdk-3 -latk-1.0 -lgobject-2.0 -lgio-2.0 -lglib-2.0
如果以上链接编译不通过,可以加入以下编译标志,也就是直接在Linux下找到gtk3下载的路径
# 编译标志
CFLAGS = -std=gnu11 -I/usr/include/glib-2.0/ -I/usr/include/atk-1.0/ \
-I/usr/include/gdk-pixbuf-2.0/ -I/usr/include/cairo/ \
-I/usr/include/pango-1.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ \
-I/usr/include/gtk-3.0/ -I/usr/include/harfbuzz -I/usr/include/freetype2 \
-I/usr/include/libpng16 -I/usr/include/sysprof-6 -pthread
/**
******************************************************************************
* @file : gtk_window.c
* @author : niuniu
* @brief : gtk界面设计
* @attention : None
* @date : 2024/8/15
******************************************************************************
*/
#include
#include "gtk_window.h"
GtkWidget *main_window;
GtkWidget *login_window;
GtkWidget *register_window;
GtkWidget *function_window;
GtkWidget* login_entry_id;
GtkWidget* register_entry_id;
GtkWidget* login_yzm;
GtkWidget* login_entry_paswd;
GtkWidget* login_entry_yzm;
GtkWidget* register_yzm;
GtkWidget* register_entry_id;
GtkWidget* register_entry_paswd;
GtkWidget* register_entry_name;
GtkWidget* register_entry_level;
GtkWidget* register_entry_yzm;
void main_window_to_login_window(GtkButton* btn, gpointer user_data);
void main_window_to_register_window(GtkButton* btn, gpointer user_data);
void login_window_to_register_window(GtkButton* btn, gpointer user_data);
void register_window_to_login_window(GtkButton* btn, gpointer user_data);
void login_window_to_function_window(GtkButton* btn, gpointer user_data);
void window_init()
{
main_window_init();
login_window_init();
register_window_init();
}
//-----------------------------------------------------------------------------------------
// -------》》》》》》》》》》* ui设计 *《《《《《《《《《《《《《《《《《《《----------------------
//-----------------------------------------------------------------------------------------
// 初始化主窗口
void main_window_init()
{
GtkWidget *overlay; // Overlay 容器,用于叠加控件
GtkWidget *grid; // 网格布局,用于布局按钮和标题
GtkWidget *login_button; // 登录按钮
GtkWidget *register_button; // 注册按钮
GtkWidget *background_image; // 背景图片
GtkWidget *main_title; // 主标题
// 创建主窗口并设置标题
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(main_window), "管理员界面"); // 设置窗口标题为“管理员界面”
gtk_window_set_default_size(GTK_WINDOW(main_window), 1024, 600); // 设置窗口默认大小为 1024x600
// 设置窗口在屏幕中央显示
gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER);
// 创建 Overlay 容器
overlay = gtk_overlay_new(); // 创建一个 Overlay 容器,用于在窗口中叠加控件
gtk_container_add(GTK_CONTAINER(main_window), overlay); // 将 Overlay 容器添加到主窗口中
// 创建背景图片
background_image = gtk_image_new_from_file("background.jpg"); // 从文件加载背景图片
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), background_image); // 将背景图片添加到 Overlay 中
gtk_widget_set_halign(background_image, GTK_ALIGN_FILL); // 设置背景图片水平填充
gtk_widget_set_valign(background_image, GTK_ALIGN_FILL); // 设置背景图片垂直填充
// 创建网格布局
grid = gtk_grid_new(); // 创建一个新的网格布局
gtk_grid_set_row_spacing(GTK_GRID(grid), 20); // 设置网格行间距为 20 像素
gtk_grid_set_column_spacing(GTK_GRID(grid), 30); // 设置网格列间距为 30 像素
gtk_container_set_border_width(GTK_CONTAINER(grid), 30); // 设置网格布局的边框宽度为 30 像素
// 创建标题并设置样式为橙色
main_title = gtk_label_new(NULL); // 创建一个空的标签控件
gtk_label_set_markup(GTK_LABEL(main_title), "森林火灾监控预警系统");
// 使用标记设置标签的字体大小和颜色
gtk_widget_set_halign(main_title, GTK_ALIGN_CENTER); // 设置标题标签水平居中
gtk_widget_set_size_request(main_title, 300, 100); // 设置标题的最小宽度为 300 像素,高度为 100 像素
gtk_grid_attach(GTK_GRID(grid), main_title, 0, 0, 3, 2); // 将标题标签添加到网格布局中,跨越 3 列和 2 行
// 创建登录按钮
login_button = gtk_button_new_with_label("登录"); // 创建一个带有“登录”文本的按钮
gtk_widget_set_size_request(login_button, 100, 40); // 设置登录按钮的最小宽度为 100 像素,高度为 40 像素
customize_button_style(login_button, "#00FFFF", 28, TRUE); // 自定义按钮样式,设置颜色和字体大小
gtk_grid_attach(GTK_GRID(grid), login_button, 0, 3, 1, 1); // 将登录按钮添加到网格布局的第 0 列,第 3 行
// 创建注册按钮
register_button = gtk_button_new_with_label("注册"); // 创建一个带有“注册”文本的按钮
customize_button_style(register_button, "#00FFFF", 28, TRUE); // 自定义按钮样式,设置颜色和字体大小
gtk_widget_set_size_request(register_button, 100, 40); // 设置注册按钮的最小宽度为 100 像素,高度为 40 像素
gtk_grid_attach(GTK_GRID(grid), register_button, 2, 3, 1, 1); // 将注册按钮添加到网格布局的第 2 列,第 3 行
// 将网格布局添加到 Overlay 容器中
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), grid); // 将网格布局添加到 Overlay 中
gtk_widget_set_halign(grid, GTK_ALIGN_CENTER); // 设置网格布局水平居中
gtk_widget_set_valign(grid, GTK_ALIGN_CENTER); // 设置网格布局垂直居中
// 连接信号
g_signal_connect(main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 当窗口关闭时退出 GTK 主循环
g_signal_connect(login_button, "clicked", G_CALLBACK(main_window_to_login_window), NULL); // 当点击登录按钮时,切换到登录窗口
g_signal_connect(register_button, "clicked", G_CALLBACK(main_window_to_register_window), NULL); // 当点击注册按钮时,切换到注册窗口
}
// 初始化登录窗口
void login_window_init()
{
GtkWidget *overlay; // Overlay 容器,用于叠加控件
GtkWidget *grid; // 网格布局,用于布局控件
GtkWidget *login_id_label; // 账号标签
GtkWidget *login_paswd_label; // 密码标签
GtkWidget *login_title; // 登录界面标题
GtkWidget *login_ok_button; // 登录按钮
GtkWidget *login_to_register_button; // 注册按钮
GtkWidget *background_image; // 背景图片
// 创建登录窗口并设置标题
login_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(login_window), "监控预警系统——管理员"); // 设置窗口标题为“监控预警系统——管理员”
gtk_window_set_default_size(GTK_WINDOW(login_window), 1024, 600); // 设置窗口默认大小为 1024x600
// 设置窗口在屏幕中央显示
gtk_window_set_position(GTK_WINDOW(login_window), GTK_WIN_POS_CENTER);
// 设置窗口可调整大小
gtk_window_set_resizable(GTK_WINDOW(main_window), TRUE); // 允许用户调整窗口大小
// 创建 Overlay 容器
overlay = gtk_overlay_new(); // 创建一个 Overlay 容器,用于在窗口中叠加控件
gtk_container_add(GTK_CONTAINER(login_window), overlay); // 将 Overlay 容器添加到登录窗口中
// 创建背景图片
background_image = gtk_image_new_from_file("background.jpg"); // 从文件加载背景图片
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), background_image); // 将背景图片添加到 Overlay 中
gtk_widget_set_halign(background_image, GTK_ALIGN_FILL); // 设置背景图片水平填充
gtk_widget_set_valign(background_image, GTK_ALIGN_FILL); // 设置背景图片垂直填充
gtk_widget_set_hexpand(background_image, TRUE); // 使背景图片水平扩展以填满窗口
gtk_widget_set_vexpand(background_image, TRUE); // 使背景图片垂直扩展以填满窗口
// 创建网格布局
grid = gtk_grid_new(); // 创建一个新的网格布局
gtk_grid_set_row_spacing(GTK_GRID(grid), 20); // 设置网格行间距为 20 像素
gtk_grid_set_column_spacing(GTK_GRID(grid), 30); // 设置网格列间距为 30 像素
gtk_container_set_border_width(GTK_CONTAINER(grid), 30); // 设置网格布局的边框宽度为 30 像素
// 创建标题并设置为橙色和更大的字体
login_title = gtk_label_new(NULL); // 创建一个空的标签控件
gtk_label_set_markup(GTK_LABEL(login_title), "管理员登录界面");
// 使用标记设置标签的字体大小和颜色
gtk_widget_set_halign(login_title, GTK_ALIGN_CENTER); // 设置标题标签水平居中
gtk_grid_attach(GTK_GRID(grid), login_title, 0, 0, 6, 2); // 将标题标签添加到网格布局中,跨越 6 列和 2 行
// 创建账号标签
login_id_label = gtk_label_new("账号:"); // 创建一个带有“账号”文本的标签
gtk_grid_attach(GTK_GRID(grid), login_id_label, 0, 2, 1, 1); // 将账号标签添加到网格布局的第 0 列,第 2 行
change_label_font_size(login_id_label, 24, "white"); // 设置账号标签的字体大小为 24,颜色为白色
// 创建密码标签
login_paswd_label = gtk_label_new("密码:"); // 创建一个带有“密码”文本的标签
gtk_grid_attach(GTK_GRID(grid), login_paswd_label, 0, 3, 1, 1); // 将密码标签添加到网格布局的第 0 列,第 3 行
change_label_font_size(login_paswd_label, 24, "white"); // 设置密码标签的字体大小为 24,颜色为白色
// 创建验证码标签
login_yzm = gtk_label_new("验证码:"); // 创建一个带有“验证码”文本的标签
gtk_grid_attach(GTK_GRID(grid), login_yzm, 0, 4, 1, 1); // 将验证码标签添加到网格布局的第 0 列,第 4 行
change_label_font_size(login_yzm, 24, "white"); // 设置验证码标签的字体大小为 24,颜色为白色
// 生成验证码并显示
do_yzm(GTK_LABEL(login_yzm)); // 调用函数生成验证码并设置到验证码标签中
// 创建登录按钮
login_ok_button = gtk_button_new_with_label("登录"); // 创建一个带有“登录”文本的按钮
customize_button_style(login_ok_button, "#00FFFF", 28, TRUE); // 自定义按钮样式,设置颜色和字体大小
gtk_grid_attach(GTK_GRID(grid), login_ok_button, 0, 5, 2, 1); // 将登录按钮添加到网格布局的第 0 列,第 5 行,跨越 2 列
// 创建注册按钮
login_to_register_button = gtk_button_new_with_label("注册"); // 创建一个带有“注册”文本的按钮
customize_button_style(login_to_register_button, "#00FFFF", 28, TRUE); // 自定义按钮样式,设置颜色和字体大小
gtk_grid_attach(GTK_GRID(grid), login_to_register_button, 3, 5, 2, 1); // 将注册按钮添加到网格布局的第 3 列,第 5 行,跨越 2 列
// 创建账号输入框
login_entry_id = gtk_entry_new(); // 创建一个输入框用于输入账号
gtk_grid_attach(GTK_GRID(grid), login_entry_id, 1, 2, 3, 1); // 将账号输入框添加到网格布局的第 1 列,第 2 行,跨越 3 列
gtk_widget_set_size_request(login_entry_id, 300, 50); // 设置输入框的最小宽度为 300 像素,高度为 50 像素
// 创建密码输入框
login_entry_paswd = gtk_entry_new(); // 创建一个输入框用于输入密码
gtk_grid_attach(GTK_GRID(grid), login_entry_paswd, 1, 3, 3, 1); // 将密码输入框添加到网格布局的第 1 列,第 3 行,跨越 3 列
gtk_widget_set_size_request(login_entry_paswd, 300, 50); // 设置输入框的最小宽度为 300 像素,高度为 50 像素
gtk_entry_set_visibility(GTK_ENTRY(login_entry_paswd), FALSE); // 隐藏密码输入,避免明文显示
// 创建验证码输入框
login_entry_yzm = gtk_entry_new(); // 创建一个输入框用于输入验证码
gtk_grid_attach(GTK_GRID(grid), login_entry_yzm, 1, 4, 3, 1); // 将验证码输入框添加到网格布局的第 1 列,第 4 行,跨越 3 列
gtk_widget_set_size_request(login_entry_yzm, 300, 50); // 设置输入框的最小宽度为 300 像素,高度为 50 像素
// 将网格布局添加到 Overlay 容器中
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), grid); // 将网格布局添加到 Overlay 中
gtk_widget_set_halign(grid, GTK_ALIGN_CENTER); // 设置网格布局水平居中
gtk_widget_set_valign(grid, GTK_ALIGN_CENTER); // 设置网格布局垂直居中
// 连接信号
g_signal_connect(login_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 当窗口关闭时退出 GTK 主循环
g_signal_connect(login_ok_button, "clicked", G_CALLBACK(do_login), NULL); // 当点击登录按钮时,调用 do_login 函数执行登录操作
g_signal_connect(login_to_register_button, "clicked", G_CALLBACK(login_window_to_register_window), NULL); // 当点击注册按钮时,切换到注册窗口
}
// 初始化注册窗口函数
// 此函数用于初始化管理员注册窗口,并为其添加背景、布局、标签、输入框和按钮等UI元素。
// 同时,该函数还为相关控件连接信号处理函数,以响应用户操作。
void register_window_init()
{
GtkWidget *overlay; // 用于覆盖窗口的容器
GtkWidget *grid; // 网格布局,用于排列控件
GtkWidget *register_title; // 窗口标题
GtkWidget *register_id_label; // "账号"标签
GtkWidget *register_paswd_label; // "密码"标签
GtkWidget *register_ok_button; // "注册"按钮
GtkWidget *register_to_login_button; // "返回登录"按钮
GtkWidget *background_image; // 背景图片
GtkWidget *background; // 包含背景图片的事件盒
// 创建注册窗口
// GTK_WINDOW_TOPLEVEL 表示窗口是顶级窗口
register_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(register_window), "监控预警系统——管理员"); // 设置窗口标题
gtk_window_set_default_size(GTK_WINDOW(register_window), 1024, 600); // 设置窗口默认尺寸
// 设置窗口在屏幕中央显示
gtk_window_set_position(GTK_WINDOW(register_window), GTK_WIN_POS_CENTER);
// 设置窗口可调整大小
gtk_window_set_resizable(GTK_WINDOW(main_window), TRUE);
// 创建 Overlay 容器,用于叠加背景和其他控件
overlay = gtk_overlay_new();
gtk_container_add(GTK_CONTAINER(register_window), overlay);
// 创建背景图片,并将其添加到事件盒中
background_image = gtk_image_new_from_file("background.jpg");
background = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(background), background_image);
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), background);
// 设置背景图片的对齐方式和扩展属性,使其充满整个窗口
gtk_widget_set_halign(background, GTK_ALIGN_FILL);
gtk_widget_set_valign(background, GTK_ALIGN_FILL);
gtk_widget_set_hexpand(background, TRUE);
gtk_widget_set_vexpand(background, TRUE);
// 创建网格布局,用于组织窗口中的控件
grid = gtk_grid_new();
gtk_grid_set_row_spacing(GTK_GRID(grid), 20); // 设置行间距
gtk_grid_set_column_spacing(GTK_GRID(grid), 30); // 设置列间距
gtk_container_set_border_width(GTK_CONTAINER(grid), 30); // 设置边框宽度
// 创建注册标题,并设置为橙色大字体
register_title = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(register_title), "管理员注册界面");
gtk_grid_attach(GTK_GRID(grid), register_title, 0, 0, 4, 2); // 将标题添加到网格布局
change_label_font_size(register_title, 28, "orange");
// 创建账号标签,并设置字体大小和颜色
register_id_label = gtk_label_new("账号:");
gtk_grid_attach(GTK_GRID(grid), register_id_label, 0, 2, 1, 1);
change_label_font_size(register_id_label, 28, "white");
// 创建密码标签,并设置字体大小和颜色
register_paswd_label = gtk_label_new("密码:");
gtk_grid_attach(GTK_GRID(grid), register_paswd_label, 0, 3, 1, 1);
change_label_font_size(register_paswd_label, 28, "white");
// 创建验证码标签,并设置字体大小和颜色
register_yzm = gtk_label_new("验证码:");
gtk_grid_attach(GTK_GRID(grid), register_yzm, 0, 4, 1, 1);
change_label_font_size(register_yzm, 28, "white");
// 生成并设置验证码
do_yzm(GTK_LABEL(register_yzm));
// 创建注册按钮,并设置其样式
register_ok_button = gtk_button_new_with_label("注册");
customize_button_style(register_ok_button, "#00FFFF", 28, TRUE);
gtk_grid_attach(GTK_GRID(grid), register_ok_button, 0, 7, 2, 1);
// 创建返回登录按钮,并设置其样式
register_to_login_button = gtk_button_new_with_label("返回登录");
customize_button_style(register_to_login_button, "#00FFFF", 28, TRUE);
gtk_grid_attach(GTK_GRID(grid), register_to_login_button, 2, 7, 2, 1);
// 创建账号输入框,并设置其大小
register_entry_id = gtk_entry_new();
gtk_grid_attach(GTK_GRID(grid), register_entry_id, 1, 2, 3, 1);
gtk_widget_set_size_request(register_entry_id, 240, 50);
// 创建密码输入框,并设置其大小和隐藏文本
register_entry_paswd = gtk_entry_new();
gtk_grid_attach(GTK_GRID(grid), register_entry_paswd, 1, 3, 3, 1);
gtk_widget_set_size_request(register_entry_paswd, 240, 50);
gtk_entry_set_visibility(GTK_ENTRY(register_entry_paswd), FALSE);
// 创建验证码输入框,并设置其大小
register_entry_yzm = gtk_entry_new();
gtk_grid_attach(GTK_GRID(grid), register_entry_yzm, 1, 4, 3, 1);
gtk_widget_set_size_request(register_entry_yzm, 240, 50);
// 将网格布局添加到 Overlay 容器中
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), grid);
gtk_widget_set_halign(grid, GTK_ALIGN_CENTER); // 将网格布局水平居中
gtk_widget_set_valign(grid, GTK_ALIGN_CENTER); // 将网格布局垂直居中
// 连接信号处理函数
g_signal_connect(register_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 窗口关闭时退出主循环
g_signal_connect(register_ok_button, "clicked", G_CALLBACK(do_register), NULL); // 注册按钮点击时执行注册函数
g_signal_connect(register_to_login_button, "clicked", G_CALLBACK(register_window_to_login_window), NULL); // 返回登录按钮点击时切换到登录窗口
}
//-----------------------------------------------------------------------------------------
// -------》》》》》》》》》》* 跳转函数 *《《《《《《《《《《《《《《《《《《《--------------------
//-----------------------------------------------------------------------------------------
void main_window_to_login_window(GtkButton* btn, gpointer user_data)
{
// 隐藏主窗口并显示管理员主窗口
gtk_widget_hide(main_window);
// 显示登录窗口及其所有控件
gtk_widget_show_all(login_window);
// gtk_widget_show(login_window);
}
void main_window_to_register_window(GtkButton* btn, gpointer user_data)
{
// 隐藏主窗口并显示管理员主窗口
gtk_widget_hide(main_window);
// 显示登录窗口及其所有控件
gtk_widget_show_all(register_window);
// gtk_widget_show(register_window);
}
void login_window_to_register_window(GtkButton* btn, gpointer user_data)
{
// 隐藏主窗口并显示管理员主窗口
gtk_widget_hide(login_window);
gtk_widget_show_all(register_window);
// gtk_widget_show(register_window);
}
void register_window_to_login_window(GtkButton* btn, gpointer user_data)
{
// 隐藏主窗口并显示管理员主窗口
gtk_widget_hide(register_window);
gtk_widget_show_all(login_window);
}
void login_window_to_function_window(GtkButton* btn, gpointer user_data)
{
// 隐藏主窗口并显示管理员主窗口
gtk_widget_hide(login_window);
gtk_widget_show_all(function_window);
}
/**
******************************************************************************
* @file : beautify.c
* @author : niuniu
* @brief : ui设计美化接口
* @attention : None
* @date : 2024/8/15
******************************************************************************
*/
#include
#include
#include
#include
#include
#include "beautify.h"
#include
#include
/*
功能:改变按钮颜色
参数:无
返回值:无
作者:niuniu
*/
void customize_button_style(GtkWidget *button, const gchar *font_color, int font_size, gboolean transparent_background) {
// 创建一个CSS提供者,用于加载和应用CSS样式
GtkCssProvider *provider = gtk_css_provider_new();
// 构建CSS样式字符串
gchar *css = g_strdup_printf(
"button { "
"color: %s; " // 设置字体颜色
"font-size: %dpx; " // 设置字体大小
"%s" // 背景透明样式
"}",
font_color,
font_size,
transparent_background ? "background-color: rgba(0,0,0,0); border: none;" : ""
);
// 加载CSS样式
gtk_css_provider_load_from_data(provider, css, -1, NULL);
g_free(css);
// 获取按钮的样式上下文,并应用CSS样式
GtkStyleContext *context = gtk_widget_get_style_context(button);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
// 释放CSS提供者
g_object_unref(provider);
}
/*
功能:改变控件字体
参数:无
返回值:无
作者:niuniu
*/
void change_label_font_size(GtkWidget *label, int size, const gchar *color)
{
// 创建CSS样式字符串,用于设置文本颜色和字体大小
gchar *css = g_strdup_printf(
"label { color: %s; font-size: %dpt; }",
color,
size
);
// 创建一个CSS提供者并加载样式数据
GtkCssProvider *provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider, css, -1, NULL);
g_free(css);
// 获取小部件的样式上下文,并添加CSS提供者
GtkStyleContext *context = gtk_widget_get_style_context(label);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
g_object_unref(provider);
}
void do_yzm(GtkLabel* label)
{
int i = 0;
// 生成一个4位数的验证码
char yzm[5] = "";
// 设置随机种子
srand(time(NULL));
for (i = 0; i < 4; ++i)
{
yzm[i] = rand() % 26 + 'a';
}
// 给标签设置值
gtk_label_set_text(label, yzm);
}
//将输入框设置为透明
void set_entry_transparent(GtkWidget *widget)
{
// 确保传入的 widget 是一个 GtkEntry 类型
g_return_if_fail(GTK_IS_ENTRY(widget));
// 创建一个 CSS 提供者
GtkCssProvider *provider = gtk_css_provider_new();
// 定义 CSS 样式:透明背景和无边框
const char *css_data =
"entry { "
"background-color: transparent; "
"border: none; "
"}";
// 加载 CSS 样式
gtk_css_provider_load_from_data(provider, css_data, -1, NULL);
// 获取 widget 的样式上下文,并应用 CSS 提供者
GtkStyleContext *context = gtk_widget_get_style_context(widget);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
// 确保 CSS 提供者被引用并且不会被过早释放
g_object_unref(provider);
}
/**
******************************************************************************
* @file : rear_end.c
* @author : niuniu
* @brief : 后端数据库操作
* @attention : None
* @date : 2024/8/15
******************************************************************************
*/
#include
#include
#include
#include
#include "rear_end.h"
#include
#include "gtk_window.h"
GtkWidget *dialog;
GtkWidget *warning_text_view;
/*
功能:进行管理员注册功能
参数:无
返回值:无
作者:niuniu
*/
void do_register(GtkButton* btn, gpointer user_date) {
// 实际上就是将输入的信息保存到数据库当中
sqlite3* db; // SQLite 数据库指针
sqlite3_open("user.db", &db); // 打开数据库文件 "user.db"
// 组 SQL 语句
char sql[100] = ""; // 存储 SQL 查询语句
char* errmsg = NULL; // 错误信息
char** table = NULL; // 存储查询结果的表
int row, column; // 表的行数和列数
// 获取用户输入的值
const gchar* id = gtk_entry_get_text(GTK_ENTRY(register_entry_id)); // 获取 ID 输入框中的文本
const gchar* paswd = gtk_entry_get_text(GTK_ENTRY(register_entry_paswd)); // 获取密码输入框中的文本
const gchar* yzm_new = gtk_entry_get_text(GTK_ENTRY(register_entry_yzm)); // 获取验证码输入框中的文本
const gchar* yzm_old = gtk_label_get_text(GTK_LABEL(register_yzm)); // 获取显示的验证码文本
// 检测 ID 是否已经被注册
char sql1[256] = ""; // 存储检测 ID 的 SQL 语句
snprintf(sql1, sizeof(sql1), "SELECT paswd FROM user WHERE id=\"%s\";", id); // 生成查询语句
sqlite3_get_table(db, sql1, &table, &row, &column, &errmsg); // 执行查询
// 如果有效行数为 0,说明没有找到该 ID
if (row == 0)
{
// 判断 ID 是否符合长度要求
if (strlen(id) <= 6)
{
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"账号必须高于6位");
gtk_window_set_title(GTK_WINDOW(dialog), "拒绝"); // 设置对话框标题
gtk_dialog_run(GTK_DIALOG(dialog)); // 显示对话框并等待用户响应
gtk_widget_destroy(dialog); // 销毁对话框
gtk_entry_set_text(GTK_ENTRY(register_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(register_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(register_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(register_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
else if (strlen(paswd) <= 6)
{
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"密码必须高于6位");
gtk_window_set_title(GTK_WINDOW(dialog), "拒绝"); // 设置对话框标题
gtk_dialog_run(GTK_DIALOG(dialog)); // 显示对话框并等待用户响应
gtk_widget_destroy(dialog); // 销毁对话框
gtk_entry_set_text(GTK_ENTRY(register_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(register_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(register_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(register_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
// 验证验证码是否正确
else if (strcmp(yzm_new, yzm_old) != 0)
{
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"验证码错误");
gtk_window_set_title(GTK_WINDOW(dialog), "拒绝"); // 设置对话框标题
gtk_dialog_run(GTK_DIALOG(dialog)); // 显示对话框并等待用户响应
gtk_widget_destroy(dialog); // 销毁对话框
gtk_entry_set_text(GTK_ENTRY(register_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(register_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(register_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(register_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
// ID 和密码都符合要求,插入数据到数据库
else {
snprintf(sql, sizeof(sql), "INSERT INTO user VALUES(\"%s\", \"%s\");", id, paswd);
sqlite3_exec(db, sql, NULL, NULL, &errmsg); // 执行插入操作
if (errmsg != NULL) {
// 插入失败,输出错误信息
printf("errmsg : %s\n", errmsg);
sqlite3_free(errmsg); // 释放错误信息
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
else {
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"注册成功");
gtk_window_set_title(GTK_WINDOW(dialog), "成功"); // 设置对话框标题
gtk_dialog_run(GTK_DIALOG(dialog)); // 显示对话框并等待用户响应
gtk_widget_destroy(dialog); // 销毁对话框
// 注册成功后,隐藏注册窗口,显示登录窗口
gtk_widget_hide(register_window); // 隐藏注册窗口
gtk_widget_show_all(login_window); // 显示登录窗口
}
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
} else {
// ID 已经被注册
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(register_window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"该ID已经被注册!");
gtk_window_set_title(GTK_WINDOW(dialog), "拒绝"); // 设置对话框标题
gtk_dialog_run(GTK_DIALOG(dialog)); // 显示对话框并等待用户响应
gtk_widget_destroy(dialog); // 销毁对话框
gtk_entry_set_text(GTK_ENTRY(register_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(register_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(register_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(register_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
}
/*
功能:管理员登录功能
参数:无
返回值:niuniu
*/
void do_login(GtkButton *btn, gpointer user_date)
{
// 获取输入的编辑框中的信息
const gchar *id = gtk_entry_get_text(GTK_ENTRY(login_entry_id)); // 获取用户输入的 ID
const gchar *paswd = gtk_entry_get_text(GTK_ENTRY(login_entry_paswd)); // 获取用户输入的密码
const gchar *yzm_new = gtk_entry_get_text(GTK_ENTRY(login_entry_yzm)); // 获取用户输入的验证码
const gchar *yzm_old = gtk_label_get_text(GTK_LABEL(login_yzm)); // 获取显示的验证码
// 登录功能实际上就是判断输入的 ID 和密码是否和数据库中的一致
sqlite3 *db; // SQLite 数据库指针
char **table = NULL; // 存储查询结果的表
int row, column; // 表的行数和列数
char *errmsg = NULL; // 错误信息
sqlite3_open("user.db", &db); // 打开数据库文件 "user.db"
char sql[100] = ""; // SQL 查询语句字符串
// 生成查询语句,查找用户输入的 ID 的密码
sprintf(sql, "SELECT paswd FROM user WHERE id=\"%s\";", id);
// 执行查询
sqlite3_get_table(db, sql, &table, &row, &column, &errmsg);
// 如果查询结果行数为 0,表示没有找到该 ID
if (row == 0) {
// 用户输入的 ID 没有注册
gtk_entry_set_text(GTK_ENTRY(login_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(login_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
}
// 判断密码是否正确
else if (strcmp(paswd, table[1]) == 0) {
// 如果密码匹配,检查验证码是否正确
if (strcmp(yzm_new, yzm_old) != 0) {
// 验证码错误
printf("验证码错误\n");
gtk_entry_set_text(GTK_ENTRY(login_entry_id), ""); // 清空 ID 输入框
gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(login_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
return; // 退出函数
} else {
// 登录成功
printf("登录成功\n");
// 查询当前用户的信息
sprintf(sql, "SELECT paswd FROM user WHERE id=\"%s\";", id);
sqlite3_get_table(db, sql, &table, &row, &column, &errmsg);
// 登录成功后,隐藏登录窗口,显示功能窗口
gtk_widget_hide(login_window); // 隐藏登录窗口
gtk_widget_show_all(function_window); // 显示功能窗口
}
} else {
// 密码错误
printf("密码错误\n");
gtk_entry_set_text(GTK_ENTRY(login_entry_paswd), ""); // 清空密码输入框
do_yzm(GTK_LABEL(login_yzm)); // 重新生成验证码
gtk_entry_set_text(GTK_ENTRY(login_entry_yzm), ""); // 清空验证码输入框
sqlite3_close(db); // 关闭数据库连接
}
}
gtk3 + sqlite3实现登录注册功能(前后端分离)完整源码-CSDN博客