英文:
How can I create a user input box and output area in a GTK C program, similar to a shell or terminal?
问题
You can use a GtkTextView
widget to achieve the functionality you described. Here's the relevant code with the necessary modifications:
#include <gtk/gtk.h>
static GtkWidget *entry1 = NULL;
static GtkWidget *text_view = NULL;
static GtkTextBuffer *buffer = NULL;
void button_clicked(GtkWidget *widget, gpointer data)
{
const gchar *entry_text1;
entry_text1 = gtk_entry_get_text(GTK_ENTRY(entry1));
// Get the current text from the text view
GtkTextIter iter;
gtk_text_buffer_get_end_iter(buffer, &iter);
// Append the new text to the text view
gtk_text_buffer_insert(buffer, &iter, entry_text1, -1);
// Scroll to the end of the text view
gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(text_view), gtk_text_buffer_get_insert(buffer), 0.0, FALSE, 0.0, 1.0);
}
void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(win), 680, 460);
entry1 = gtk_entry_new();
text_view = gtk_text_view_new();
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
GtkWidget *btn2 = gtk_button_new_with_label("Click Here2");
GtkWidget *grd = gtk_grid_new();
g_signal_connect(btn2, "clicked", G_CALLBACK(button_clicked), NULL);
gtk_grid_attach(grd, entry1, 1, 1, 1, 1);
gtk_grid_attach(grd, btn2, 2, 1, 1, 1);
gtk_grid_attach(grd, text_view, 1, 2, 2, 1);
gtk_container_add(GTK_CONTAINER(win), grd);
gtk_container_set_border_width(GTK_CONTAINER(win), 20);
g_signal_connect(win, "destroy", G_CALLBACK(destroy), NULL);
gtk_widget_show_all(win);
gtk_main();
return 0;
}
This code includes a GtkTextView
widget (text_view
) and a GtkTextBuffer
(buffer
) to manage the text inside the text view. When the button is clicked, it appends the text from the entry to the text view and scrolls to show the latest text, giving you a basic terminal-like behavior.
英文:
I am trying to make a shell-ish thing in C using GTK. I want to make a box where:
- the user types something
- the output appears in a box
- The output moves upwards and you can scroll (basically like a regular terminal.)
How would I go about doing this? Here is my code so far:
#include <gtk/gtk.h>
static GtkWidget *entry1 = 0;
void button_clicked(GtkWidget *widget,gpointer data)
{
const gchar *entry_text1;
entry_text1 = gtk_entry_get_text (GTK_ENTRY (entry1));
g_print ("%s\n", entry_text1);
}
void destroy(GtkWidget* widget, gpointer data)
{
gtk_main_quit();
}
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv);
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (win), 680, 460);
entry1 = gtk_entry_new();
GtkWidget *btn2 = gtk_button_new_with_label("Click Here2");
GtkWidget *grd = gtk_grid_new();
g_signal_connect(btn2,"clicked",G_CALLBACK(button_clicked),NULL);
gtk_grid_attach(grd, entry1, 1,1,1,1);
gtk_grid_attach(grd, btn2, 2,1,1,1);
gtk_container_add(GTK_CONTAINER(win),grd);
gtk_container_set_border_width(GTK_CONTAINER(win), 20);
g_signal_connect(win, "destroy",G_CALLBACK(destroy), NULL);
gtk_widget_show_all(win);
gtk_main();
return 0;
}
I have no clue what type of widget to use to do something like this.
答案1
得分: 1
我认为你应该使用 GtkScrolledWindow
来实现这个功能。例如:
#include <gtk/gtk.h>
// 用户在此输入内容。
static GtkWidget *input = NULL;
// 包含所有以前用户输入的文本的文本缓冲区。
static GtkTextBuffer *buffer = NULL;
// 当单击“userText”按钮时,将用户添加到输入的所有内容传输到文本区域。
void button_clicked(GtkWidget *widget, gpointer data)
{
// 获取用户添加到输入的文本:
const gchar *userText;
userText = gtk_entry_get_text(GTK_ENTRY(input));
// 在文本视图中插入(在末尾):
GtkTextIter end; // 请注意,这是在堆栈上创建的!像往常一样传递指针不起作用。
// 请参阅:https://stackoverflow.com/questions/52182527/iterators-do-not-belong-to-their-assigned-text-buffer
gtk_text_buffer_get_end_iter(buffer, &end);
gtk_text_buffer_insert(buffer, &end, userText, -1);
gtk_text_buffer_insert(buffer, &end, "\n", -1);
// 清除用户输入以进行下一次输入:
gtk_entry_set_text(GTK_ENTRY(input), "");
}
void destroy(GtkWidget* widget, gpointer data)
{
gtk_main_quit();
}
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv);
GtkWidget *mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
input = gtk_entry_new();
GtkWidget *send = gtk_button_new_with_label("Send");
// 使用文本视图显示用户的过去输入(以终端方式)。我们将文本视图包装在GtkScrollmainWindowdow中,
// 这使文本视图的内容可滚动:
GtkWidget *scrollWindow = gtk_scrolled_window_new(NULL, NULL);
buffer = gtk_text_buffer_new(NULL);
GtkWidget *textArea = gtk_text_view_new_with_buffer(buffer);
gtk_container_add(GTK_CONTAINER(scrollWindow), textArea);
g_signal_connect(send,"clicked", G_CALLBACK(button_clicked), NULL);
GtkWidget *layout = gtk_grid_new();
gtk_grid_attach(GTK_GRID(layout), scrollWindow, 1, 1, 2, 1);
gtk_grid_attach(GTK_GRID(layout), input, 1, 2, 1, 1);
gtk_grid_attach(GTK_GRID(layout), send, 2, 2, 1, 1);
gtk_container_set_focus_child(GTK_CONTAINER(layout), input);
gtk_container_add(GTK_CONTAINER(mainWindow),layout);
gtk_container_set_border_width(GTK_CONTAINER(mainWindow), 20);
g_signal_connect(mainWindow, "destroy", G_CALLBACK(destroy), NULL);
gtk_widget_show_all(mainWindow);
gtk_main();
return 0;
}
这是在添加了"text 1"、"text 2"、"text 3"和"text 4"之后的样子:
起初,看起来似乎没有滚动条(至少在我的设置中是这样),但将鼠标悬停在文本视图右侧会使它们出现:
英文:
I think you should use GtkScrolledWindow
to achieve this. For example:
#include <gtk/gtk.h>
// User adds contents to this entry.
static GtkWidget *input = NULL;
// The text buffer containing all previous user entries.
static GtkTextBuffer *buffer = NULL;
// When the "userText" button is clicked, all the user added to the
// entry is transfered to the text area.
void button_clicked(GtkWidget *widget, gpointer data)
{
// Get the text added to the entry by the user:
const gchar *userText;
userText = gtk_entry_get_text(GTK_ENTRY(input));
// Insert in the text view (at the end):
GtkTextIter end; // Notice how this is created on the stack! Passing a pointer as usual is not working.
// See : https://stackoverflow.com/questions/52182527/iterators-do-not-belong-to-their-assigned-text-buffer
gtk_text_buffer_get_end_iter(buffer, &end);
gtk_text_buffer_insert(buffer, &end, userText, -1);
gtk_text_buffer_insert(buffer, &end, "\n", -1);
// Clear the user input entry for the next input:
gtk_entry_set_text(GTK_ENTRY(input), "");
}
void destroy(GtkWidget* widget, gpointer data)
{
gtk_main_quit();
}
int main(int argc,char *argv[])
{
gtk_init(&argc,&argv);
GtkWidget *mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
input = gtk_entry_new();
GtkWidget *send = gtk_button_new_with_label("Send");
// A text view is used to show the user's past input (in terminal
// fashion). We wrap the text view in a GtkScrollmainWindowdow, which
// makes the text view's content scrollable:
GtkWidget *scrollWindow = gtk_scrolled_window_new(NULL, NULL);
buffer = gtk_text_buffer_new(NULL);
GtkWidget *textArea = gtk_text_view_new_with_buffer(buffer);
gtk_container_add(GTK_CONTAINER(scrollWindow), textArea);
g_signal_connect(send,"clicked", G_CALLBACK(button_clicked), NULL);
GtkWidget *layout = gtk_grid_new();
gtk_grid_attach(GTK_GRID(layout), scrollWindow, 1, 1, 2, 1);
gtk_grid_attach(GTK_GRID(layout), input, 1, 2, 1, 1);
gtk_grid_attach(GTK_GRID(layout), send, 2, 2, 1, 1);
gtk_container_set_focus_child(GTK_CONTAINER(layout), input);
gtk_container_add(GTK_CONTAINER(mainWindow),layout);
gtk_container_set_border_width(GTK_CONTAINER(mainWindow), 20);
g_signal_connect(mainWindow, "destroy", G_CALLBACK(destroy), NULL);
gtk_widget_show_all(mainWindow);
gtk_main();
return 0;
}
Here is what it looks like after having added "text 1", "text 2", "text 3" and "text 4", in that order:
At first, it seems like there are no scrollbars (at least on my setup), but hovering the mouse on the right side of the text view makes them appear:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论