Forum: PC-Programmierung eigene Button in GTK+ Cairo erstellen


von KidMoritz (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

die Vielfalt der Widgets aus dem "GTK-Package" ist begrenzt.
Kreative, farbenfrohe und kurvenreiche Widgets, welche das "Window" 
schmuecken sind damit nicht moeglich.

Mit Benutzung der GrafikBibliothek Cairo laesst sich ein Fenster schon 
super grafisch aufwerten.

Ich moechte nun ein eigenen Button erstellen.
Die Konstruktion des Buttons (bzw. des Bildes) ist kein Problem.
Der Button soll eine runde Form erhalten.

Das erstellte Bild des Button's soll nicht auf ein GTK-Standard 
Button-Widget gelegt werden, da dieses wieder eine eckige Form hat. Auch 
wenn der Button rund dargestellt werden kann.
Der eigens erstellte Button soll ein eigenes Widget sein.

1. Frage: Welche Moeglichkeiten gibt es dies zu realisieren?
          - kann der Button(Bild) als eigens Object(Widget) angelgt 
werden
          - oder kann der runde Bereich vom Mauszeiger erfasst werden
            und mit diesem Bereich interagieren

2. Frage: Ist es besser den eigens erstellten Button als Bild zu laden
          oder waehrend der Laufzeit des Programmes zu erstellen


Kann da jemand weiterhelfen?

PS: im Anhang ein erstelltes "face" (nicht der Button ;o) mit Cairo.
    Hat jemand ein Erklaerung fuer die Streifen auf der rechten
    Seite?

Danke im Voraus.

von Lukas K. (carrotindustries)


Lesenswert?

Ich hatte mich mal mit ähnlichem beschäftigt und bin zu dem Schluss 
gekommen, dass cairo doch besser Backend für höher entwickelte 
Graphikbibliotheken bleiben sollte; das Zeichenmodell ist doch ein wenig 
gewöhnungsbedürftig. Goocanvas hingegen ist relativ einfach, um nicht zu 
sagen intuitiv, zu benutzen.

von KidMoritz (Gast)


Lesenswert?

Danke fuer den Hinweis.
Warum umstaendlich, wenn es auch einfacher geht. ;)
Das erste Example von goocanvas erfuellt somit schon einmal meine 
Anforderungen bzgl. des Buttons + press event.

ist goocanvas ein standard?
wird es heaufig genutzt?
wird es weiterentwickelt? letzte Aktualisierung

Ja die direkte Nutzung von Cairo ist etwas aufwendiger.
Der Kontext von Cairo ist, meiner Meinung nach, dennoch leicht zu 
verstehen.

Ich werde mir goocanvas das mal genauer anschauen und probieren.

PS: scheinbar ein Fehler im Reference Manual von GooCanvas
[[http://library.gnome.org/devel/goocanvas/unstable/GooCanvas.html]]

Zeile: 49 -  GOO_CANVAS_ANCHOR_CENTER geht nicht
       dafuer GTK_ANCHOR_CENTER eingesetzt -> geht

Danke.

von Lukas K. (carrotindustries)


Lesenswert?

KidMoritz schrieb:
> ist goocanvas ein standard?
Nicht wirklich
> wird es heaufig genutzt?
http://live.gnome.org/GooCanvas
> wird es weiterentwickelt? letzte Aktualisierung
http://ftp.gnome.org/pub/GNOME/sources/goocanvas/

von KidMoritz (Gast)


Lesenswert?

Hatte mich schon etwas umgeschaut.
Letzte Aktualisierung ist ja auch schon'ne Weile her.
Wenn's kein Standard ist lohnt es sich nicht viel Zeit zu investieren.
Ein wenig spielen ist erlaubt.

Dennoch vielen Dank.

Was ist denn Standard?
Was wird denn da so genutzt?

von Lukas K. (carrotindustries)


Lesenswert?

Cairo ist Standard, jedoch konnte ich mich damit nie anfreunden; will 
aber nichts heißen ;)

von Simon B. (nomis)


Lesenswert?

KidMoritz schrieb:
> PS: im Anhang ein erstelltes "face" (nicht der Button ;o) mit Cairo.
>     Hat jemand ein Erklaerung fuer die Streifen auf der rechten
>     Seite?

Ohne Sourcecode kann ich hier nur spekulieren:

Zeichnest Du den äußeren Rahmen mit cairo_arc? Geht der dann von 0 bis 
2*M_PI? Von 0 bis 6.2831 wäre nicht gut genug...

Falls Du für den Rahmen einen Pfad mit cairo_stroke() zeichnest, ist 
dieser Pfad dann wirklich geschlossen?

Viele Grüße,
        Simon

von update (Gast)


Lesenswert?

KidMoritz schrieb:
> Letzte Aktualisierung ist ja auch schon'ne Weile her.

stimmt, der 3.11.2010 ist schon ein paar Stunden alt ;)

