 |
GTK+ Forums Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
|
|
|
| Author |
Message |
|
|
Micah Carrick Never Seen the Sunlight
Joined: 21 Sep 2005 Posts: 546 Location: Portland, OR USA
|
Posted: Thu May 08, 2008 12:26 pm Post subject: Automatically scroll to end of GtkTextView |
|
|
This little example shows how you can use gtk_text_view_scroll_to_iter () to automatically scroll to the end of a GtkTextView when you insert text. This would commonly be used to implement a status log or something of that nature.
This example uses a GtkBuilder XML file created using Glade and therefore requires GTK+ 2.12 or greater.
Compile using:
| Code: (Plaintext) | 1
| cc -Wall -g main.c -o example -export-dynamic `pkg-config --cflags --libs gtk+-2.0` |
ui.xml
| Code: (XML/HTML) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| <?xml version="1.0"?>
<interface>
<object class="GtkWindow" id="window">
<property name="border_width">4</property>
<signal name="destroy" handler="gtk_main_quit"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<object class="GtkEntry" id="entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Log Message</property>
<signal name="clicked" handler="on_button_clicked"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<object class="GtkTextView" id="textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface> |
main.c
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| /*
Example logging to a GtkTextView and automatically scrolling to the newly
inserted text.
Written for www.gtkforums.com by Micah Carrick
Compile using:
cc -Wall -g main.c -o example -export-dynamic `pkg-config --cflags --libs gtk+-2.0`
*/
#include <gtk/gtk.h>
/* structure to hold references to our widgets */
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} MyWidgets;
/* call back function for when the button is pressed */
void
on_button_clicked (GtkWidget* widget, gpointer user_data)
{
MyWidgets *widgets;
gchar *message;
GtkTextBuffer *buffer;
GtkTextIter iter;
/* cast the gpointer user_data into the MyWidgets structure */
widgets = (MyWidgets *)user_data;
/* build message to log appending a new line char to the end */
message = g_strconcat (gtk_entry_get_text (GTK_ENTRY (widgets->entry)),
"\n", NULL);
/* get the text buffer */
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widgets->textview));
/* get end iter */
gtk_text_buffer_get_end_iter (buffer, &iter);
/* add the message to the text buffer */
gtk_text_buffer_insert (buffer, &iter, message, - 1);
g_free (message);
/* scroll to end iter */
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (widgets->textview),
&iter, 0.0, FALSE, 0, 0);
}
int
main ( int argc, char *argv[])
{
GtkWidget *window;
GtkBuilder *builder;
MyWidgets *widgets;
PangoFontDescription *font_desc;
GError *err = NULL;
/* allocate space for widgets struct */
widgets = g_slice_new (MyWidgets);
/* initialize the GTK+ library */
gtk_init (&argc, &argv);
/* Build UI from xml description */
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "ui.xml", &err);
if (err)
{
/* There was an error building the interface */
g_error (err->message);
g_error_free (err);
g_slice_free (MyWidgets, widgets);
return 1;
}
/* get widgets from GladeXML object */
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
widgets->entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
widgets->textview = GTK_WIDGET (gtk_builder_get_object (builder,
"textview"));
/* connect callback functions passing MyWidgets struct as user_dada */
gtk_builder_connect_signals (builder, widgets);
/* free memory used by builder object and XML */
g_object_unref (G_OBJECT (builder));
/* use a fixed width font on the text view so the output looks proper */
font_desc = pango_font_description_from_string ( "monospace 10");
gtk_widget_modify_font (widgets->textview, font_desc);
pango_font_description_free (font_desc);
/* show the main window */
gtk_widget_show (window);
gtk_main ();
/* free space for widget struct */
g_slice_free (MyWidgets, widgets);
return 0;
}
| |
|
| Back to top |
|
 |
Vadi GTK+ Geek
Joined: 28 May 2008 Posts: 67
|
Posted: Wed May 28, 2008 10:02 pm Post subject: |
|
|
| Code: (Plaintext) | 1 2 3
| gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (widgets->textview),
&iter, 0.0, FALSE, 0, 0); |
Does your example work if the text added was wrapped? For me, if the added line was wrapped, it doesn't scroll to the end of the line(s) but to the first one. I tried getting the end iterator after the insertion too, but it's the same thing. |
|
| Back to top |
|
 |
