Wie setzt man das Window Icon korrekt?

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Wie setzt man bei GTK3 das Window-Icon korrekt, so dass es skaliert?

Code: Alles auswählen

self.window.set_icon_from_file('icon.png')
Weist ein Icon zu das nicht skaliert. Wenn ich ein SVG zuweise motzt er mit 'icon too large'.
Wenn ich mehrere zuweise, skaliert das Icon trotzdem nicht.

Code: Alles auswählen

icon_list = []
for resolution in ['16','32','48','64','128']:
	self.window.set_icon_from_file('icon' + resolution + '.png')
	icon_list.append(self.window.get_icon())
self.window.set_icon_list(icon_list)
Wie macht man das richtig?
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

set_icon_list() geht eben nicht. Zumindest nicht so wie ich es gemacht habe (siehe Codeblock weiter oben). Das Icon bleibt immer gleich (im Launcher bzw. bei Alt+Tab). Sieht dort jemand einen Fehler?
lunar

@rhersel: So ist diese Methode auch nicht gedacht. Du musst die Symbole manuell über GdkPixbuf laden und anschließend über diese Methode dem Fenster zuweisen.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Aber wie bekomme ich das Image-File in den PixBuf?

GdkPixbuf kennt ja nur zwei Methoden die beide nicht aus einem File lesen: http://developer.gnome.org/gdk3/stable/ ... xbufs.html
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Wenn man bei Google nach „pixbuf from file“ sucht, findet man beim ersten Treffer den Link zu der Erklärung.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

In Gdk3 gibt es kein gdk_new_from_pixbuf()
lunar

@rhersel: Diese Funktion ist auch nicht Teil von GDK, sondern von Gdk-Puxbuf. Gdk selbst kümmert sich nur um die Details der Fensterverwaltung.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Dank, so geht es: (nur die relevanten Codezeilen)

Code: Alles auswählen

from gi.repository import Gtk, Gdk, GdkPixbuf

icon_16 = GdkPixbuf.Pixbuf.new_from_file('icon16.png')
icon_32 = GdkPixbuf.Pixbuf.new_from_file('icon32.png')
icon_48 = GdkPixbuf.Pixbuf.new_from_file('icon48.png')
icon_64 = GdkPixbuf.Pixbuf.new_from_file('icon64.png')
icon_128 = GdkPixbuf.Pixbuf.new_from_file('icon128.png')
self.window.set_icon_list([icon_16, icon_32, icon_48, icon_64, icon_128])
Zuletzt geändert von Anonymous am Donnerstag 8. März 2012, 16:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

Diese ständige Wiederholung der Pixelgrössen könnte man durch eine „list comprehension” los werden (ungetestet):

Code: Alles auswählen

self.window.set_icon_list(
    [
        GdkPixbuf.Pixbuf.new_from_file('icon%d.png' % x)
        for x in [16, 32, 48, 64, 128]
    ]
)
Edit: Den von nomnom angeprochenen Fehler verbessert.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Bei BlackJacks Variante fehlt natürlich noch das „% x“ hinter dem Stringliteral. Die eckigen Klammern um die Zahlen hätte man übrigens auch weglassen können. (Dann würde über ein Tupel statt über eine Liste iteriert.)
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Sehr elegant; hab's jetzt so gemacht:

Code: Alles auswählen

self.window.set_icon_list(
	[GdkPixbuf.Pixbuf.new_from_file('nota%d.png' % resolution)
	for resolution in 16, 32, 48, 64, 128])
Aber leider funktioniert die Sache immer noch nicht. Python-seitig ist zwar alles ok aber die verschiedenen Auflösungen werden nicht verwendet. Wenn ich im Ubuntu 11.10 Unity 3D Launcher die Icongrösse auf 'ganz gross' stelle ist das Icon ziemlich verwaschen. Das Gleiche beim App-Switcher (Alt+Tab) obwohl das 128er Icon die richtige Auflösung für die Alt+Tab Grösse bieten würde.

Schade, dass man nicht einfach ein SVG angeben kann; damit wäre der Unsinn mit den 5 Icon-Grössen überflüssig.

Kennt jemand ein Python Programm das in den normalen Repositories ist. Dann schaue ich mal im Sourcecode nach wie andere Leute das machen.
lunar

@rhersel: Bist Du sicher, dass das der empfohlene Weg ist, einem Gtk-Fenster ein Symbol zu verleihen? Ich kenne mich mit Gtk nicht aus, doch bei Qt kann man dieses Symbol automatisch in der passenden Größe aus dem aktuellen Symbolthema laden.

Es ist auch kein Unsinn, verschiedene Symbole für verschiedene Größen anzugeben. Jede Desktop-Umgebung verfährt so, vor allem bei kleinen Symbolen, da diese in der Regel nachbearbeitet werden. Daher findest Du unter "/usr/share/icons" auch eine Menge Symbole als Pixelgrafik.

Probiere erst einmal auch, ob die Symbole in anderen Desktopumgebungen funktionieren. Unity ist in dieser Hinsicht etwas... merkwürdig.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Ich meine, dass das nichts mit dem Desktop zu tun haben kann. Unter Unity (und in jeder anderen Distro bzw. Desktop) hat jede Anwendung eigene Applikations-Icons in diversen Auflösungen und legt diese in "usr/share/icons" ab. Wo die Icons gespeichert sind, sollte doch egal sein. Die Anwendung lädt die Icons und gut ist. Auch bei Qt musst du deiner Anwendung doch ein individuelles App-Icon verpassen können.

