Meine GTK+ Fragen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Meine GTK+ Fragen

Beitrag von Kanalratte » 27.01.2009 19:53:16

Hallo an alle, die es schon geschafft haben und GTK+ können.
Da ich gerade GTK+ lerne, ergeben sich immer mal wieder einige Fragen, die nach einer Antwort verlangen.
Hier sind die ersten:
1.Wie kann man Buttons eine Breite und eine Höhe zuweisen?
2.Wozu braucht man diverse Boxen?
3.Wie gehe ich mit Signalen um?
4.Wie beende ich ein GTK+ Programm.

Vielleicht wäre hier noch der Hinweis angebracht, dass ich in C Programmiere.

Danke für hoffentlich hilfreichen Antworten
Kanalratte
IN TUX WE TRUST

Benutzeravatar
Leonidas
Beiträge: 2032
Registriert: 28.04.2003 13:48:49
Lizenz eigener Beiträge: MIT Lizenz
Kontaktdaten:

Re: Meine GTK+ Fragen

Beitrag von Leonidas » 29.01.2009 01:26:46

Kanalratte hat geschrieben:1.Wie kann man Buttons eine Breite und eine Höhe zuweisen?
Das macht man normalerweise nicht, dafür ist der Layout-Manager da. Ist auch viel besser so.
Kanalratte hat geschrieben:2.Wozu braucht man diverse Boxen?
Die Boxen kannst du verwenden, um deine Widgets auf dem Fenster richtig anzuordnen.
Wir wollten einen Marsch spielen, aber wir hatten nur Xylophone.

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 29.01.2009 14:11:51

Okay, danke.
Ich hab auch ein Turorial auf pro-linux.de gefunden, da ist alles lang und breit erklärt.
IN TUX WE TRUST

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 15:13:05

Die nächste:
Wie kann ich zwischen den Datentypen umwandeln?
Beispiel:
Ich hab' einen Timer, der liefert gulong und gdouble zurück, jetzt will ich das Ergebnis in einem Label darstellen, welcher gchar[] erwartet.
Wie wandel ich gulong und gdouble in gchar um?

MfG Kanalratte
IN TUX WE TRUST

Benutzeravatar
schorsch_76
Beiträge: 2612
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von schorsch_76 » 30.01.2009 15:36:55

Hi Kanalratte,

du nimmst den Wert den du wandeln willst und erstllst mit g_sprintf die Zeichenkette, die dargestellt werden muss.

http://library.gnome.org/devel/glib/sta ... #g-sprintf

gchar buffer[256];
g_sprintf(buffer,"%d",dein_int);
oder
g_sprintf(buffer,"%g",dein_double);

buffer enthält dann deinen Wert für das Label.

Gruß

schorsch

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 15:42:41

Achtung, ungetestet und für normale (nicht glib) Typen!

Code: Alles auswählen

#include <stdlib.h>
#include <stdio.h>
int main()
{
double var_1=3.5;
unsigned long var_2=1;
char *a;
char *b;

a=malloc(20*sizeof(char));
b=malloc(10*sizeof(char));

snprintf (a, 20, "%f", var_1);
snprintf (b, 10, "%u", var_2);

printf("%s\n", a);
printf("%s\n", b);
free(a);
free(b);

return 0;
}
Edit: Ok, glib hat ein eigenes sprintf, hätte man eigentlich erraten können ...

Benutzeravatar
schorsch_76
Beiträge: 2612
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von schorsch_76 » 30.01.2009 16:14:11

Hi Kanalratte,

ich hab grad nochmal nachgelesen. Um sicher zu gehen (und keine Bufferoverflows zuzulassen) ist es besser g_snprintf () zu verwenden.

Code: Alles auswählen

gchar buffer[256];
g_snprintf(buffer,256,"%d",dein_gulong);

Code: Alles auswählen

gchar buffer[256];
g_snprintf(buffer,256,"%f",dein_gdouble);
Gruß

schorsch

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 17:28:13

Okay, soweit danke, aber da ergibt sich schon ganz spontan das nächste Problem:
Jetz hab' ich 2 Strings(beide gchar) und möchte diese zusammenfügen, finde aber auf library.gnome.org nichts passendes.

Thx Kanalratte
IN TUX WE TRUST

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 17:39:00

cat fügt Dateien zusammen, strcat (oder besser strncat) normal c strings, also sollte es auch etwas wie g_strncat geben.

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 18:11:04

