文章目录

  • 前言
  • 一、编程七步法
  • 二、编程实践
    • 1.编写此程序的目的
    • 2.设计程序
    • 3.编写-运行-调试代码
      • 项目的文件结构
      • (1)使用glade设计主窗体UI
      • (2)编写后台C代码
      • (3)运行程序
      • (4)实现其他功能
        • 添加CD功能
          • UI功能的实现
          • 安装Mariadb数据库
          • 添加后台代码实现
        • 搜索CD功能
          • UI关于Treeview修改
          • 后台代码实现
          • 效果图

前言

学习如何使用C语言编写一个gui程序,并掌握编写程序的一般步骤。


一、编程七步法

  • 第一步:定义程序的目标
  • 第二步:设计程序
  • 第三步:编写代码
  • 第四步:编译程序
  • 第五步:运行程序
  • 第六步:程序测试与调试
  • 第七步:维护与更新程序

第三步到第六步是一个 “运行–调试–修改代码” 循环过程,直到项目的正式结束。

二、编程实践

1.编写此程序的目的

顾名思义CD管理程序就是管理CD数据的,具体有查找、添加、删除、修改CD,还要可以对CD的track进行增删改查。

2.设计程序

主界面就是一个输入框查询和展示查找的数据。一个按钮用来实现添加功能。数据保存到MySQL数据库中。通过一个添加按钮打开CD添加界面,完成CD添加操作。

3.编写-运行-调试代码

项目的文件结构

头文件CDManager.h:保存主要函数的声明,以及全局变量定义。 UI源文件Interface.c:实现生成UI的函数。 回调函数源文件Callback.c:存放所有用到的回掉函数。 程序入口Main.c:包含main函数

开发环境
操作系统:Linux Mint 20
gcc:v9.3.0 (命令 gcc --version
gtk:v3.24.20 (查看的命令 pkg-config --modversion gtk+-3.0
glade: v3.22.2
vscode:v1.48.2

(1)使用glade设计主窗体UI

推荐先学习这个课程:gtk glade programming
打开glade,软件的界面如下

新建一个gui项目

最后完成的预览图如下

添加treeview的时候要注意:
model是liststore,这是数据格式
view对应的是treeview,添加显示的列的方法是在treeview上右键选择edit,然后就可以添加了。

关于treeview的详细教程参考链接:http://scentric.net/tutorial/treeview-tutorial.html

最后附上ui的数据:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface><requires lib="gtk+" version="3.20"/><object class="GtkListStore" id="liststoreCD"><columns><!-- column-name Tittle --><column type="gchararray"/><!-- column-name Artist --><column type="gchararray"/><!-- column-name Catalogue --><column type="gchararray"/></columns></object><object class="GtkWindow" id="wndMain"><property name="width_request">800</property><property name="height_request">600</property><property name="can_focus">False</property><property name="resizable">False</property><property name="window_position">center</property><child type="titlebar"><placeholder/></child><child><object class="GtkFixed"><property name="visible">True</property><property name="can_focus">False</property><child><object class="GtkButton" id="btnAdd"><property name="label">gtk-add</property><property name="width_request">80</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property><property name="receives_default">True</property><property name="use_stock">True</property><property name="always_show_image">True</property></object><packing><property name="x">20</property><property name="y">20</property></packing></child><child><object class="GtkButton" id="btnQuit"><property name="label">gtk-close</property><property name="width_request">80</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property><property name="receives_default">True</property><property name="use_stock">True</property><property name="always_show_image">True</property></object><packing><property name="x">120</property><property name="y">20</property></packing></child><child><object class="GtkSeparator"><property name="width_request">760</property><property name="height_request">1</property><property name="visible">True</property><property name="can_focus">False</property></object><packing><property name="x">20</property><property name="y">80</property></packing></child><child><object class="GtkLabel"><property name="width_request">100</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">False</property><property name="halign">start</property><property name="label" translatable="yes">Search String: </property><attributes><attribute name="font-desc" value="Sans 12"/></attributes></object><packing><property name="x">20</property><property name="y">100</property></packing></child><child><object class="GtkEntry" id="txtSearch"><property name="width_request">545</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property></object><packing><property name="x">140</property><property name="y">100</property></packing></child><child><object class="GtkButton" id="btnSearch"><property name="label">gtk-find</property><property name="width_request">80</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property><property name="receives_default">True</property><property name="use_stock">True</property><property name="always_show_image">True</property></object><packing><property name="x">700</property><property name="y">100</property></packing></child><child><object class="GtkScrolledWindow"><property name="width_request">760</property><property name="height_request">420</property><property name="visible">True</property><property name="can_focus">True</property><property name="shadow_type">in</property><child><object class="GtkTreeView" id="tvCD"><property name="visible">True</property><property name="can_focus">True</property><property name="model">liststoreCD</property><property name="search_column">0</property><child internal-child="selection"><object class="GtkTreeSelection"/></child><child><object class="GtkTreeViewColumn" id="colTitle"><property name="sizing">fixed</property><property name="fixed_width">200</property><property name="title" translatable="yes">Tittle</property><child><object class="GtkCellRendererText" id="cellTitle"/><attributes><attribute name="text">0</attribute></attributes></child></object></child><child><object class="GtkTreeViewColumn" id="colArtist"><property name="sizing">fixed</property><property name="fixed_width">300</property><property name="title" translatable="yes">Artist</property><child><object class="GtkCellRendererText" id="cellArtist"/><attributes><attribute name="text">1</attribute></attributes></child></object></child><child><object class="GtkTreeViewColumn" id="colCatalogue"><property name="sizing">autosize</property><property name="title" translatable="yes">Catalogue</property><child><object class="GtkCellRendererText" id="cellCatalogue"/><attributes><attribute name="text">2</attribute></attributes></child></object></child></object></child></object><packing><property name="x">20</property><property name="y">160</property></packing></child></object></child></object>
</interface>

(2)编写后台C代码

CDManager.h 的源代码:

#include <gtk/gtk.h>// UI fuctions
GtkWidget *CreatMainWindow(void);
GtkWidget *CreatAddCDWindow(void);// Callback functions
void on_btnAdd_clicked(GtkWidget *button);
void on_btnQuit_clicked(GtkWidget *button);
void on_btnSearch_clicked(GtkWidget *button,gpointer *data);

Interface.c 的源代码:

#include "CDManager.h"GtkWidget *CreatMainWindow(void)
{GtkBuilder *builder = gtk_builder_new_from_file("Main.ui");GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "wndMain"));gtk_builder_connect_signals(builder, NULL);g_signal_connect(window,"destroy",G_CALLBACK(gtk_main_quit),NULL);return window;
}GtkWidget *CreatAddCDWindow(void)
{}