Ein SVG zu verwenden fände ich halt wesentlich eleganter weil man sich dadurch die vielen Dateien in verschiedenen Auflösung ersparen würde. Das ist ja genau der Sinn von Scalable Vector Graphics.

Ich werde deinen Ratschlag trotzdem befolgen und mein Programm mal unter dem Gnome-Shell Desktop laufen lassen.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Wie zu erwarten war, skalieren die Icons auch unter Gnome-Shell nicht.
Da aber alle anderen Anwendungen das können, dürfte es nicht zu schwierig sein herauszufinden wie man es richtig macht. Ich werde mal bei Ubuntuusers und AskUbuntu nachfragen und auch versuchen den Sourcecode einer anderen Anwendung zu untersuchen.
lunar

@rhersel: In Qt gibt man normalerweise einfach nur den Namen des Symbols an (siehe "QIcon.fromTheme()"), und überlässt Qt den Rest, sprich suchen, laden und skalieren. Gdk ist dafür gar nicht zuständig, denn wie gesagt kümmert sich Gdk nur um die direkte Fensterverwaltung. In Gtk gibt es dafür http://developer.gnome.org/gtk3/stable/ ... kIconTheme, und ich bin mir ziemlich sicher, dass das die Klasse ist, die Du eigentlich suchst. GdkPixbuf ist – wie der Name schon sagt – einfach nur ein Haufen Pixel, kein Symbol mit verschiedenen Größen und erst recht keine Vektorgrafik. SVG ist so komplex, dass es dafür mit rsvg eine eigene Bibliothek gibt. GtkIconTheme implementiert dagegen den Standard für Symbole und Symbolthemen unter Linux, so dass Unity und Deine Anwendung zumindest schon mal an der selben Stelle nach einem Symbol für Dein Programm suchen.

Allerdings wird das wohl nicht reichen. Ich habe bisher nicht daran gedacht, doch ich glaube, dass Gnome Shell und Unity ihre Symbole aus der Desktop-Datei der Anwendung zu laden versuchen, und das Fenstersymbol nur als letzten Ausweg verwenden. Damit Deine Anwendung sich in Unity integriert, musst Du also eine Desktop-Datei für Deine Anwendung installieren.

Verschiedene Pixelgrafiken für verschiedene Auflösungen kann man sich im Übrigen nicht sparen, wenn hochwertige Symbole gewünscht sind, da man die unterschiedlichen Anforderungen an Symbole verschiedener Größen nicht mit einer Grafik abdecken kann. Große Symbole müssen detailreich sein, um nicht langweilig zu sein, kleine Symbole dagegen dürfen nicht viele Details haben, da man bei geringen Symbolgrößen die wesentliche optische Eigenschaft des Symbols nicht durch Details verdecken darf. Detailarme Vektorgrafiken wirken in hohen Auflösungen langweilig, detailreiche Vektorgrafiken sind in niedrigen Auflösungen verwaschen, und überladen. Beim Entwurf eines Symbols geht man mithin von der detailreichen, großen Symbolgrafik aus, und erzeugt daraus manuell (und nicht automatisch mit einem SVG-Renderer) kleinere Pixelgrafiken, wobei man manuell unerwünschte Details entfernt. Deswegen liegen in "/usr/share/icons/" viele Pixelgrafiken, die allesamt subtile Unterschiede zur entsprechenden skalierbaren Vektorgrafik in "/usr/share/icons/*/scalable/" aufweisen.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Danke für die einleuchtende Erklärung, sowohl bezüglich IconTheme als auch zu SVG.
Jetzt brauche ich nur noch ein Python Code Beispiel wie man es tatsächlich macht; ich meine das IconTheme dem Window zuweisen.

...

In der Zwischenzeit habe ich mir die ganze Spezifikation für IconThemes durchgelesen. Das ist mir zu aufwändig; ich beschränke mich auf ein 48er Icon und weise es einfach mit window.set_icon_new_from_file() zu; fertig, aus.
Zuletzt geändert von rhersel am Freitag 9. März 2012, 10:49, insgesamt 1-mal geändert.
lunar

@rhersel: Falls Du dieses Beispiel jetzt von mir erwartest, so muss ich Dich enttäuschen. Ich kenne Gtk zu wenig, als dass ich Dir ein Beispiel aus dem Ärmel schütteln könnte. Was ich bisher getan habe, war im Wesentlichen lediglich, Dir die Dokumentation vorzulesen.
rhersel
User
Beiträge: 105
Registriert: Mittwoch 3. Dezember 2008, 11:29

Ist völlig ok. Vielen Dank für die Hilfe.

In der Zwischenzeit habe ich mir die ganze Spezifikation für IconThemes durchgelesen. Das ist mir zu aufwändig; ich beschränke mich auf ein 48er Icon und weise es einfach mit window.set_icon_new_from_file() zu; fertig, aus.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo, irgend eine Lösung inzwischen gefunden? Ich versuche auch schon seit einem halben Jahr bald eine Lösung zu finden für das Problem, dass meine Programm Icons immer nur in schlechter Qualität dargestellt werden, selbst wenn ich eine SVG Bilddatei nehme.
Antworten