Schiffeversenken mit GTK+ und C
-
Hallo,
Ich bin ein blutiger Anfänger in C sowie GTK+, und nein, ich kann nicht die Finger davon lassen, und mit etwas einfacherem anfangen, weil ich das als Projekt in der Schule habe :S
Ich meine es macht ja spaß, aber andererseits werden wir mit Problemen auch allein gelassen, weil der Lehrer kaum da is...
Und in meiner Gruppe (4 Leute atm, bald aber 5) hat jeder seine Arbeit zu leisten. Einer ist mit dem Netzwerkproblem versorgt, einer mit der Programmlogik (bald 2) und ein weiterer und ich mit der Grafischen Oberfläche.
Da wir noch am "kennenlernen" von GTK+ sind, habe ich eine kleine Frage, wieso folgender code ein leeres Fenster ausgibt.
Am Rande: Wir Programmieren unter SuSE Linux 10.1 mit Eclipse und dem C-Plugin
#include <gtk/gtk.h> #include <stdio.h> #include <stdlib.h> void delete_event( GtkWidget *widget, GdkEvent event, gpointer data ) { gtk_main_quit(); } int main( int argc, char *argv[] ) { GtkWidget *table; GtkWidget *window; GtkWidget *buttonArray[10][10]; int i; int n; gtk_init( &argc, &argv ); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); table = gtk_table_new(10, 10, FALSE); gtk_window_set_title( GTK_WINDOW( window ), "Table Beispiel"); gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); /* Hier wird das 10x10-Button-Feld erstellt */ for(n = 0; n < 10; n++) { for(i = 0; i < 10; i++) { buttonArray[n][i] = gtk_button_new_with_label ("B"); gtk_table_attach_defaults( GTK_TABLE( table ), buttonArray[n][i], i, i + 1, n, n + 1 ); gtk_widget_show (buttonArray[n][i]); } } /* Jetzt kommen wieder die üblichen Beendigungs-Callbacks */ gtk_signal_connect( GTK_OBJECT( window ), "delete_event", GTK_SIGNAL_FUNC( delete_event ), NULL ); gtk_signal_connect_object( GTK_OBJECT( window ), "destroy", GTK_SIGNAL_FUNC( gtk_main_quit ), GTK_OBJECT( window ) ); /* Die Tabelle wird ins Fenster gepackt */ gtk_container_add( GTK_CONTAINER( window ), table ); /* alles was auf window ist, wird angezeigt */ gtk_widget_show(window); gtk_main(); return 0; }
Ich will damit ein Feld erstellen, dass 10x10 Buttons beinhaltet.
Bin für Tipps offen.
Wie gesagt ich habe wenig Ahnung von GTK+
Danke
-
Fast am Ende von main... probier mal gtk_window_show_all(window); anstatt gtk_window_show(window);
Falls es das nicht ist, kann ich erst heute Abend genaueres dazu sagen.
MfG
GPC
-
Yay es hat geklappt, allerdings war es
gtk_widget_show_all(window);
Trotzdem ging es!
Danke, das bringt uns ein großes Stück weiter
//Edit
So nun das Nächste problem, ich hab zwar etwas gesucht @ google und gtk+ reference man aber ich hab nichts gefunden, dass ALLE Buttons dieselbe größe haben, EGAL was drinsteht...
-
TAI06-Wayne schrieb:
Yay es hat geklappt, allerdings war es
gtk_widget_show_all(window);
Äh, ja. Sorry, morgentliche Müdigkeit und so meinerseits.
So nun das Nächste problem, ich hab zwar etwas gesucht @ google und gtk+ reference man aber ich hab nichts gefunden, dass ALLE Buttons dieselbe größe haben, EGAL was drinsteht...
GtkWidget *table = gtk_table_new(10, 10, TRUE);
Zieht euch auch mal das rein: http://gtk.org/tutorial/
-
Hallo, wieder mal ich
Ich wollte fragen ob jemand einen kleinen tipp für mich hat, wie ich jetzt das
g_signal_connect
für jeden Button EINDEUTIG in diese Schleife packen kann.Oder ob andere tipps und tricks mir die Arbeit an der Oberfläche erleichtern. Ich erkläre kurz wie es am Ende aussehen soll:
2 Spielfelder à 10x10 Buttons, die dann pressed bleiben sollen wenn die Schiffe gesetzt werden, in der Mitte zwischen den 2 Feldern eine art Optionsmenu (steht aber noch nicht fest):
_______________________________________ |______________ _____________| | | Options | | | Feld 1 | | Feld 2 | | Spieler | Menü | Gegner | |______________| |_____________| |_______________________________________|
In etwa so.
An sich sollen die gedrückten Buttons ein Signal an die Logik schicken, die dann überprüft ob sie die richtige Anzahl von Buttons für ein Schiff sind, (wie die Logik-coder überprüfen wollen ob das Schiff keine "Ecke" hat, wenn ihr versteht, weiß ich noch nicht) und dann eben diese Buttons pressed bleiben.
Heute ist wieder Projektarbeit, und evtl weitere Fortschritte zu melden!
Danke für eure Hilfe
// EDIT:
GPC schrieb:
GtkWidget *table = gtk_table_new(10, 10, TRUE);
Das is schon ganz ok, kann man aber nicht die größe von einzelnen Buttons festsetzten? also, egal ob was "drin" steht?
Hat aber einen guten fortschritt gegeben!
Danke!
-
Hallo,
schick am Besten noch Daten an die Funktion, zu der connected wird. Zum Einen von welchem Spieler das kam und den Index des Buttons, der gedrückt wurde.
Du kannst die (Mindest-)Größe von Buttons festlegen, schau einfach mal hier: http://gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Widget.html#5e95431f630a226b0b7297e4815ee945
Aber evtl. habt ihr auch nur ein Layout-Problem.
MfG
GPC
-
GPC schrieb:
schick am Besten noch Daten an die Funktion, zu der connected wird. Zum Einen von welchem Spieler das kam und den Index des Buttons, der gedrückt wurde.
Das ist nicht meine Aufgabe^^
Ich bin nur für die Grafik zuständig und muss nur eine Funktion oder ähnliches implementieren, dass die Koordinaten an die Logik weitergibt, darum kümmert sich dann ein weiterer Mann des Teams, aber so weit bin ich noch nich >.> muss eben zuerst ein vorläufiges Layout entwickeln, mit dem dann die anderen Arbeiten können, um zu sehen, ob ihre Arbeit funktionniert...Nur mal so, zur klärung
Bin unterdessen dabei nur einen "Optionen" Button zu machen, und auf eine "normale" größe zu bekommen weil er in der hbox als EINZELNER Button, genauso hoch ist, wie die 2 Felder zur Linken und Rechten :S
Aber dass dürfte kein allzugroßes Problem darstellen, notfalls mach ichs einfach mit ner vbox in die ich dann den Optionen button reinleg...
Cya
//EDIT
GPC schrieb:
Du kannst die (Mindest-)Größe von Buttons festlegen, schau einfach mal hier: http://gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Widget.html#5e95431f630a226b0b7297e4815ee945
und der damit verbundene Code:
Gtk::Window::set_default_size()
in meinem Fall:
Gtk::buttonArray[i][n]::set_default_size()
geht leider nicht! Das liegt Laut dem Projektbetreuer daran, dass Eclipse sehr empfindlich reagiert, wenn in einem C-Projekt C++ Strukuren (die "::") auftauchen (bei mir in dem fall mit 100% systemlast :S) also muss ich entweder die ganze Sache in ein C++ Projekt (:S) aber da keine Ahnung von C++ würd ich das lieber zurückstellen, jedoch find ich dann keine C-Kompatible Lösung
//Edit
Das mit der größe haben wir jetzt im Griff, eben einfach alle auf gleich groß gesetzt, und dann im nachhinein die größe mit Hilfe von Bilder anzupassen.Ich kann aber scheinbar kein Image einem buttonArray[n][i] zuweisen..
. . . image = gtk_image_new_from_file("/home/wayne/workspace/wave.gif"); . . . for(n = 0; n < feldgroesse; n++) { for(i = 0; i < feldgroesse; i++) { buttonArray_s[n][i] = gtk_button_new_with_label ("O"); gtk_table_attach( GTK_TABLE(spielerfeld),b buttonArray_s[n][i], i, i + 1, n, n + 1, 0, 0, 0, 0 ); gtk_widget_show (buttonArray_s[n][i]); gtk_button_set_image(buttonArray_g[n][i], image); } }
gtk_button_set_image(buttonArray_g[n][i], image);
bingt in dem fall:
warning: passing argument 1 of ‘gtk_button_set_image’ from incompatible pointer type
und in der consolenausgabe von Eclipse:
(projektschablone:5672): Gtk-CRITICAL **: gtk_button_set_image: assertion `GTK_IS_BUTTON (button)' failed
//Edit 2
Jetzt geht das image, ALLERDINGS nur auf dem allerletzten Button rechts unten O_o
Ich hab auch schon eine Ahnung woher das kommen könnte, ich glaube nämlich anhand der vorherigen Ausgabe von Eclipse und ein wenig lesestoff den ich gefunden hatte, dass ich das buttonArray, welches alsGtkWidget *buttonArray[n][i]
gecasted ist, "downcasten" (soweit ich gelesen habe) und zwar zu GtkWidget, nur ich finde einfach nicht wie man das macht..
Danke
-
TAI06-Wayne schrieb:
GPC schrieb:
Du kannst die (Mindest-)Größe von Buttons festlegen, schau einfach mal hier: http://gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Widget.html#5e95431f630a226b0b7297e4815ee945
und der damit verbundene Code:
Gtk::Window::set_default_size()
in meinem Fall:
Gtk::buttonArray[i][n]::set_default_size()
geht leider nicht! Das liegt Laut dem Projektbetreuer daran, dass Eclipse sehr empfindlich reagiert, wenn in einem C-Projekt C++ Strukuren (die "::") auftauchen (bei mir in dem fall mit 100% systemlast :S) also muss ich entweder die ganze Sache in ein C++ Projekt (:S) aber da keine Ahnung von C++ würd ich das lieber zurückstellen, jedoch find ich dann keine C-Kompatible Lösung
Laut mir liegt das daran, dass ich Ausversehen in die gtkmm Doku verlinkt habe. Wollte eigentlich zur GTK+ Doku verlinken.
In GTK+ gibt's die Funktion natürlich auch: http://developer.gnome.org/doc/API/2.0/gtk/GtkWidget.html#gtk-widget-set-size-requestgecasted ist, "downcasten" (soweit ich gelesen habe) und zwar zu GtkWidget, nur ich finde einfach nicht wie man das macht..
http://gtk.org/tutorial/c451.html#SEC-CASTING
Ach ja, wenn du hier immer reineditierst sehe ich das natürlich nicht. Ich schaue nur auf Threads, die neue Antworten bekommen haben. In Zukunft als bitte 'nen zusätzlichen Post anhängen und nicht reineditieren. Danke.
MfG
GPC
-
Ok tut mir Leid
das mit dem Casten hat sich geklärt, und jetzt werden auch alle Buttons gezeigt!
Hier der funktionierende Code:#include <gtk/gtk.h> #include <stdio.h> #include <stdlib.h> #include <gtk/gtkwidget.h> void delete_event(GtkWidget *widget, GdkEvent event, gpointer data) { gtk_main_quit(); } void ausgabe(int i, int n) { g_print("Button %i:%i wurde geklickt\n", i, n); } int main( int argc, char *argv[] ) { GtkWidget *spielerfeld = NULL; GtkWidget *gegnerfeld = NULL; GtkWidget *window = NULL; GtkWidget *buttonArray_s[10][10]; GtkWidget *buttonArray_g[10][10]; GtkWidget *hbox; GtkWidget *optionen_but; GtkWidget *image_feld_s[10][10]; GtkWidget *image_feld_g[10][10]; GtkAllocation child_allocation; int feldgroesse = 10; int i; int n; gtk_init(&argc, &argv); printf("\n Z36: window = %p\n", window); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); printf("\n Z38: window = %p\n", window); /* Zuweisungen */ printf("\n Z40: spielerfeld = %p\n", spielerfeld); spielerfeld = gtk_table_new(feldgroesse, feldgroesse, FALSE); printf("\n Z42: spielerfeld = %p\n", spielerfeld); printf("\n Z43: gegnerfeld = %p\n", gegnerfeld); gegnerfeld = gtk_table_new(feldgroesse, feldgroesse, FALSE); printf("\n Z43: gegnerfeld = %p\n", gegnerfeld); hbox = gtk_hbox_new(FALSE, 70); gtk_window_set_title(GTK_WINDOW(window), "Spielfeld"); gtk_container_set_border_width(GTK_CONTAINER(window), 15); child_allocation.height = 20; child_allocation.width = 20; /* Schleife um 10x10 Buttons zu erstellen und mit signalen zu versehen * edit: signale gehen noch nicht * --> SPIELER */ for(n = 0; n < feldgroesse; n++) { for(i = 0; i < feldgroesse; i++) { image_feld_s[n][i] = gtk_image_new_from_file("/home/schuller/workspace/wave.gif"); buttonArray_s[n][i] = gtk_button_new(); gtk_button_set_image(GTK_BUTTON(buttonArray_s[n][i]), image_feld_s[n][i]); gtk_table_attach_defaults(GTK_TABLE(spielerfeld), buttonArray_s[n][i], i, i + 1, n, n + 1 /*, 0, 0, 0, 0*/ ); gtk_widget_show (buttonArray_s[n][i]); } } /* Schleife um 10x10 Buttons zu erstellen und mit signalen zu versehen * edit: signale gehen noch nicht * --> GEGNER */ for(n = 0; n < feldgroesse; n++) { for(i = 0; i < feldgroesse; i++) { image_feld_g[n][i] = gtk_image_new_from_file("/home/schuller/workspace/wave.gif"); buttonArray_g[n][i] = gtk_button_new(); gtk_table_attach_defaults( GTK_TABLE(gegnerfeld), buttonArray_g[n][i], i, i + 1, n, n + 1 /*, 0, 0, 0, 0*/ ); gtk_button_set_image(GTK_BUTTON(buttonArray_g[n][i]), image_feld_g[n][i]); gtk_widget_show (buttonArray_g[n][i]); } } optionen_but = gtk_button_new_with_label("Optionen"); gtk_widget_size_allocate (GTK_BIN (optionen_but)->child, &child_allocation); gtk_box_pack_start(GTK_BOX(hbox), spielerfeld, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), optionen_but, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), gegnerfeld, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(window), hbox); /* Jetzt kommen wieder die üblichen Beendigungs-Callbacks */ gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); gtk_signal_connect_object(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), GTK_OBJECT(window)); /* alles was auf window ist, wird angezeigt */ gtk_widget_show_all(window); gtk_main(); return 0; }
Nun werde ich mich darum kümmern, dass bei "clicked" sich das Bild ändert. Optional, für spätere Vereifachung, packe ich die Spieler-relevanten Felder und Gegner-relevanten Felder in structs, so muss ich Später nicht immer alles neuschreiben, und auch nicht immer neue Argumente an Funktionen hinzufügen, falls ein neues Feld (o.Ä.) hinzukommt.
Danke für eure Hilfe!
Ihr seid SpitzeMarius