gtk3 + sqlite3实现登录注册(前后端分离)

目录

主要思路

界面设计(以主界面为例)

后端注册

设计总结

后端登录

设计思路

界面展示

主界面

登录界面

注册界面

源代码(详细注释)

Makefile

gtk_window.c(前端)

beautify.c(样式美化)

rear_end.c(后端)

项目完整源码可移步到:


更多文章和源码在我的个人博客:首页 (niuniu65.top)

如需咨询请添加个人微信:a15135158368

欢迎叨扰,互相交流

主要思路

界面设计(以主界面为例)

  1. 创建主窗口

    • 使用 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);
  2. 使用 Overlay 容器进行叠加布局

    • 创建一个 GtkOverlay 容器,将其作为主窗口的子控件。

    • Overlay 容器允许在同一窗口中叠加多个控件,如背景图片和网格布局。

    overlay = gtk_overlay_new();
    gtk_container_add(GTK_CONTAINER(main_window), overlay);
  3. 添加背景图片

    • 在 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);
  4. 网格布局的创建与配置

    • 创建一个 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);

  5. 设置主标题

    • 创建一个标签作为主标题,使用 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);

  6. 创建登录和注册按钮

    • 分别创建登录和注册按钮,并自定义按钮的颜色和字体大小。

    • 将按钮添加到网格布局中,并设置其位置。

    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);

  7. 将网格布局添加到 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);

  8. 信号连接

    • 连接窗口关闭信号以退出程序,并为按钮点击事件绑定相应的回调函数。

    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);

后端注册

  1. 打开数据库连接

    • 通过 sqlite3_open() 函数打开一个 SQLite 数据库连接,确保在操作之前已经连接到数据库。

    sqlite3* db;
    sqlite3_open("user.db", &db);

  2. 获取用户输入

    • 使用 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));

  3. 检查 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);

  4. 验证输入信息

    • ID 和密码长度检查:如果 ID 或密码长度小于或等于 6 位,弹出错误对话框,并清空输入框。

    • 验证码验证:如果用户输入的验证码与显示的验证码不匹配,弹出错误对话框,并清空输入框。

    if (strlen(id) <= 6) {
        // 错误对话框和清空操作
    } else if (strlen(paswd) <= 6) {
        // 错误对话框和清空操作
    } else if (strcmp(yzm_new, yzm_old) != 0) {
        // 错误对话框和清空操作
    }

  5. 插入新用户数据到数据库

    • 如果 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 {
        // 注册成功对话框和窗口切换
    }

  6. 处理 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已经被注册!");
        // 错误对话框和清空操作
    }

  7. 关闭数据库连接

    • 在函数的最后,确保数据库连接被关闭,防止资源泄漏。

    sqlite3_close(db);

设计总结

  • 该函数的设计集中在用户输入的验证和数据库操作上。

  • 通过检查用户输入的 ID 是否已被注册,然后通过验证输入的长度和验证码来确保数据的有效性

  • 如果所有验证通过,将数据插入数据库并切换窗口。

后端登录

设计思路

  1. 获取用户输入的信息

    • 在登录功能中,首先通过 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));
  2. 打开数据库

    • 使用 sqlite3_open 打开 SQLite 数据库文件 user.db 以便在后续操作中进行用户信息的查询和验证。

    • 代码示例:

      sqlite3 *db;
      sqlite3_open("user.db", &db);
  3. 生成查询语句

    • 根据用户输入的 ID,生成查询 SQL 语句,查询数据库中是否存在对应的用户及其密码。

    • 代码示例:

      char sql[100] = "";
      sprintf(sql, "SELECT paswd FROM user WHERE id=\"%s\";", id);
  4. 执行查询

    • 使用 sqlite3_get_table 执行查询语句,并将查询结果存储在表格中以进行后续的密码和验证码验证。

    • 代码示例:

      char **table = NULL;
      int row, column;
      char *errmsg = NULL;
      sqlite3_get_table(db, sql, &table, &row, &column, &errmsg);
  5. 验证用户 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;
      }
  6. 验证密码是否正确

    • 对比用户输入的密码与数据库中存储的密码。如果不匹配,清空密码输入框并重新生成验证码。

    • 代码示例:

      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);
      }
  7. 验证验证码

    • 如果密码正确,进一步验证用户输入的验证码是否与显示的验证码匹配。如果匹配,表示登录成功,隐藏登录窗口并显示功能窗口。

    • 代码示例:

      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);
      }
  8. 关闭数据库

    • 在函数结束前,确保关闭数据库连接以避免资源泄漏。

    • 代码示例:

      sqlite3_close(db);

界面展示

主界面

gtk3 + sqlite3实现登录注册(前后端分离)_第1张图片

登录界面

gtk3 + sqlite3实现登录注册(前后端分离)_第2张图片

注册界面

gtk3 + sqlite3实现登录注册(前后端分离)_第3张图片

源代码(详细注释)

Makefile

# 链接库
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

gtk_window.c(前端)

/**
  ******************************************************************************
  * @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);
}

beautify.c(样式美化) 

/**
  ******************************************************************************
  * @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);
}

rear_end.c(后端)

/**
  ******************************************************************************
  * @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博客

你可能感兴趣的:(Linux应用层开发,sqlite,数据库)