von KidMoritz (Gast)


Lesenswert?

update schrieb
>stimmt, der 3.11.2010 ist schon ein paar Stunden alt ;)

Ist'ne schnelllebige Welt ;)
Spass beiseite. Hatte da bei den Windows Binaries geschaut.


Simon schrieb

>Zeichnest Du den äußeren Rahmen mit cairo_arc? Geht der dann von 0 bis
>2*M_PI? Von 0 bis 6.2831 wäre nicht gut genug...

Ja die Ringe sind mit cairo_arc und M_PI = 3.14 gezeichnet worden.
Das reicht nicht, sehe ich gerade.
Mit: M_PI = 3.1415926535897932384626433832795 sieht die Sache perfekt 
aus.
Danke fuer den Hinweis. ;o)
Ist M_PI in einer Lib oder einem Header schon niedergeschrieben?
Oder muss diese Groesse immer eigens initialisiert werden?

>Falls Du für den Rahmen einen Pfad mit cairo_stroke() zeichnest, ist
>dieser Pfad dann wirklich geschlossen?

cairo_stroke(cr) wird verwendet.
Muss der Pfad mit
1
cairo_close_path(cr);
geschlossen werden?
Wann muss ein Pfad immer geschlossen werden? Das habe ich noch nicht so 
richtig erkannt.
Am Schluss der Funktion wird diese mit
1
cairo_destroy(cr);
 abgeschlossen.


Frage: Sollten die
1
cairo_set_line_width(cr, _set_line_width);
 immer ungerade Werte haben damit sie symmetrisch auf dem Radius 
gezeichnet werden?

Danke im Voraus.

von Simon B. (nomis)


Angehängte Dateien:

Lesenswert?

KidMoritz schrieb:
> Ja die Ringe sind mit cairo_arc und M_PI = 3.14 gezeichnet worden.
> Das reicht nicht, sehe ich gerade.
> Mit: M_PI = 3.1415926535897932384626433832795 sieht die Sache perfekt
> aus.
> Danke fuer den Hinweis. ;o)
> Ist M_PI in einer Lib oder einem Header schon niedergeschrieben?
> Oder muss diese Groesse immer eigens initialisiert werden?

Du findest M_PI in <math.h>

>>Falls Du für den Rahmen einen Pfad mit cairo_stroke() zeichnest, ist
>>dieser Pfad dann wirklich geschlossen?
>
> cairo_stroke(cr) wird verwendet.
> Muss der Pfad mit cairo_close_path(cr); geschlossen werden?
> Wann muss ein Pfad immer geschlossen werden? Das habe ich noch nicht so
> richtig erkannt.

Das wird insbesonders dann wichtig, wenn Linien nicht gerade 
aufeinanderstoßen. Ich habe mal ein Bild angehängt, das den Unterschied 
verdeutlicht: links ist der Pfad an der oberen Spitze nicht geschlossen, 
d.h. es werden zwei Linienenden (oben CAIRO_LINE_CAP_BUTT, unten 
CAIRO_LINE_CAP_SQUARE) hingemalt. Rechts ist der Pfad geschlossen, d.h. 
statt Linienenden werden Linienknicke hingemalt (oben 
CAIRO_LINE_JOIN_MITER, unten CAIRO_LINE_JOIN_ROUND).

Wenn - wie bei deinem Kreis - zwei Linien sich genau entgegenkommen, ist 
dieser Unterschied natürlich nicht so deutlich, wie in meinem Beispiel. 
Man sollte IMHO aber trotzdem darauf achten, damit man genau das 
bekommt, was man will.

> Frage: Sollten die cairo_set_line_width(cr, _set_line_width);
> immer ungerade Werte haben damit sie symmetrisch auf dem Radius
> gezeichnet werden?

Ich bin nicht ganz sicher, ob ich das Problem verstehe. Ich vermute, 
dass Du da ein anderes Koordinatensystem annimmst, als Cairo tatsächlich 
verwendet.

Sofern Du keine Koordinatentransformation verwendest - also direkt in 
"echten Pixeln" malst, liegen die ganzzahligen Koordinaten jeweils an 
den Pixelecken, und nicht in der Pixelmitte. Viele Leute sind ein 
bischen verwirrt, wenn Sie eine Linie von (10,10) nach (10,20) mit der 
Linienstärke 1.0 malen und dann eine Linie sehen, die zwei Pixel breit 
aussieht. Hintergrund ist natürlich, dass eine ein-pixel-breite Linie 
entlang der Pixelgrenze nach links und rechts je ein halbes Pixel 
überdeckt, entsprechend wird das von Cairo gerendert.