Callback.c 的源代码:

// 暂时没有代码

Main.c 的源代码:

#include "CDManager.h"int main(int argc, char *argv[])
{gtk_init(&argc, &argv);GtkWidget *mainWindow = CreatMainWindow();gtk_widget_show_all(mainWindow);gtk_main();return EXIT_SUCCESS;
}

(3)运行程序

先编写一个makefile来编译整个项目,内如如下

all: appapp: CDManager.h Callback.c Interface.c Main.cgcc -o CDManager Callback.c Interface.c Main.c `pkg-config --cflags --libs gtk+-3.0`clean:rm -f CDManager

在项目目录中运行

make

最后就可以运行程序了

./CDManager

(4)实现其他功能

添加CD功能

UI功能的实现

添加的UI

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface><requires lib="gtk+" version="3.20"/><object class="GtkWindow" id="wndAddCD"><property name="width_request">400</property><property name="height_request">300</property><property name="can_focus">False</property><property name="resizable">False</property><property name="window_position">center-on-parent</property><child type="titlebar"><placeholder/></child><child><object class="GtkFixed"><property name="visible">True</property><property name="can_focus">False</property><child><object class="GtkLabel"><property name="width_request">360</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">False</property><property name="label" translatable="yes">Add CD</property><attributes><attribute name="font-desc" value="Sans 14"/><attribute name="weight" value="semibold"/></attributes></object><packing><property name="x">20</property><property name="y">20</property></packing></child><child><object class="GtkLabel"><property name="width_request">100</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">False</property><property name="label" translatable="yes">Tittle:</property><property name="justify">right</property></object><packing><property name="x">20</property><property name="y">80</property></packing></child><child><object class="GtkEntry" id="txtTittle"><property name="width_request">250</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property></object><packing><property name="x">120</property><property name="y">80</property></packing></child><child><object class="GtkLabel"><property name="width_request">100</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">False</property><property name="label" translatable="yes">Catalogue:</property><property name="justify">right</property></object><packing><property name="x">20</property><property name="y">180</property></packing></child><child><object class="GtkLabel"><property name="width_request">100</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">False</property><property name="label" translatable="yes">Artist:</property><property name="justify">right</property></object><packing><property name="x">20</property><property name="y">130</property></packing></child><child><object class="GtkEntry" id="txtCatalogue"><property name="width_request">250</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property></object><packing><property name="x">120</property><property name="y">180</property></packing></child><child><object class="GtkEntry" id="txtArtist"><property name="width_request">250</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property></object><packing><property name="x">120</property><property name="y">130</property></packing></child><child><object class="GtkButton" id="btnAddCD"><property name="label">gtk-add</property><property name="width_request">80</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property><property name="receives_default">True</property><property name="use_stock">True</property><property name="always_show_image">True</property><signal name="clicked" handler="on_btnAddCD_clicked" swapped="no"/></object><packing><property name="x">120</property><property name="y">230</property></packing></child><child><object class="GtkButton" id="btnClose"><property name="label">gtk-close</property><property name="width_request">80</property><property name="height_request">40</property><property name="visible">True</property><property name="can_focus">True</property><property name="receives_default">True</property><property name="use_stock">True</property><property name="always_show_image">True</property><signal name="clicked" handler="on_btnClose_clicked" swapped="no"/></object><packing><property name="x">290</property><property name="y">230</property></packing></child></object></child></object>
</interface>

