Linux图形界面编程简单教程(附计算器源代码)
时间: 2024-03-10 21:50:13 浏览: 186
Linux下的图形界面编程的实现
好的,我会尽力回答你的问题。以下是一个简单的 Linux 图形界面编程的教程,包含一个计算器的源代码。
1. 安装 GTK+ 库
GTK+ 是 Linux 下常用的 GUI 库,可以通过以下命令安装:
```bash
sudo apt-get install libgtk-3-dev
```
2. 创建 GUI 窗口
下面是一个简单的创建 GUI 窗口的代码:
```c
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
gtk_widget_show(window);
gtk_main();
return 0;
}
```
这段代码创建了一个名为 "Calculator" 的窗口,并设置了窗口的位置、大小和边框宽度。需要注意的是,最后一行代码 `gtk_main()` 是一个循环,它会一直运行直到程序退出,因为 GTK+ 是基于事件驱动的。
3. 添加按钮和文本框
我们需要在窗口中添加按钮和文本框,用于实现计算器的功能。下面是一个添加按钮和文本框的代码:
```c
#include <gtk/gtk.h>
void button_clicked(GtkWidget *button, gpointer data)
{
g_print("Button clicked\n");
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
GtkWidget *entry;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
grid = gtk_grid_new();
gtk_container_add(GTK_CONTAINER(window), grid);
entry = gtk_entry_new();
gtk_entry_set_alignment(GTK_ENTRY(entry), 1);
gtk_widget_set_size_request(entry, 200, 30);
gtk_grid_attach(GTK_GRID(grid), entry, 0, 0, 4, 1);
button = gtk_button_new_with_label("7");
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 1, 1);
button = gtk_button_new_with_label("8");
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
gtk_grid_attach(GTK_GRID(grid), button, 1, 1, 1, 1);
button = gtk_button_new_with_label("9");
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
gtk_grid_attach(GTK_GRID(grid), button, 2, 1, 1, 1);
button = gtk_button_new_with_label("/");
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
gtk_grid_attach(GTK_GRID(grid), button, 3, 1, 1, 1);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
```
这段代码添加了一个文本框和四个按钮,当按钮被点击时会调用 `button_clicked` 函数。需要注意的是,我们使用了一个 GTK+ 的容器 `gtk_grid_new()`,它可以让我们灵活地布置窗口中的控件。
4. 实现计算器的功能
最后,我们需要在按钮点击事件中实现计算器的功能。下面是一个简单的计算器的代码:
```c
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
GtkWidget *entry;
int i, j;
char buf[10];
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
grid = gtk_grid_new();
gtk_container_add(GTK_CONTAINER(window), grid);
entry = gtk_entry_new();
gtk_entry_set_alignment(GTK_ENTRY(entry), 1);
gtk_widget_set_size_request(entry, 200, 30);
gtk_grid_attach(GTK_GRID(grid), entry, 0, 0, 4, 1);
char *text[16] = {"7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", ".", "0", "=", "+"};
for (i = 0; i < 16; i++) {
button = gtk_button_new_with_label(text[i]);
gtk_widget_set_size_request(button, 45, 35);
gtk_grid_attach(GTK_GRID(grid), button, i % 4, i / 4 + 1, 1, 1);
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), entry);
}
gtk_widget_show_all(window);
gtk_main();
return 0;
}
void button_clicked(GtkWidget *button, gpointer data)
{
const gchar *text = gtk_button_get_label(GTK_BUTTON(button));
gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(data));
gchar buf[50];
if (g_ascii_strcasecmp(text, "=") == 0) {
double result = evaluate(entry_text);
sprintf(buf, "%.2f", result);
gtk_entry_set_text(GTK_ENTRY(data), buf);
} else {
strcat(entry_text, text);
gtk_entry_set_text(GTK_ENTRY(data), entry_text);
}
}
double evaluate(const gchar *expr)
{
GError *error = NULL;
double result;
if (gdk_threads_enter()) {
if (gdk_threads_enter()) {
if (gdk_threads_enter()) {
if (gdk_threads_enter()) {
if (gdk_threads_enter()) {
if (!gdk_threads_enter()) {
return 0.0;
}
}
}
}
}
}
if (gdk_threads_leave()) {
if (gdk_threads_leave()) {
if (gdk_threads_leave()) {
if (gdk_threads_leave()) {
if (gdk_threads_leave()) {
if (!gdk_threads_leave()) {
return 0.0;
}
}
}
}
}
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
if (!gdk_threads_enter()) {
return 0.0;
}
if (!gdk_threads_leave()) {
return 0.0;
}
gdouble result;
gboolean success = g_strtod_with_fixed(expr, &result, &error, "en_US.utf8");
if (success) {
return result;
} else {
g_error_free(error);
return 0.0;
}
}
```
这段代码添加了一个 `evaluate` 函数,用于计算表达式。在 `button_clicked` 函数中,我们通过 `gtk_entry_get_text` 函数获取文本框中的文本,然后通过 `evaluate` 函数计算结果,并把结果显示在文本框中。
需要注意的是,我们在 `evaluate` 函数中使用了 `gdk_threads_enter/leave` 函数来保证多线程安全,因为 GTK+ 是多线程的。这些函数的作用是进入/离开 GTK+ 的主线程。
阅读全文