Würde man die Linie von (10.5,10) nach (10.5,20) malen, würde es wie 
erwartet aussehen.

Möglicherweise ist das bei Dir ein ähnliches Missverständnis?

Viele Grüße,
        Simon

von KidMoritz (Gast)


Angehängte Dateien:

Lesenswert?

Ah! So ist das mit dem Pfad schliessen gedacht.
Jetzt verstehe ich.


>Ich bin nicht ganz sicher, ob ich das Problem verstehe. Ich vermute,
>dass Du da ein anderes Koordinatensystem annimmst, als Cairo tatsächlich
>verwendet.

>Hintergrund ist natürlich, dass eine ein-pixel-breite Linie
>entlang der Pixelgrenze nach links und rechts je ein halbes Pixel
>überdeckt, entsprechend wird das von Cairo gerendert.

>Möglicherweise ist das bei Dir ein ähnliches Missverständnis?

Aha! Ja so hatte ich das gemeint.

>Würde man die Linie von (10.5,10) nach (10.5,20) malen, würde es wie
>erwartet aussehen.

Ich habe das auch gleich mal probiert(Anhang) und den Unterschied 
erkannt.
Beide Linien haben die Staerke 1.
In diesem Fall wuerde jetzt eine - Koordinatentransformation - 
vorliegen.
Ist das Richtig?


Noch 2 Fragen haette ich:
1. Ueber meine Anzeige bewegt sich ein Zeiger.
   Das geht auch so weit.
   Lasse ich die Anzeige nicht erstellen und der Zeiger dreht alleine
   seine Runden laeuft der Zeiger fluessig. Mit Anzeige ruckt er sehr.
   Ich nutze aus einem Bspl. den TimeHandler +
   gtk_widget_queue_draw(widget);
   Mein Rechner auf dem ich hier schhreibe/programmiere hat 700Mhz und 
8MB
   Grafik.
   Ist so eine Animation schon zu viel verlangt?
   Auf meinem "grossen" Rechner gehts besser.
   Oder sollte ich die Anzeige als Bild(png,jpg) aufsetzen und den 
Zeiger
   ueber das Bild drehen lassen?
2. laesst sich(wie oben schon erfragt) ein button press event auf eine
   beliebig geformte Grafik erstellen?

Jede Antwort bring neue Fragen ;)

Erstmals vielen Dank fuer deine Muehen mit den Dreiecken.

:)

von Simon B. (nomis)


Lesenswert?

KidMoritz schrieb:
> Ich habe das auch gleich mal probiert(Anhang) und den Unterschied
> erkannt.
> Beide Linien haben die Staerke 1.
> In diesem Fall wuerde jetzt eine - Koordinatentransformation -
> vorliegen.
> Ist das Richtig?

Nein, mit "Koordinatentransformation" meine ich z.B. einen Aufruf von 
cairo_scale, cairo_translate oder cairo_rotate. Das heißt, das 
Koordinatensystem wird transformiert und die folgenden Zeichenaufrufe 
beziehen sich nicht mehr auf das originale Pixelraster als 
Koordinatensystem. Es hat also nicht direkt etwas mit der Linienstärke 
zu tun.

Der Screenshot von Dir ist absolut korrekt: die obere Linie wirkt zwei 
Pixel breit, ist aber etwas transparent, da die Pixel jeweils nicht 
vollständing überdeckt werden.

> Noch 2 Fragen haette ich:
> 1. Ueber meine Anzeige bewegt sich ein Zeiger.
>    Das geht auch so weit.
>    Lasse ich die Anzeige nicht erstellen und der Zeiger dreht alleine
>    seine Runden laeuft der Zeiger fluessig. Mit Anzeige ruckt er sehr.

Also, ohne Quellcode kann ich dazu nicht viel sagen. Es ist allerdings 
wahr, dass Cairo keine Geschwindigkeitswunder vollbringt - die 
Entwickler legen mehr Wert auf Korrektheit als auf Geschwindigkeit.

>    Ist so eine Animation schon zu viel verlangt?
>    Auf meinem "grossen" Rechner gehts besser.
>    Oder sollte ich die Anzeige als Bild(png,jpg) aufsetzen und den
>    Zeiger ueber das Bild drehen lassen?

Im Prinzip wäre das eine Möglichkeit, um die Geschwindigkeit zu 
verbessern. Man kann allerdings auch reines Cairo verwenden und den 
Hintergrund in ein pattern rendern, dass man dann wiederverwendet.

Aber erstmal würde ich gucken, welches Element die Geschwindigkeit am 
meisten runterzieht, ich würde ja spontan auf die vielen Farbverläufe 
tippen, aber - wie gesagt - das ist ohne Sourcecode reine Spekulation.

> 2. laesst sich(wie oben schon erfragt) ein button press event auf eine
>    beliebig geformte Grafik erstellen?

