PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichnen mit Gtk



_Martin
07-06-2005, 18:50
Hallo.

Könnte viellicht jemand einen Code posten der zeigt wie man mit auf ein gtk-fenster zeichnen kann (linien und ähnliches).
Seit schon ein paar Wochen suche ich nach einem verständlichen Beispielcode.
Leider sind sämtliche Beispiele die ich gefunden habe entweder übelst kompiziert (gtk-demo eingeschlossen) oder schlichtweg falsch, und nach dem man sie kompiliert hat bekommt man Gdk-CRITICAL bla...bla...bla failed.
Ich habe hier sogar ein Buch "GUI-Programierung mit GTK+", das bringt mich auch nicht weiter.
Gtk muss aber auf meinem Rechner richtig instaliert sein sonst würden die ganzen Prorgramme nicht laufen die Gtk verwenden.

Also ich wäre dankbar für jede Hilfe.

BeS
07-06-2005, 22:59
Hallo,
ein Beispiel für Gtk+, also in C, habe ich nicht. Du kannst dafür aber ein DrawingArea Widget verwenden. In der Gtkmm Doku[1] gibt es dazu ein paar Erklärungen, welche man dann relativ einfach auch auf jede andere Sprache mit Gtk+ übertragen kann, dass Prinzip und die Funktionen bleiben ja immer die gleichen.
Ich habe dazu mal vor einiger Zeit ein kleines Beispiel in C# geschrieben. Nichts besonders, nur ein Kreis und zwei Linien, einfach um es mal auszuprobieren. Vielleicht hilft es dir ja dabei es zu verstehen und die richtigen Funktionen für C zu finden.



using System;
using Gtk;

class window : DrawingArea
{
static void Main(string[] args) {
Application.Init();
new window();
Application.Run();
}

public window() {
Window win = new Window("Darwing Test");
win.Add(this);
win.DeleteEvent += quit;
this.ExposeEvent += OnExposed;

win.ShowAll();
}

void OnExposed (object obj, ExposeEventArgs args) {
Gdk.GC gc = new Gdk.GC (this.GdkWindow);
this.GdkWindow.DrawLine (gc, 60,10,60,110);
this.GdkWindow.DrawLine (gc, 10,60,110,60);
this.GdkWindow.DrawArc (gc, false, 10, 10, 100, 100, 90*64, 360*64);
}


void quit (object obj, DeleteEventArgs args) {
Application.Quit();
}
}



[1] http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/index.html

_Martin
08-06-2005, 14:52
Danke für die Antwort.
Aber dein Beispiel genau das was man auch sonst überall findet , also ein aus dem zusammen gerissenes Stücktcode der mir leider nicht weiter hilft.
gtkmm kommt bei mir leider auch nicht in Fragen.

Dennoch Danke für deine Mühe.

_Martin
08-06-2005, 15:13
Vielleicht eine andere Frage, warum ist dieser Code falsch:

/*gcc drawing_area.c -o drawing_area `gtk-config --cflags --libs`*/
#include <gtk/gtk.h>

//-------------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
GtkWidget *window;
GdkGC *gc;
GtkWidget *drawing_area;
GdkDrawable *drawable;

gtk_init( &argc, &argv );

window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);

drawing_area = gtk_drawing_area_new();
drawable = drawing_area->window;
gc = gdk_gc_new(drawable);//warum bekommt man hier ein Gdk-CRITICAL

gtk_container_add( GTK_CONTAINER( window ), drawing_area );
gtk_widget_show_all(window);
gtk_main();
return 0;
}
/* Ende */

BeS
12-06-2005, 11:38
Hallo,
ich hoffe die Antwort kommt nicht zu spät...

Es ist doch richtig was du gemacht hast. Das einzige was noch fehlt ist ein expose-Event, ganz nach dem Beispiel in der API-docu: http://developer.gnome.org/doc/API/2.0/gtk/GtkDrawingArea.html

Dann sieht dein Code so aus und zeichnet jetzt eine Ellipse:


#include <gtk/gtk.h>

gboolean
expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
gdk_draw_arc (widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
TRUE,
0, 0, widget->allocation.width, widget->allocation.height,
0, 64 * 360);

return TRUE;
}