PhilL
Joined: 03 Jul 2008 Posts: 1
|
Posted: Thu Jul 03, 2008 2:30 pm Post subject: |
|
|
| Vadi wrote: | | Code: (Plaintext) | 1 2 3
| gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (widgets->textview),
&iter, 0.0, FALSE, 0, 0); |
Does your example work if the text added was wrapped? For me, if the added line was wrapped, it doesn't scroll to the end of the line(s) but to the first one. I tried getting the end iterator after the insertion too, but it's the same thing. |
I remember having problems with this in the past, and I think you need to use a new iterator in the second call to gtk_text_buffer_get_end_iter
An alternative approach is to use:
| Code: (Plaintext) | 1 2
| mk = gtk_text_buffer_get_mark (buffer, "insert");
gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (widgets->textview), mk, 0.0, FALSE, 0.0, 0.0); |
If your textview is non-editable, the insert mark (which is automatically maintained for you) should always point at the end of the buffer.
Phil |
|
| Back to top |
|
 |
mamalmst
Joined: 21 Aug 2008 Posts: 1
|
Posted: Thu Aug 21, 2008 5:55 am Post subject: |
|
|
The following code snippet does scroll to the end no matter if you manually have moved the scrollbar or clicked your cursor somewhere in the text.
| Code: (Plaintext) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| /* get the text buffer */
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_field));
/* get end iter */
gtk_text_buffer_get_end_iter (buffer, &end_start_iter);
/* set the text in the buffer */
gtk_text_buffer_insert(buffer,&end_start_iter, text, -1);
/* get end iter again */
gtk_text_buffer_get_end_iter (buffer, &end_start_iter);
/* get the current ( cursor )mark name */
insert_mark = gtk_text_buffer_get_insert (buffer);
/* move mark and selection bound to the end */
gtk_text_buffer_place_cursor(buffer, &end_start_iter);
/* scroll to the end view */
gtk_text_view_scroll_to_mark( GTK_TEXT_VIEW (text_field),
insert_mark, 0.0, TRUE, 0.0, 1.0); | |
|
| Back to top |
|
 |
Javadev
Joined: 04 Aug 2009 Posts: 1 Location: Rostock (Germany)
|
Posted: Wed Sep 09, 2009 7:47 pm Post subject: - - - a good function to add text in the textview - - - |
|
|
The first use of the GtkTextView isn't easy. In the start I have had also some problems with the "text-buffer", "text-iter" and the "text-mark". Unfortunately I found this article to late.
Meanwhile I wrote a function for the easy use the GtkTextView for my project. I think this is a good function for beginners or the fast use.
Whenever you call the function, the function will write the parameter (gchar) in a GtkTextView. The text will be added and the GtkTextView does scroll at last row.
If you would like the function you need a global widget from type GtkTextView.
For example:
| Code: (Plaintext) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| static GtkWidget *textArea;
textArea = gtk_text_view_new();
/* Add the widget on the scroll window. */
gtk_container_add(GTK_CONTAINER(scrollWindow), textArea);
/* The function is really easy. As parameter you need a pointer to a gchar string. */
static void fWriteInTextView(gchar *data){
gtkTextBuffer *buffer;
gtkTextMark *mark;
gtkTextIter iter;
/* Returns the GtkTextBuffer being displayed by this text view. */
buffer = gtk_text_view_get_buffer(gtk_TEXT_VIEW(textArea));
/* Returns the mark that represents the cursor (insertion point). */
mark = gtk_text_buffer_get_insert(buffer);
/* Initializes iter with the current position of mark. */
gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
/* Inserts buffer at position iter. */
gtk_text_buffer_insert(buffer, &iter, data, -1);
/* Scrolls text_view the minimum distance such that mark is contained within the visible area of the widget. */
gtk_text_view_scroll_mark_onscreen(gtk_TEXT_VIEW(textArea), mark);
}
|
After this you can use the function.
1. fWriteInTextView("Hello World!");
Or with a function which will be return a pointer of gchar.
2. fWriteInTextView(fReturnDate());
Or with the ingenious glib function.
3. fWriteInTextView(g_strconcat(fReturnDate() , ": Hello", data, "\n", NULL); // data = "World!";
Have a lot of fun, if you use the function. |
|
| Back to top |
|
 |
|
Powered by phpBB © 2001, 2005 phpBB Group CodeBB 1.0 Beta 2
|