es gibt was, das nennt sich g_srtconcat, da krieg ich aber den error incompatible types in assignment...
IN TUX WE TRUST

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 18:17:13

g_strconcat scheint genau das zu sein, was du haben willst. Poste mal den Quelltext, indem du die Funktion benutzt.

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 18:39:41

Code: Alles auswählen

//gtk timer - timer.c
#include <gtk/gtk.h>
#include <glib.h>
GTimer *timer;
GtkWidget *stsp;
GtkWidget *reset;
GtkWidget *tlabel;
GtkWidget *plabel;
GtkWidget *window;
GtkWidget *hb;
GtkWidget *vb;
gint p;
gulong *micro;
gdouble count;
gchar zeit1[64];
gchar zeit2[64];
gchar str[1024];
int time(){
  if(p == 0){
    p = 1;
    g_timer_start(timer);
    gtk_label_set_text(GTK_LABEL(plabel), "Timer gestartet");
  }
  else{
    p = 0;
    g_timer_stop(timer);
    gtk_label_set_text(GTK_LABEL(plabel), "Timer gestopt");
    count = g_timer_elapsed(timer, micro);
    g_snprintf(zeit1, 64, "%f", count);
    g_snprintf(zeit2, 64, "%d", micro);
    str = g_strconcat(zeit1, ",", zeit2);
    gtk_label_set_text(GTK_LABEL(tlabel), str);
  }
  return 0;
}
int main(int argc, char *argv[]){
  //initialisierung
  gtk_init(&argc, &argv);
  timer = g_timer_new();
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  stsp   = gtk_button_new_with_label("Start / Stop");
  reset  = gtk_button_new_with_label("Reset");
  hb     = gtk_hbox_new(FALSE, 2);
  vb     = gtk_vbox_new(FALSE, 2);
  tlabel = gtk_label_new("");
  plabel = gtk_label_new("");
  gtk_container_set_border_width(GTK_CONTAINER(window), 2);
  gtk_window_set_title(GTK_WINDOW(window), "Timer");
  gtk_window_set_default_size(GTK_WINDOW(window), 500, 100);
  //boxen packen
  //hb
  gtk_box_pack_start(GTK_BOX(hb), stsp, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(hb), reset, TRUE, TRUE, 2);
  //vb
  gtk_box_pack_start(GTK_BOX(vb), plabel, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vb), tlabel, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, TRUE, 2);
  //signale
  gtk_signal_connect(GTK_OBJECT(stsp), "clicked", GTK_SIGNAL_FUNC(time), NULL);
  gtk_signal_connect(GTK_OBJECT(reset), "clicked", GTK_SIGNAL_FUNC(g_timer_reset), timer);
  gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
  //container und widget
  gtk_container_add(GTK_CONTAINER(window), vb);
  gtk_widget_show_all(window);
  gtk_main();
  return 0;
}
in Funktion Time
Compiler-Error:
timer.c: In function ‘time’:
timer.c:31: error: incompatible types in assignment
IN TUX WE TRUST

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 18:50:07

Ohne es ausprobiert zu haben: micro ist der Pointer, *micro der Wert auf den der Pointer zeigt und den du ausgeben willst, also sollte der Aufruf von gsnprintf so aussehen (das %ul, da es ein unsigned long ist, mehr zu format strings in "man 3 printf"):

Code: Alles auswählen

g_snprintf(zeit2, 64, "%ul", *micro);
Edit: Der Aufruf von g_strconcat sollte so aussehen, g_stroncat scheint intern malloc zu verwenden:

Code: Alles auswählen

gchar *str;
...
str = g_strconcat(zeit1, ",", zeit2, NULL);
...
free(str);
Zuletzt geändert von Spasswolf am 30.01.2009 18:59:33, insgesamt 2-mal geändert.

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 18:53:28

nein, selber error
IN TUX WE TRUST

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 18:58:40

Hab mich auch verzählt :mrgreen:

Benutzeravatar
king-crash
Beiträge: 742
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von king-crash » 30.01.2009 19:29:21

Ganz nebenbei bemerkt: Lass das mit GTK bis du programmieren kannst was du hier bringst zeugt von völliger Unwissenheit...
Bin kein Spielverderber und lass dich deinen Fehler trotzdem wissen:

falsch:
gchar str[1024];*MÖÖÖP*
g_snprintf(zeit1, 64, "%f", count);*MÖÖÖP*
g_snprintf(zeit2, 64, "%d", micro);*MÖÖÖP*
str = g_strconcat(zeit1, ",", zeit2);*MÖÖÖP*

richtig:
gchar *str;
g_snprintf(zeit1, 64, "%lf", count);
g_snprintf(zeit2, 64, "%ld", *micro);
str = g_strconcat(zeit1, ",", zeit2, NULL);


^^

Benutzeravatar
king-crash
Beiträge: 742
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von king-crash » 30.01.2009 19:29:53

btw: #include <glib.h> brauchste net...

Benutzeravatar
Leonidas
Beiträge: 2032
Registriert: 28.04.2003 13:48:49
Lizenz eigener Beiträge: MIT Lizenz
Kontaktdaten:

Re: Meine GTK+ Fragen

Beitrag von Leonidas » 30.01.2009 19:50:22

king-crash hat geschrieben:Ganz nebenbei bemerkt: Lass das mit GTK bis du programmieren kannst was du hier bringst zeugt von völliger Unwissenheit...
Deswegen haben peschmae und ich im anderen Thread zu Python + PyGTK geraten.

Warum: Keine g*-Datentypen. PyGTK arbeitet immer mit den Python-Datentypen und konvertiert selbst. Strings konkatenieren geht so: "string" + "strong" und fertig ist der neue String, der in einem Label angezeigt werden kann. Darüber hinaus ist der Weg auch sicher, man muss sich nicht darum kümmern, unsichere Operationen wie ``strcpy`` zu vermeiden.
Wir wollten einen Marsch spielen, aber wir hatten nur Xylophone.

Benutzeravatar
schorsch_76
Beiträge: 2612
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von schorsch_76 » 30.01.2009 19:59:51

Naja, ich muss sagen: Programmieren lernt man nur durchs programmieren. Man lernt daraus auch wie man sich Informationen besorgt. Wie man Specs liest. Im Prinzip ist es egal ob ich mit Python oder mit C++ anfange. Jede (Script)-Sprache hat ihre Vor und Nachteile.

Gruß

schorsch

Kanalratte
Beiträge: 226
Registriert: 06.12.2008 11:45:56
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Internet

Re: Meine GTK+ Fragen

Beitrag von Kanalratte » 30.01.2009 20:42:14

Okay, ich seh ja ein, dass ich noch nich so gut bin, aber ihr habt auch was übersehen.
wenn ich den Button Start/Stop zum 2ten mal drücke, krieg ich 'nen Speicherzugriffsfehler....
Woran liegt das?
IN TUX WE TRUST

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 21:22:12

So ich hab es jetzt an einen Rechner geschafft auf dem auch ein Compiler installiert ist. So funktioniert die Sache:

Code: Alles auswählen