int
main( int argc, char *argv[] )
{
GtkWidget *window;
GtkWidget *drawing_area;

gtk_init( &argc, &argv );

window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);

drawing_area = gtk_drawing_area_new();

g_signal_connect (G_OBJECT (drawing_area), "expose_event",
G_CALLBACK (expose_event_callback), NULL);

gtk_container_add( GTK_CONTAINER( window ), drawing_area );
gtk_widget_show_all(window);
gtk_main();
return 0;
}


PS: ich habe ja nicht gesagt das du gtkmm verwenden sollst. Aber manchmal hilft der Blick in die API-Doku einer der Bindings, da dort vielleicht manchmal etwas genauer oder verständlicher für einen beschrieben ist. Kennt man dann die Funktionen von gtkmm, gtk#, pygtk,... dann findet man auch relativ schnell das richtige für seine Sprache, da letztlich ja alles immer das gleiche ist.

nomad
14-06-2005, 15:36
hi
hier ein kleines beispiel
mfg nomad

*gcc drawing_area.c -o drawing_area `gtk-config --cflags --libs`*/
#include <gtk/gtk.h>


/************************************************** ************************************************** ***************/
// functions

void button1_funk(GtkWidget *widget, gpointer daten);
void button2_funk(GtkWidget *widget, gpointer daten);
/******************/
// widgets:

GtkWidget *window;
GtkWidget *scrolledwindow1;
GtkWidget *layout1;
GtkWidget *drawingarea1;
GtkWidget *button1;

GtkWidget *pixmapwid;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkStyle *style;

GdkGC *kontext;
GdkGC *kontext1;
GdkVisual *visual;
GdkColormap *cmap;

GdkColor red = { 0, 0xFF00, 0x00, 0x00 };
GdkColor black = { 0, 0x00, 0x00, 0x00 };
GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
GdkColor blue = { 0, 0x00, 0x00, 0xff00 };
GdkColor yellow = { 0, 0xff00, 0xff00, 0x00 };
GdkColor green = { 0, 0x0000, 0xb000, 0x0000 };
GdkColor green2 = { 0, 0x0000, 0xff00, 0x0000 };
GdkColor mygray = { 0, 0xd500, 0xd600, 0xd500 };

GdkDrawable *mydrawable;
GdkDrawable *mydrawable1;

int bdaten1, bdaten2, bdaten3;
/******************************************/
// Backing pixmap for drawing area
// static GdkPixmap *pixmap = NULL;

// Create a new backing pixmap of the appropriate size

static gint configure_event(GtkWidget *widget, GdkEventConfigure *event )
{
if(pixmap)
gdk_pixmap_unref(pixmap);

pixmap = gdk_pixmap_new(widget->window,widget->allocation.width,widget->allocation.height,-1);
gdk_draw_rectangle (pixmap,widget->style->white_gc,TRUE,0, ,widget->allocation.width,widget->allocation.height);
gdk_draw_rectangle(pixmap,widget->style->black_gc,FALSE,0,0,640,440);

return TRUE;
}

// Redraw the screen from the backing pixmap
static gint expose_event( GtkWidget *widget, GdkEventExpose *event )
{
gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],pixmap,event->area.x,event->area.y,event->area.x, event->area.y, event->area.width, event->area.height);

return FALSE;
}

// Draw a rectangle on the screen
static void draw_brush( GtkWidget *widget,gdouble x,gdouble y)
{
GdkRectangle update_rect;

update_rect.x = x - 1;
update_rect.y = y - 1;
update_rect.width = 1;
update_rect.height = 1;
gdk_draw_rectangle (pixmap,widget->style->black_gc, TRUE, update_rect.x, update_rect.y, update_rect.width,update_rect.height);
gtk_widget_draw (widget, &update_rect);

g_print("CalcPos\n");

mposX = x; // update_rect.x;
mposY = y; // update_rect.y;
nomadXpos = x;
nomadYpos = y;

printf("mausPosX: %f, mausPosY: %f\n",mposX,mposY);


}

static gint button_press_event( GtkWidget *widget, GdkEventButton *event )
{
if(event->button == 1 && pixmap != NULL)
draw_brush (widget, event->x, event->y);

return TRUE;
}