Vermutlich geht das irgendwie, ich habe da aber zuwenig Erfahrung um dir 
da einen echten Tip geben zu können.

Viele Grüße,
        Simon

von KidMoritz (Gast)


Lesenswert?

Vielleicht kann die Administrative das Bild umbenennen, damit es zu 
keinr Verwirrung für Interessierte kommt.


>Nein, mit "Koordinatentransformation" meine ich z.B. einen Aufruf von
>cairo_scale, cairo_translate oder cairo_rotate. Das heißt, das
>Koordinatensystem wird transformiert und die folgenden Zeichenaufrufe
>beziehen sich nicht mehr auf das originale Pixelraster als
>Koordinatensystem. Es hat also nicht direkt etwas mit der Linienstärke
>zu tun.

Sorry, hätte ich selber erkennen müssen. Stimmt.

> 2. laesst sich(wie oben schon erfragt) ein button press event auf eine
>    beliebig geformte Grafik erstellen?

>Vermutlich geht das irgendwie, ich habe da aber zuwenig Erfahrung um dir
>da einen echten Tip geben zu können.

Ich habe es erst einmal mit einer Event Box realisiert.
Ansonsten muss man, wie ich es verstanden habe, ein eigenes Widget 
erstellen.
Aber bis dahin ist noch ein weiter Weg.

Den Code stelle ich demnächst mal noch ein.

Danke und Gruß

von KidMoritz (Gast)


Lesenswert?

Der letzte Eintrag ist ja nun doch schon ne Weile her.

>Im Prinzip wäre das eine Möglichkeit, um die Geschwindigkeit zu
>verbessern. Man kann allerdings auch reines Cairo verwenden und den
>Hintergrund in ein pattern rendern, dass man dann wiederverwendet.

>Aber erstmal würde ich gucken, welches Element die Geschwindigkeit am
>meisten runterzieht, ich würde ja spontan auf die vielen Farbverläufe
>tippen, aber - wie gesagt - das ist ohne Sourcecode reine Spekulation.

Ich habe nun den ganzen Hintergrund (Grafik, Bild, Gauge) in InkScape 
angefertigt und der App als .png übergeben.
Der Zeiger wird mit Cairo erzeugt und animiert.
Läuft alles sehr flüssig.

Die ganze App funktioniert tadellos. Bis auf eine kleine Sache. :(
Die App besteht aus mehreren Teilbildern.
Alle TeilBilder werden perfekt zur App zusammengefügt.
Die App ist mit einem Button ausgestattet, welcher in einer EventBox 
liegt.
Das funktioniert problemlos.
Alle lib____.dll wurden in den "App-Ordner" eingefügt.
Nur wir das ButtonBild, welches in der EventBox liegt nicht angezeigt, 
wenn die App auf einem anderen Recher läuft, als dort wo die App 
geschrieben wurde.
Das Buttonbild liegt mit im selben "App-Ordner" wie die anderen 
Teilbilder.


Hat da jemand´ne Idee?

Im Voraus vielen Dank.

von MikroMakro (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal ein Stueck Code aus meiner App.
Wobei ich denke, dass es nicht am Code liegen wird.

Danke und Gruß

von KidMoritz (Gast)


Lesenswert?

Bin in meiner Recherche ein Stueck weitergekommen.

Ich hatte bei der Entwicklung irgendwann das DosFenster abgeschalten.
Das habe ich wieder eingeschalten.
Das stand da nun die Warnung:

GdkPixbuf-Warning **:cannot open pixbuf loader module file + Pfad zum 
Projectordner  + etc/gtk-2.0/gdk-pixbuf.loaders

Ich habe den Ordner "etc" in meinen ProjectOrdner kopiert.
App gestartet.
Die Warnung "GdkPixbuf-Warning...." blieb aus.
Das Bild wurde aber dennoch nicht geladen.

Ich habe dazu noch etwas gegoogelt. Aber nur Bruchstuecke gefunden, 
welche ich mir nicht zusammenfuegen kann.

Hat da jemand noch ein Hinweis?

von KidMoritz (Gast)


Lesenswert?

So nun scheint es zu funktionieren.
Nachdem ich das Project neu erstellt hatte blieb das Problem weiterhin 
bestehen.
Nachdem ich das Project mit einem aktuellerem GTK-Package compilierte 
"schwoll" die .exe von 352kB auf 438kB an.
Nun läuft die App auf beiden Rechnern.

Das vorhergehende GTK Package war das 2.16.
Das aktuell neu installierte das 2.22.

Aber ich kann mir auch nicht vorstellen, dass es an der Version des 
Packages lag.
Das sind ja Standard-Module mit denen ich arbeite.
Evtl wurde mal etwas "verinstalliert" :confused:

Danke &Gruß

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.