//gtk timer - timer.c
#include <gtk/gtk.h>
#include <glib.h>
GTimer *timer;
GtkWidget *stsp;
GtkWidget *reset;
GtkWidget *tlabel;
GtkWidget *plabel;
GtkWidget *window;
GtkWidget *hb;
GtkWidget *vb;
gint p;
gulong *micro;
gdouble count;
gchar zeit1[64];
gchar zeit2[64];
gchar *str;
int testtime(){
  if(p == 0){
    p = 1;
    g_timer_start(timer);
    gtk_label_set_text(GTK_LABEL(plabel), "Timer gestartet");
  }
  else{
    p = 0;
    g_timer_stop(timer);
    gtk_label_set_text(GTK_LABEL(plabel), "Timer gestopt");
    count = g_timer_elapsed(timer, micro);
    g_snprintf(zeit1, 64, "%f", count);
    if(micro){
    g_snprintf(zeit2, 9, "%u" , (unsigned int)*micro);
    str = g_strconcat(zeit1, ",", zeit2);
    gtk_label_set_text(GTK_LABEL(tlabel), str);
    }
    else{
    printf("Warnung micro ist NULL Pointer\n");
    gtk_label_set_text(GTK_LABEL(tlabel), zeit1);
    }
  }
  return 0;
}
int main(int argc, char *argv[]){
  //initialisierung
  gtk_init(&argc, &argv);
  timer = g_timer_new();
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  stsp   = gtk_button_new_with_label("Start / Stop");
  reset  = gtk_button_new_with_label("Reset");
  hb     = gtk_hbox_new(FALSE, 2);
  vb     = gtk_vbox_new(FALSE, 2);
  tlabel = gtk_label_new("");
  plabel = gtk_label_new("");
  gtk_container_set_border_width(GTK_CONTAINER(window), 2);
  gtk_window_set_title(GTK_WINDOW(window), "Timer");
  gtk_window_set_default_size(GTK_WINDOW(window), 500, 100);
  //boxen packen
  //hb
  gtk_box_pack_start(GTK_BOX(hb), stsp, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(hb), reset, TRUE, TRUE, 2);
  //vb
  gtk_box_pack_start(GTK_BOX(vb), plabel, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vb), tlabel, TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, TRUE, 2);
  //signale
  gtk_signal_connect(GTK_OBJECT(stsp), "clicked", GTK_SIGNAL_FUNC(testtime), NULL);
  gtk_signal_connect(GTK_OBJECT(reset), "clicked", GTK_SIGNAL_FUNC(g_timer_reset), timer);
  gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
  //container und widget
  gtk_container_add(GTK_CONTAINER(window), vb);
  gtk_widget_show_all(window);
  gtk_main();
  return 0;
}
Das Problem ist, das micro immer ein NULL Pointer ist. Das ist wohl ein Fehler in glib, wobei der microseconds Parameter eh nicht benötigt wird, denn die Sekundenbruchteile werden auch schon im Rückgabewert von g-timer-elapsed berücksichtigt[1] (The microseconds out parameter is essentially useless.).


[1] http://library.gnome.org/devel/glib/sta ... er-elapsed
Zuletzt geändert von Spasswolf am 30.01.2009 22:24:54, insgesamt 1-mal geändert.

Benutzeravatar
schorsch_76
Beiträge: 2612
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von schorsch_76 » 30.01.2009 21:30:38

Hi Spasswolf,

du hast hier aber noch ein Speicherloch:
g_strconcat ()

gchar* g_strconcat (const gchar *string1,
...);
Concatenates all of the given strings into one long string. The returned string should be freed when no longer needed.

The variable argument list must end with NULL. If you forget the NULL, g_strconcat() will start appending random memory junk to your string.


testtime sollte etwa so aussehen ...

Code: Alles auswählen

    gchar* str;
...
    g_snprintf(zeit1, 64, "%f", count);
    g_snprintf(zeit2, 64, "%d", micro);
    str = g_strconcat(zeit1, ",", zeit2,NULL);
    gtk_label_set_text(GTK_LABEL(tlabel), str);
    free(str);
...
Gruß

schorsch

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 21:53:25

schorsch_76 hat geschrieben:Hi Spasswolf,

du hast hier aber noch ein Speicherloch:
g_strconcat ()

gchar* g_strconcat (const gchar *string1,
...);
Concatenates all of the given strings into one long string. The returned string should be freed when no longer needed.

The variable argument list must end with NULL. If you forget the NULL, g_strconcat() will start appending random memory junk to your string.
schorsch
Jein, der Zweig indem g_strconcat enthalten ist wird ja nie durchlaufen.

Benutzeravatar
schorsch_76
Beiträge: 2612
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Meine GTK+ Fragen

Beitrag von schorsch_76 » 30.01.2009 22:04:11

Spasswolf hat geschrieben: ...
Jein, der Zweig indem g_strconcat enthalten ist wird ja nie durchlaufen.
Doch. Er wird durchlaufen, wenn du den Start/Stop Button drückst. In diesem Fall beim zweiten drücken. Also dem Stop.

Gruß

schorsch

Spasswolf
Beiträge: 3472
Registriert: 30.11.2005 10:32:22
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Wald

Re: Meine GTK+ Fragen

Beitrag von Spasswolf » 30.01.2009 22:26:45

Hab den Code noch ein wenig geändert (if else statt 2 x if):

Code: Alles auswählen

if(micro){
    g_snprintf(zeit2, 9, "%u" , (unsigned int)*micro);
    str = g_strconcat(zeit1, ",", zeit2);
    gtk_label_set_text(GTK_LABEL(tlabel), str);
    }
    else{
    printf("Warnung micro ist NULL Pointer\n");
    gtk_label_set_text(GTK_LABEL(tlabel), zeit1);
    }
In diesem Teil wird nur der else Teil durchlaufen.

Antworten