主窗体添加窗口

GtkWidget *CreatAddCDWindow(void)
{GtkBuilder *builder=gtk_builder_new_from_file("AddCD.ui")   ;GtkWidget *window=GTK_WIDGET(gtk_builder_get_object(builder,"wndAddCD"));gtk_builder_connect_signals(builder,NULL);g_signal_connect(window,"destroy",G_CALLBACK(on_btnClose_clicked),NULL);g_object_unref(builder);return window;
}

编写回调函数

#include "CDManager.h"static GtkWidget *addCDWindow;void on_btnAdd_clicked(GtkButton *button)
{if (addCDWindow){gtk_widget_hide(addCDWindow);}else{addCDWindow = CreatAddCDWindow();}gtk_widget_show_all(addCDWindow);
}void on_btnQuit_clicked(GtkButton *button)
{gtk_main_quit();
}void on_btnSearch_clicked(GtkButton *button, gpointer *data);void on_btnAddCD_clicked(GtkButton *button);
void on_btnClose_clicked(GtkButton *button)
{gtk_widget_hide(addCDWindow);addCDWindow=NULL;
}

再次编译测试

make./CDManager
安装Mariadb数据库

Linux Mint中执行下面的命令

sudo apt-get install mariadb-server

这条命令将安装server和client

然后安装一个有命令行提示的MySQL工具

sudo apt-get install mycli

创建数据库和数据表

mycli
> creat database CDManagerDb;> creat table Artists(Id int auto_increment primary key,Name varchar(20) not null);> creat table CD(Id int auto_increment primary keyTitle varchar(30) not null,ArtistId int not null,Catalogue varchar(20) not null,notes varchar(100));> creat table Track(CdId int not null,TrackId int not null,Title varchar(100),primary key(CdId,TrackId))

授权用户

grant all on CDManagerDb.* to test@'%' identified by 'test';

安装MySQL开发包

sudo apt-get install libmysqlclient-dev
添加后台代码实现

添加一个访问数据库的头文件CDManagerMysql.h,源代码如下:
这是《Beginning Linux Progamming》书中的代码

// A simplistic structure to represent current CD
struct CurrentCDSt
{int ArtistId;int CDId;char Title[100];char ArtistName[100];char Catalogue[100];
};// A simplistic track detailed structure
struct CurrentTracksSt
{int CDId;char Track[20][100];
};#define MaxCDResult 10
struct CDSearchSt
{int CDId[MaxCDResult];
};// Database backend functions
int DatabaseStart(char *name,char *password);
void DatabaseEnd();// Functions for adding a CD
int AddCD(char *artist,char *title,char *catalogue,int *cdId);
int AddTrack(struct CurrentTracksSt *tracks);// Functions for finding and retrieving a CD
int FindCDs(char *searchStr,struct CDSearchSt *results);
int GetCD(int CDId,struct CurrentCDSt *dest);
int GetCDTracks(int CDId,struct CurrentTracksSt *dest);// Function for deleting items
int DeleteCD(int CDId);