static gint motion_notify_event( GtkWidget *widget,GdkEventMotion *event )
{
int x, y;
GdkModifierType state;

if(event->is_hint)
gdk_window_get_pointer (event->window, &x, &y, &state);
else
{
x = event->x;
y = event->y;
state = event->state;
mposX = x; // update_rect.x;
mposY = y; // update_rect.y;
nomadXpos = x;
nomadYpos = y;


}

if(state & GDK_BUTTON1_MASK && pixmap != NULL)
draw_brush (widget, x, y);

return TRUE;
}

//-------------------------------------------------------------------------------
main( )
{
gtk_set_locale();

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(window, 795,500);
gtk_window_set_title(GTK_WINDOW (window), "The Navigator Version 0.0.2.8.(c)RCI 2005");
gtk_window_set_modal(GTK_WINDOW (window), TRUE);

scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_ref(scrolledwindow1);
gtk_object_set_data_full(GTK_OBJECT (window), "scrolledwindow1", scrolledwindow1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show(scrolledwindow1);
gtk_container_add(GTK_CONTAINER (window), scrolledwindow1);

layout1 = gtk_layout_new(NULL, NULL);
gtk_widget_ref(layout1);
gtk_object_set_data_full(GTK_OBJECT (window), "layout1", layout1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show(layout1);
gtk_container_add(GTK_CONTAINER (scrolledwindow1), layout1);
gtk_layout_set_size(GTK_LAYOUT (layout1), 100, 100);
GTK_ADJUSTMENT(GTK_LAYOUT (layout1)->hadjustment)->step_increment = 10;
GTK_ADJUSTMENT(GTK_LAYOUT (layout1)->vadjustment)->step_increment = 10;

drawingarea1 = gtk_drawing_area_new();
gtk_widget_ref(drawingarea1);
gtk_object_set_data_full(GTK_OBJECT (window), "drawingarea1", drawingarea1,
(GtkDestroyNotify) gtk_widget_unref);

gtk_layout_put (GTK_LAYOUT (layout1), drawingarea1, 10,10);
gtk_widget_set_usize (drawingarea1, 640,440);
gtk_widget_show (drawingarea1);

// Signals used to handle backing pixmap
gtk_signal_connect(GTK_OBJECT (drawingarea1), "expose_event",(GtkSignalFunc) expose_event, NULL);
gtk_signal_connect (GTK_OBJECT(drawingarea1),"configure_event",(GtkSignalFunc) configure_event, NULL);

// Event signals
gtk_signal_connect (GTK_OBJECT (drawingarea1), "motion_notify_event",(GtkSignalFunc) motion_notify_event, NULL);
gtk_signal_connect (GTK_OBJECT (drawingarea1), "button_press_event",(GtkSignalFunc) button_press_event, NULL);

gtk_signal_connect(GTK_OBJECT(drawingarea1),"expose_event",(GtkSignalFunc)expose_event_callback,NULL);

gtk_widget_set_events (drawingarea1, GDK_EXPOSURE_MASK
| GDK_LEAVE_NOTIFY_MASK
| GDK_BUTTON_PRESS_MASK
| GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK);

// startbutton1
button1 = gtk_button_new_with_label("GPS-Start");
gtk_widget_ref(button1);
gtk_object_set_data_full(GTK_OBJECT (window), "button1", button1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show(button1);
gtk_layout_put(GTK_LAYOUT (layout1), button1,660,20); //870, 40);
gtk_widget_set_usize(button1, 100, 22);


gtk_main();
return 0;
}
/****************************/
// GPS_Start
void button1_funk(GtkWidget *widget, gpointer zdaten)
{

}
/* Ende */

_Martin
17-06-2005, 16:10
@BeS

Das einzige was noch fehlt ist ein expose-Event
Das war ne richtige Qual herauszufinden dass es nötig ist.
Ich habe auch hier was brachbares gefunden:
http://pronix.de/modules/newbb/viewtopic.php?viewmode=flat&topic_id=500&forum=3

ich hoffe die Antwort kommt nicht zu spät...
Nein. Grade rechtzeitig. Jetzt kann ich mein Projekt weiter voranbringen.
Danke für die Hilfe.


@nomad
Danke auch für dein Beispiel