GTK+: TreeView + Icons
-
Hi,
ich schreibe gerade ein kleines Programm, das ein Verzeichnis einliest und dieses dann in einer GtkTreeView darstellt. Das habe ich dank diesem Tutorial: http://developer.gnome.org/gtk/stable/TreeWidget.html auch schon erfolgreich hinbekommen.
Jetzt würde ich gerne noch Icons in die TreeView einfügen. Hier mal ein Screenshot der Andwendung:
http://www.abload.de/img/2011-12-15-211716_495xtbmk.png.hidden
z.B. ist ein Ordner, deshalb soll vor dem Namen (Spalte Name) ein Ordnericon eingefügt werden.Makefile
hingegen ist eine Datei, deshalb soll vor solch einem Eintrag ein Dateiicon angezeigt werden. Am liebsten wäre es mir, wenn sich das ganze mit mit einem GTK_STOCK_ICON umsetzen lassen würde.Weiß da jemand rat?
Vielen Dank für eure Hilfe.
Lg,
Fabi
-
Ich habe das jetzt noch nicht so sehr gebraucht, es sollte aber kein all zu grosses Problem sein... Schau mal hier:
http://developer.gnome.org/gtk/2.24/GtkCellRendererPixbuf.html
Vielleicht hilfts ja.
-
Schau Dir auch das hier an:
http://developer.gnome.org/gtk/2.24/GtkListStore.html#gtk-list-store-new
Denke immer daran, Du hast es mit einem MVC Konzept zu tun...
-
@abcdefg: Vielen dank für die Links. Das hilft mir schon weiter. Das werde ich mal ausprobieren. Bin mal gespannt ob das Look & Feel dann auch so ist, wie ich mir das vorgestellt habe.
Lg,
Fabi
-
Also mit GtkCellRendererPixbuf hat es funktioniert.
Vielen Dank dafür.Jetzt habe ich aber noch eine Frage, und zwar, wie kann ich denn einer Callbackfunktion mehrere Parameter übergeben.
Eine Callbackfunktion sieht ja folgendermaßen aus:
void button_open_clicked( GtkButton *pbtn, gpointer data)
Wie kann ich jetzt zum Beispiel folgende Daten übergeben:
char* GtkWidget* GtkWidget*
Irgendwie finde ich dazu keine vernünftige Erklärung.
gpointer ist ja eigentlich ein void Pointer, aber was für eine Struktur/Objekt soll/kann ich denn dazu übergeben?
Vielen Dank für eure Hilfe.
Grüße,
Fabi
-
Fabi++ schrieb:
Jetzt habe ich aber noch eine Frage, und zwar, wie kann ich denn einer Callbackfunktion mehrere Parameter übergeben.
Eine Callbackfunktion sieht ja folgendermaßen aus:
void button_open_clicked( GtkButton *pbtn, gpointer data)
Wie kann ich jetzt zum Beispiel folgende Daten übergeben:
char* GtkWidget* GtkWidget*
Irgendwie finde ich dazu keine vernünftige Erklärung.
gpointer ist ja eigentlich ein void Pointer, aber was für eine Struktur/Objekt soll/kann ich denn dazu übergeben?
Vielen Dank für eure Hilfe.
Grüße,
FabiDas ist aber jetzt eher eine C Frage. Wenn ich GTK+ Programme schreibe, mache ich das etwa wie folgt:
typedef struct { gchar *blbla; GtkWidget *foo; GtkWidget *foo2; } Gtk_foo_Fields;
In der main() sieht das dann so aus:
[...] Gtk_foo_Fields *data; // // Speicher alocieren work = g_slice_new(Gtk_foo_Fields); [...]
Und dann gibst Du beim Connect eben data an. Beziehen auf Deine Felder tust Du Dich dann im Callback etwa so:
void button_open_clicked( GtkButton *pbtn, Gtk_foo_Fields *data) [...] irgend_eine_GTK_Funktion([...](data->foo)[...]); [...]
Den Speicher gibst Du mit g_slice_free wieder frei.
Aber das ist eher C... :xmas1:
-
abcdefg schrieb:
[...] Gtk_foo_Fields *data; // // Speicher alocieren work = g_slice_new(Gtk_foo_Fields); [...]
Es muss natürlich
[...] Gtk_foo_Fields *data; // // Speicher alocieren data = g_slice_new(Gtk_foo_Fields); [...]
heissen
-
@abcdefg: Danke, so hat es funktioniert.
Ich habe noch eine Frage und zwar verwende ich auf meiner GUI eine GtkProgressBar.
Wenn ein bestimmter Button auf meiner GUI gelickt wird ("clicked"-event) wird eine Routine angestossen und die Progressbar soll den fortschritt anzeigen.Leider wird die Progressbar nicht akualisiert.
Folgendermaßen sieht das ganze aus:
g_signal auf den Button:
g_signal_connect( btn_sync, "clicked", G_CALLBACK(button_sync_clicked), sync_fl );
void button_sync_clicked( GtkButton *pbtn, sync_folders *param ) { /*Code zum testen der Progressbar!!*/ int i = 0; char tmp[10]; for( i = 0; i <= 100; i++ ) { gtk_progress_bar_pulse( param->bar ); sprintf( tmp, "%d", i ); gtk_progress_bar_set_text( param->bar, tmp ); sleep( 1 ); } }
Die For-Schleife soll mir eigentlich momentan nur anzeigen, dass etwas passiert. Aber die Progressbar macht nichts, erst wenn die Schleife dann komplett durchgelaufen ist, wird
100
als Text in der Progressbar angezeigt.
Ich hätte das ganze aber gerne so, dass bei jedem Schritt der Inhalt aktualisiert wird, und sich die Progressbar bzw. der Balken darin bewegt.
ich habe auch schon ans Ende der Schleife einsleep( 1 )
gesetzt, damit das ganze etwas langsamer ist um etwas zu sehen.
Es scheint aber so, dass die Progressbar erst aktualisiert wird, wenn alle Aktion der callback-Funktion ausgeführt sind.
Weiß jemand zufällig, wie ich es anstellen kann, dass die Progressbar bei jedem Schritt aktualisiert wird?
Vielen Dank für eure Hilfe.
Grüße,
Fabi
-
Fabi++ schrieb:
Ich hätte das ganze aber gerne so, dass bei jedem Schritt der Inhalt aktualisiert wird, und sich die Progressbar bzw. der Balken darin bewegt.
ich habe auch schon ans Ende der Schleife einsleep( 1 )
gesetzt, damit das ganze etwas langsamer ist um etwas zu sehen.
Es scheint aber so, dass die Progressbar erst aktualisiert wird, wenn alle Aktion der callback-Funktion ausgeführt sind.
Dur wirst hier um "Multithreading" nicht herumkommen. Nach ein klein wenig Googeln bin ich auf folgendes Beispiel gestossen:
#include <gtk/gtk.h> //****************** // lengthy_func_done // END OF THE LENGTHY FUNC //****************** gboolean lengthy_func_done(gpointer data) { GtkWidget *dialog; g_source_remove(GPOINTER_TO_INT(g_object_get_data(data, "source_id"))); gtk_widget_destroy(GTK_WIDGET(data)); dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Operation completed!"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return FALSE; } //****************** // async_lengthy_func //****************** gpointer async_lengthy_func(gpointer data) { int i; for (i=1;i<=50000;i++) { printf("ok,%d",i); } g_idle_add(lengthy_func_done, data); return NULL; } //****************** // update_progress() //****************** gboolean update_progress(gpointer data) { gtk_progress_bar_pulse(GTK_PROGRESS_BAR(data)); return TRUE; } //****************** // on_clicked() //****************** void on_clicked(GtkWidget *button, gpointer data) { GtkWidget *win, *w, *vbox; guint sid; /* create the modal window which warns the user to wait */ win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_modal(GTK_WINDOW(win), TRUE); gtk_window_set_title(GTK_WINDOW(win), "Progress"); gtk_container_set_border_width(GTK_CONTAINER(win), 12); g_signal_connect(win, "delete_event", G_CALLBACK(gtk_true), NULL); vbox = gtk_vbox_new(FALSE, 12); gtk_widget_show(vbox); /* create label */ w = gtk_label_new("Please wait..."); gtk_widget_show(w); gtk_container_add(GTK_CONTAINER(vbox), w); /* create progress bar */ w = gtk_progress_bar_new(); gtk_widget_show(w); gtk_container_add(GTK_CONTAINER(vbox), w); /* add vbox to dialog */ gtk_container_add(GTK_CONTAINER(win), vbox); gtk_widget_show (win); /* refresh the progress dialog */ sid = g_timeout_add(100, update_progress, w); g_object_set_data(G_OBJECT(win), "source_id", GINT_TO_POINTER(sid)); g_thread_create(async_lengthy_func, win, FALSE, NULL); } //************************************ int main (int argc, char *argv[]) { GtkWidget *window, *button; g_thread_init(NULL); gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL); gtk_window_set_title (GTK_WINDOW (window), "Multithreding"); gtk_container_set_border_width (GTK_CONTAINER (window), 25); gtk_widget_set_size_request (window, 250, 100); button = gtk_button_new_with_mnemonic ("_Func"); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_clicked), (gpointer) button); gtk_container_add (GTK_CONTAINER (window), button); gtk_widget_show_all (window); gtk_main (); return 0; }
Das Programm kannst Du umwandeln wie es dasteht und dann siehst Du den Effekt. Beachte hier folgende Statements:
g_thread_init(NULL); // sid = g_timeout_add(100, update_progress, w); g_object_set_data(G_OBJECT(win), "source_id", GINT_TO_POINTER(sid)); g_thread_create(async_lengthy_func, win, FALSE, NULL); // gtk_progress_bar_pulse(GTK_PROGRESS_BAR(data)); // g_idle_add(lengthy_func_done, data); // g_source_remove(GPOINTER_TO_INT(g_object_get_data(data, "source_id")));
Ich muss dazu aber sagen, dass ich diese Lösung nicht besonders finde - aber sie funktioniert...
Ach ja:
Ich finde es klasse, wie Du Dich da "durchbeisst" - Mach weiter so!
-
@abcdefg:
Dur wirst hier um "Multithreading" nicht herumkommen.
Ok, das werde ich mir mal anschauen. Danke für das auführliche Beispiel.
Werde mich damit morgen früh mal intensiv auseinandersetzen.Ich muss dazu aber sagen, dass ich diese Lösung nicht besonders finde
Ich irgendwie auch nicht, ich habe schon einige Erfahrung mit Qt und Tk und dort waren Progressbars doch etwas weniger "aufwendig" umzusetzen. Ich finde es auch schade, das dazu in der GTK-Doku (http://developer.gnome.org/gtk/stable/GtkProgressBar.html), also zu der Verwendung von Threads im Zusammenhang mit Progressbars nichts gesagt bzw. geschrieben wird.
Ach ja:
Ich finde es klasse, wie Du Dich da "durchbeisst" - Mach weiter so!Vielen Dank für das Kompliment :). Mir macht es einfach Spaß zu Coden und da meine absolute Lieblingssprache C ist bietet sich GTK+ einfach an. Als OS nutze ich Linux und dort selbst vorwiegend GTK+ Programme.
Durch deine Hilfe ist der Einstieg in GTK+ aber auch etwas einfacher. Kann also das Kompliment nur zurückgeben :D.
Verwendest du für die GUI Entwicklung soetwas wie Glade oder machst du das auch alles von Hand.
Ich bin eigentlich ein Fan davon alles selbst zu schreiben, jedoch ist das ganze doch manchmal sehr sehr aufwendig.
Grüße,
Fabi
-
Fabi++ schrieb:
Ich muss dazu aber sagen, dass ich diese Lösung nicht besonders finde
Ich irgendwie auch nicht,
Die Lösung ist grundsätzlich schon ok - ich finde nur, dass der Timeout Callback "eleganter" beendet werden könnte, nämlich mit FALSE und nicht via g_idle_add... aber das findest Du schon selber heraus....