数据库操作的函数实现CDManagerMysql.c,源代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
#include "CDManagerMysql.h"static MYSQL myConnection;
static int dbConnected = 0;static int GetArtistId(char *artist);int DatabaseStart(char *name, char *password)
{if (dbConnected){return 1;}mysql_init(&myConnection);if (!mysql_real_connect(&myConnection, "localhost", name, password, "CDManagerDb", 0, NULL, CLIENT_FOUND_ROWS)){fprintf(stderr, "Database connection failed: %d, %s", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}dbConnected = 1;return 1;
}void DatabaseEnd()
{if (dbConnected){mysql_close(&myConnection);}dbConnected = 0;
}int AddCD(char *artist, char *title, char *catalogue, int *cdId)
{if (!dbConnected){return 0;}int artistId = -1;artistId = GetArtistId(artist);char es[250];char is[250];mysql_escape_string(es, title, strlen(title));sprintf(is, "insert into CD(Title,ArtistId,Catalogue) values('%s',%d,'%s')", title, artistId, catalogue);int result = mysql_query(&myConnection, is);if (result){fprintf(stderr, "Insert error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}result = mysql_query(&myConnection, "select last_insert_id()");MYSQL_RES *resPtr;MYSQL_ROW row;int newCDId = -1;if (!result){resPtr = mysql_use_result(&myConnection);if (resPtr){row = mysql_fetch_row(resPtr);if (row){sscanf(row[0], "%d", &newCDId);}mysql_free_result(resPtr);}}else{fprintf(stderr, "Select error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}*cdId = newCDId;return newCDId == -1 ? 0 : 1;
}int GetArtistId(char *artist)
{char es[100];char qs[250];mysql_escape_string(es, artist, strlen(artist));sprintf(qs, "select Id from Artist where name='%s'", es);MYSQL_RES *resPtr;MYSQL_ROW row;int result = mysql_query(&myConnection, qs);if (result){fprintf(stderr, "Select error %d: %s", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}resPtr = mysql_store_result(&myConnection);int artistId = -1;if (resPtr){if (mysql_num_rows(resPtr) > 0){if (row = mysql_fetch_row(resPtr)){sscanf(row[0], "%d", &artistId);}}}mysql_free_result(resPtr);if (artistId != -1){return artistId;}char is[250];sprintf(is, "insert into Artist(Name) values('%s')", es);result = mysql_query(&myConnection, is);if (result){fprintf(stderr,"Insert error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}result = mysql_query(&myConnection, "select last_insert_id()");if (result){fprintf(stderr,"Select error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}resPtr = mysql_use_result(&myConnection);if (resPtr){if (row = mysql_fetch_row(resPtr)){sscanf(row[0], "%d", &artistId);}}mysql_free_result(resPtr);return artistId;
}int AddTrack(struct CurrentTracksSt *tracks)
{if (!dbConnected){return 0;}int i = 0;char es[100];char is[250];int result = -1;while (tracks->Track[i][0]){mysql_escape_string(es, tracks->Track[i], strlen(tracks->Track[i]));sprintf(is, "insert into Track(CdId,TrackId,Title) values(%d,%d,'%s')", tracks->CDId, i + 1, es);result = mysql_query(&myConnection, is);if (result){fprintf(stderr,"Add track error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}i++;}return 1;
}int FindCDs(char *searchStr, struct CDSearchSt *results)
{MYSQL_RES *resPtr;MYSQL_ROW row;int res = -1;char qs[250];char es[30];int count = 0;if (!dbConnected){return 0;}memset(results, -1, sizeof(*results));mysql_escape_string(es, searchStr, strlen(searchStr));sprintf(qs, "select CD.Id from CD,Artist where CD.ArtistId=Artist.Id and (Artist.Name like '%%%s%%' or CD.Title like '%%%s%%' or CD.Catalogue like '%%%s%%')", es, es, es);res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Find CDs error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}else{resPtr = mysql_store_result(&myConnection);if (resPtr){count = mysql_num_rows(resPtr);if (count > 0){int i = 0;while ((row = mysql_fetch_row(resPtr)) && (i < MaxCDResult)){sscanf(row[0], "%d", &results->CDId[i]);i++;}}}mysql_free_result(resPtr);}return count;
}int GetCD(int CDId, struct CurrentCDSt *dest)
{if (!dbConnected){return 0;}MYSQL_RES *resPtr;MYSQL_ROW row;int res = 0;char qs[250];memset(dest, 0, sizeof(*dest));sprintf(qs, "select CD.Id,Artist.Id,CD.Title,CD.Catalogue,Artist.Name from CD,Artist where CD.ArtistId=Artist.Id and CD.Id=%d", CDId);res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Get CD error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}else{resPtr = mysql_store_result(&myConnection);if (resPtr){if (mysql_num_rows(resPtr) > 0){if (row = mysql_fetch_row(resPtr)){sscanf(row[0], "%d", &dest->CDId);sscanf(row[1], "%d", &dest->ArtistId);strcpy(dest->Title, row[2]);strcpy(dest->Catalogue, row[3]);strcpy(dest->ArtistName, row[4]);}}}mysql_free_result(resPtr);}return dest->ArtistId == -1 ? 0 : 1;
}int GetCDTracks(int CDId, struct CurrentTracksSt *dest)
{if (!dbConnected){return 0;}MYSQL_RES *resPtr;MYSQL_ROW row;char qs[250];int result;int count = 0, i = 0;memset(dest, 0, sizeof(*dest));dest->CDId = -1;sprintf(qs, "select TrackId,Title from Track where CDId=%d order by TrackId", CDId);result = mysql_query(&myConnection, qs);if (result){fprintf(stderr, "Get Tracks error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}else{resPtr = mysql_store_result(&myConnection);if (resPtr){count = mysql_num_rows(resPtr);if (count > 0){while (row = mysql_fetch_row(resPtr)){strcpy(dest->Track[i], row[1]);i++;}dest->CDId = CDId;}}mysql_free_result(resPtr);}return count;
}int DeleteCD(int CDId)
{if (!dbConnected){return 0;}MYSQL_RES *resPtr;MYSQL_ROW row;char qs[250];int artistId = -1, count = 0;sprintf(qs, "select ArtistId from CD where ArtistId=(select ArtistId from CD where Id=%d)", CDId);int res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Select artistId error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}else{resPtr = mysql_store_result(&myConnection);if (resPtr){count = mysql_num_rows(resPtr);if (count == 1){row = mysql_fetch_row(resPtr);sscanf(row[0], "%d", &artistId);}mysql_free_result(resPtr);}}sprintf(qs, "delete from Track where CdId=%d", CDId);res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Select artistId error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}sprintf(qs, "delete from CD where Id=%d", CDId);res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Select artistId error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}if (artistId != -1){sprintf(qs, "delete from Artist where Id=%d", artistId);res = mysql_query(&myConnection, qs);if (res){fprintf(stderr, "Select artistId error %d: %s\n", mysql_errno(&myConnection), mysql_error(&myConnection));return 0;}}return 1;
}

获取文本输入框对象

#include "CDManager.h"GtkWidget *TittleEntry;
GtkWidget *ArtistEntry;
GtkWidget *CatalogueEntry;GtkWidget *CreatMainWindow(void)
{GtkBuilder *builder = gtk_builder_new_from_file("Main.ui");GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "wndMain"));gtk_builder_connect_signals(builder, NULL);g_object_unref(builder);return window;
}GtkWidget *CreatAddCDWindow(void)
{GtkBuilder *builder=gtk_builder_new_from_file("AddCD.ui")   ;GtkWidget *window=GTK_WIDGET(gtk_builder_get_object(builder,"wndAddCD"));TittleEntry=GTK_WIDGET(gtk_builder_get_object(builder,"txtTittle"));ArtistEntry=GTK_WIDGET(gtk_builder_get_object(builder,"txtArtist"));CatalogueEntry=GTK_WIDGET(gtk_builder_get_object(builder,"txtCatalogue"));gtk_builder_connect_signals(builder,NULL);g_signal_connect(window,"destroy",G_CALLBACK(on_btnClose_clicked),NULL);g_object_unref(builder);return window;
}

UI中添加功能的回掉函数

#include "CDManagerMysql.h"  //包含头文件extern GtkWidget *TittleEntry;
extern GtkWidget *ArtistEntry;
extern GtkWidget *CatalogueEntry;// Add CD Callbacks
void on_btnAddCD_clicked(GtkButton *button)
{const gchar *tittleConst,*artistConst,*catalogueConst;tittleConst= gtk_entry_get_text(GTK_ENTRY(TittleEntry));artistConst= gtk_entry_get_text(GTK_ENTRY(ArtistEntry));catalogueConst= gtk_entry_get_text(GTK_ENTRY(CatalogueEntry));gchar tittle[200], artist[200], catalogue[200];strcpy(tittle, tittleConst);strcpy(artist, artistConst);strcpy(catalogue, catalogueConst);DatabaseStart("jlee", "ljj"); //用户名和密码int cdId, result;result = AddCD(artist, tittle, catalogue, &cdId);GtkWidget *msgDialog;if (result == 1){msgDialog = gtk_message_dialog_new(GTK_WINDOW(AddCDWindow),GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_INFO,GTK_BUTTONS_CLOSE,"Add CD successfully!");}else{msgDialog = gtk_message_dialog_new(GTK_WINDOW(AddCDWindow),GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_INFO,GTK_BUTTONS_CLOSE,"Add CD failed!");}gtk_dialog_run(GTK_DIALOG(msgDialog));gtk_widget_destroy(msgDialog);DatabaseEnd();
}

makefile文件需要修改如下:

all: appapp: CDManager.h Callback.c Interface.c Main.c CDManagerMysql.h CDManagerMysql.cgcc -rdynamic -o CDManager Callback.c Interface.c CDManagerMysql.c Main.c -lmysqlclient `pkg-config --cflags --libs gtk+-3.0`clean:rm -f CDManager

最后实现的效果图





搜索CD功能

UI关于Treeview修改

由于要展示Track的信息,我们将Treeview的Model 改成TreeStore,而不是简单使用Liststore。
新建一个Treestore

绑定到Treeview上

后台代码实现

CDManager.h头文件中添加一个枚举:

enum {ColumnTittle,ColumnArtist,ColumnCatalogue,NumColumns
};

Callback.c文件中添加搜索按钮的回掉函数,源代码如下:

extern GtkWidget *CDTreeView;
extern GtkTreeStore *TreeStore;void on_btnSearch_clicked(GtkButton *button, gpointer *data)
{DatabaseStart("jlee","ljj");gchar searchString[200];strcpy(searchString, gtk_entry_get_text(GTK_ENTRY(data)));struct CDSearchSt cdSearchResult;gint foundedCDCount = FindCDs(searchString, &cdSearchResult);gint i, j, trackCount;struct CurrentCDSt cd;struct CurrentTracksSt ct;GtkTreeIter parent, child;gchar trackTittle[110];for (i = 0; i < foundedCDCount && i < MaxCDResult; i++){GetCD(cdSearchResult.CDId[i], &cd);gtk_tree_store_append(TreeStore, &parent, NULL);gtk_tree_store_set(TreeStore, &parent,ColumnTittle, cd.Title,ColumnArtist, cd.ArtistName,ColumnCatalogue, cd.Catalogue,-1);trackCount = GetCDTracks(cdSearchResult.CDId[i], &ct);memset(trackTittle, 0, sizeof(trackTittle));for (j = 0; j < trackCount; j++){sprintf(trackTittle, " Track %d. ", j + 1);strcat(trackTittle, ct.Track[j]);gtk_tree_store_append(TreeStore, &child, &parent);gtk_tree_store_set(TreeStore, &child, ColumnTittle, trackTittle);}}gtk_tree_view_set_model(GTK_TREE_VIEW(CDTreeView),GTK_TREE_MODEL(TreeStore));DatabaseEnd();
}
效果图


C语言实现CD管理程序相关推荐

  1. C语言学生成绩管理程序(可排队序统计)

    C语言学生成绩管理程序(可排队序统计) 一.系统菜单的主要功能 (1)输入若干条记录 (2)显示所有记录 (3)按学号排序 (4)插入一条记录 (5)按姓名查找,删除一条记录 (6)查找并显示一条记录 ...

  2. c语言大作业答辩ppt,C语言程序设计—考试管理程序答辩ppt.ppt

    C语言程序设计-考试管理程序答辩ppt * 人员:张旭东.王隆基.汤双节.刘宇 系 统 功 能 逻 辑 结 构 小 组 分 工 程 序 特 色 系 统 功 能 考试设置 学生信息的录入.修改增加与删除 ...

  3. c语言 交通处罚单管理程序 typedef struct,交通罚单.doc

    C语言程序设计课程设计报告交通处罚单管理程序学号-姓名第PAGE \* MERGEFORMAT34页 <C语言程序设计>课程设计报告题目:交通处罚单管理程序班级:0214108 学号:02 ...

  4. 怎样用c语言写超市管理程序,C语言超市收银管理系统实现程序.doc

    超市收银管理程序的设计与实现 1摘要和关键字 1.1摘要 该系统主要用于超市商品管理人员对于商品的信息(包括商品号.商品名.单价)进行输入.删除.修改和查询.除此之外,当销售人员输入商品号及销售数量时 ...

  5. C语言编程编制职工档案管理程序,c语言人事档案管理程序

    c语言大作业,关于人事档案管理方面的 #include #include #include #include /*函数声明*/ void readFile(); void display(); voi ...

  6. c语言学生学籍管理程序,C语言实现简单学籍管理系统

    #include #include #include int shoudsave=0; // struct student { char num[10];//学号 char name[20]; int ...

  7. 高校人事档案c语言代码大全,c语言人事档案管理程序

    c语言大作业,关于人事档案管理方面的 #include #include #include #include /*函数声明*/ void readFile(); void display(); voi ...

  8. c语言设计通讯录管理程序,C语言程序的设计学生通讯录管理系统方案.docx

    include ustdio.hH include "stdlib.h" include "string.h" include "conio.h&qu ...

  9. C语言停车场模拟管理程序的设计与实现

    这个程序是利用栈和循环队列实现的,属于练手的吧.很简单的.只不过自己得先处理好逻辑关系就好了.自己关于这个程序没加重复判断,比如一辆车已经停在车位上或者便道上,再来一辆就判断不了了,所以加个重复判断还 ...

最新文章

  1. 雷军的最后一次 重 大 创 业
  2. 扫地机器人“离家出走”的真实原因找到了:差个自动驾驶算法
  3. 「炫富」的GPT-3来了:31位作者,45TB数据,72页论文,1750亿个参数,会编故事,还会三位数加减法...
  4. Spring Cloud构建微服务架构:消息驱动的微服务(消费分区)【Dalston版】
  5. Fedora 30系统下,用g++编译opencv项目
  6. 数据解析系统中需改进的几点
  7. 利用koa实现mongodb数据库的增删改查
  8. php 进制 小数,小数进制转换
  9. 各种平台的表达芯片跟mRNA-seq数据比较
  10. T-sne可视化digits
  11. 马化腾亲自写腾讯网站,雷军靠写程序赚到第一个100万...那些码农出身的互联网大佬们...
  12. python dataframe是否为空_python if条件判断dataframe是否为空
  13. C++ primer 5th 读完的一点心得体会
  14. 【裸SPFA】星门跳跃
  15. 前端工程师ps学习笔记
  16. 华为OD机试 - 德州扑克(Java JS Python)
  17. 【2023】Kotlin教程 第二篇 面向对象与函数式编程 第15章 数据容器——数组和集合 15.2 集合概述
  18. 降本提效!注册中心在蚂蚁集团的蜕变之路
  19. 什么是大数据(Big Data)?
  20. 数据结构与算法之美(二)

热门文章

  1. java calendar getactualmaximum_Java Calendar
  2. oracle exadata x6 -m,Oracle新推Exadata X6数据库云平台
  3. 春花秋月何时了,互联网广告系统知多少?
  4. HTML+CSS系列学习:重生之我要精通编程语言修仙
  5. 【笔记】vue实现音乐播放器
  6. linux jdk8下载
  7. C#对磁盘路径字符串的相关操作
  8. Python保护视力小程序
  9. 显示器点距 测试软件,液晶显示器常见、尺寸、分辨率、点距
  10. 将GUI打包成EXE发布