Seite 1 von 2
Farbe von Widgets
Verfasst: Dienstag 8. Februar 2005, 21:13
von mawe
Hi!
Ich habe kurzfristig beschlossen, mich mal mit PyGtk zu beschäftigen.
Mein erstes Programm (Ähnlichkeiten mit Hello World sind durchaus beabsichtigt
):
Code: Alles auswählen
import pygtk
pygtk.require('2.0')
import gtk
class Test:
def __init__(self):
self.root = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.root.connect("destroy", lambda w: gtk.main_quit())
button = gtk.Button("Juhuu")
self.root.add(button)
button.show()
self.root.show()
gtk.main()
Test()
Beeindruckend, oder?
Jetzt fangen die Probleme aber an: Wie bringe ich Farbe ins Spiel? Entweder ist die Doku in diesem Punkt so schlecht, oder ich bin einfach zu blöd dazu.
Könnte mir bitte jemand zeigen, wie ich z.B. die Schrift rot und den Button-Hintergrund blau mache. Danke im Voraus.
Gruß, mawe
Verfasst: Dienstag 8. Februar 2005, 21:50
von Dookie
Hi mawe,
am Einfachsten ist wohl mit
Pangomarkup zu arbeiten:
Code: Alles auswählen
button = gtk.Button('<span foreground="red" background="blue">Juhuu</span>')
button.get_child().set_use_markup(True)
self.root.add(button)
mit button.get_child() bekommst du das Label des Buttons und bei dem Label muss noch use_markup aktiviert werden mit .set_use_markup(True).
Gruß
Dookie
Verfasst: Dienstag 8. Februar 2005, 21:53
von Dookie
noch eine Anmerkung, bei gtk überlässt man das Stylen der Buttons und anderer GUI-Elemente besser gtk bzw. dem vom User gewählten Theme.
Dookie
Verfasst: Dienstag 8. Februar 2005, 21:58
von mawe
Hi Dookie!
Danke für Deine Antwort, sieht wirklich einfach aus
Dookie hat geschrieben:
bei gtk überlässt man das Stylen der Buttons und anderer GUI-Elemente besser gtk bzw. dem vom User gewählten Theme.
Schon klar, ich will auch keine bunten Faschings-GUIs erstellen
Ich wollte nur eine gtk-Variante von meinem
Periodensystem programmieren. Da brauch ich die Farben.
Gruß, mawe
Verfasst: Mittwoch 9. Februar 2005, 07:21
von mawe
Hi!
Noch eine Frage:
Der Hintergrund ist jetzt nur unterhalb der Schrift gefärbt. Wie bekomme ich den gesamten Button farbig?
Gruß, mawe
Verfasst: Mittwoch 9. Februar 2005, 13:40
von Dookie
hmm, das ist nicht so einfach, ich würde da ein Drawingarea umwursteln zu einem Button, dann kannst du dort nach belieben Texte (auch mit Pango formatierte) Hintergründe (Farben und Bilder) plazieren. Vielleicht komm ich heute noch dazu da was zusammenzubasteln.
Gruß
Dookie
Verfasst: Mittwoch 9. Februar 2005, 22:13
von Dookie
Hi Mawe,
hier ein Beispiel mit einem abgeleiteten Drawing-Area als Button.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
Modul: Test
Description: Description
Version: 0.1
Copyright: 2004 by Fritz Cizmarov fritz@sol.at
Created: 08. Feb. 2005
Last modified: 09. Feb. 2005
License: Python license
Requirements: Python2.3
Exports: Classes and Functions to export
"""
import pygtk
pygtk.require('2.0')
import gtk
import pango
class ElementButton(gtk.DrawingArea):
""" Button fuer "Chemische Elemente Tafel" """
def __init__(self, text, foreground, background):
super(ElementButton, self).__init__()
# Farben reservieren
self.colormap = self.get_colormap()
self.fg = self.colormap.alloc_color(foreground)
self.bg = self.colormap.alloc_color(background)
self.light = self.colormap.alloc_color("#f8f8f8")
self.dark = self.colormap.alloc_color("#070707")
# Groesse nach Zeichensatz berechnen und setzen
self.layout = pango.Layout(self.create_pango_context())
self.layout.set_text("XXXX\nXXXX\nXXXX") # 3 Zeilen a 4 Zeichen
self.width, self.height = self.layout.get_pixel_size()
self.set_size_request(self.width, self.height)
# Pangolayout erstellen und Position berechnen
self.layout.set_markup(text)
t_width, t_height = self.layout.get_pixel_size()
self.l_x = (self.width - t_width) / 2
self.l_y = (self.height - t_height) / 2
# Event BUTTON_PRESS aktivieren
self.set_events(self.get_events() | gtk.gdk.BUTTON_PRESS_MASK)
self.connect("realize", self.on_realize)
self.connect("expose_event", self.on_expose_event)
def on_realize(self, event):
# Widget erstellt, graphical context holen
self.gc = self.window.new_gc()
return True
def on_expose_event(self, area, event):
# Widget neu zeichnen
self.gc.set_foreground(self.bg)
self.window.draw_rectangle(self.gc, True, 0, 0, self.width, self.height)
# 3D-Border
self.gc.set_foreground(self.light)
self.window.draw_line(self.gc, 0, 0, self.width, 0)
self.window.draw_line(self.gc, 0, 0, 0, self.height)
self.gc.set_foreground(self.dark)
self.window.draw_line(self.gc, self.width-1, 0,
self.width-1, self.height)
self.window.draw_line(self.gc, 0, self.height-1,
self.width, self.height-1)
# Text zeichnen
self.window.draw_layout(self.gc,
self.l_x, self.l_y,
self.layout, self.fg)
return True
class Test:
def __init__(self):
self.root = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.root.connect("destroy", lambda w: gtk.main_quit())
button_text = "<small>2</small>\n<b>He</b>\n<small>4.002</small>"
button = ElementButton(button_text, "#ff0000", "#0000ff")
button.connect("button_press_event", self.on_button_press_event)
self.root.add(button)
button.show()
self.root.show()
gtk.main()
def on_button_press_event(self, widget, event):
print widget.layout.get_text() # oder sonst eine Aktion
return True
Test()
in der Methode
.on_expose_event wird auch noch ein Pseudo3D-Rahmen um den Button gezeichnet dort kannst du auch sonsitge Zeichenoperationen hinzufügen oder sonstwas.
Gruß
Dookie
Verfasst: Mittwoch 9. Februar 2005, 22:38
von Leonidas
Ahem, Dookie, Helium (He) ist an zweiter Stelle im Periodensystem und etwa viermal so schwer.
Ansonsten: Nett, aber ein 3D Rahmen wäre schon cool.
Verfasst: Mittwoch 9. Februar 2005, 22:54
von Dookie
hab jetzt nen Border drumrum und Helium auch richtig beschriftet.
Dookie
Verfasst: Donnerstag 10. Februar 2005, 12:17
von Leonidas
Gefällt mir!
Stellt sich nur dir Frage, warum das nicht mit den normalen GTK+ Buttons geht.
Verfasst: Donnerstag 10. Februar 2005, 13:36
von Dookie
Bei Gnome/GTK kommts wohl eher auf eine einheitliche Darstellung der Bedienelemente an als auf volle Flexibilität.
Hier mal ein Screenshot wie so eine Elementetafel bei mir dann ausschaut:
und hier das Script:
Elements.py
Gruß
Dookie
Verfasst: Donnerstag 10. Februar 2005, 14:08
von Leonidas
Sieht großartig aus!
Das Problem ist, dass es bei mir unter Windows nicht so hübsch ist, wenn man das Fenster langzieht wird es immer schlimmer, da dann so Freiräume auftreten.
Verfasst: Donnerstag 10. Februar 2005, 14:18
von Dookie
Du sollst ja auch nicht das Fenster langziehen
In einer echten Anwendung käme die Tabelle ja in eine H- oder VBox und dort wird dann fill und expand auf False gesetzt, dann bleiben die Elemente schön zusammen.
Gruß
Dookie
Verfasst: Donnerstag 10. Februar 2005, 20:31
von mawe
Hi!
Dookie, ich kann nur sagen
WOW!!
Das sieht einfach genial aus!
Vielen Dank!
Gruß, mawe
Verfasst: Donnerstag 10. Februar 2005, 22:51
von Dookie
Hab gerade ein Update hochgeladen, mit etwas bereinigtem Code und noch zwei Labels, die über mehrere Tabellenzellen gehen.
Gruß
Dookie
Verfasst: Freitag 11. Februar 2005, 09:30
von mawe
Hi!
Geschafft! Nach stundenlagem Fluchen und Haareraufen (meine Frisur sieht jetzt so ähnlich aus wie die von meinem Avatar
), weiß ich endlich wie man den Hintergrund eines Buttons einfärbt:
Code: Alles auswählen
import pygtk
pygtk.require('2.0')
import gtk
class ColoredButton:
def __init__(self):
self.root = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.root.connect("destroy", lambda w: gtk.main_quit())
self.root.set_border_width(10)
button = gtk.Button("Color! Juhuu!!!")
style = button.get_style()
color = button.get_colormap()
bg = color.alloc_color("red")
style.bg[gtk.STATE_NORMAL] = bg
button.set_style(style)
self.root.add(button)
button.show()
self.root.show()
gtk.main()
ColoredButton()
Keine Ahnung ob's auch besser/einfacher geht. Ich bin jetzt mal zufrieden
Gruß, mawe
Verfasst: Freitag 11. Februar 2005, 12:08
von Leonidas
mawe hat geschrieben:Keine Ahnung ob's auch besser/einfacher geht. Ich bin jetzt mal zufrieden
Wäre ich auch. Fast:
Code: Alles auswählen
style.bg[gtk.STATE_PRELIGHT] = bg
style.bg[gtk.STATE_ACTIVE] = bg
Würde ich noch einsetzen, damit der Button auch beim Hover und Eingedrückt Rot bleibt.
Cooler Code, nutzt tatsächlich gtk.Buttons
Eindeutig ein Kandidat für den Snippetsindex!
Verfasst: Freitag 11. Februar 2005, 16:43
von Dookie
Hi nochmal,
hier Mawes Colorbutton in einer von gtk.Button abgeleiteten Klasse:
Code: Alles auswählen
class ColoredButton(gtk.Button):
def __init__(self, label=None, stock=None, use_underline=True,
fg="black", bg="gray90",
states=(gtk.STATE_NORMAL,
gtk.STATE_PRELIGHT,
gtk.STATE_ACTIVE)):
super(ColoredButton, self).__init__(label, stock, use_underline)
st = self.get_style()
cm = self.get_colormap()
fgc = cm.alloc_color(fg)
bgc = cm.alloc_color(bg)
for state in states:
st.fg[state] = fgc
st.bg[state] = bgc
self.set_style(st)
self.child.set_use_markup(True)
Gruß
Dookie
Verfasst: Freitag 11. Februar 2005, 17:16
von mawe
Hi!
Bevor ich mir noch die letzten Haare ausreisse, frag ich lieber gleich
Hier mal der Code:
Code: Alles auswählen
import pygtk
pygtk.require('2.0')
import gtk
class ColoredButton(gtk.Button):
def __init__(self, label=None, stock=None, use_underline=True,
states=(gtk.STATE_NORMAL, gtk.STATE_PRELIGHT, gtk.STATE_ACTIVE)):
super(ColoredButton, self).__init__(label, stock, use_underline)
self.states = states
self.label = label
self.st = self.get_style()
self.cm = self.get_colormap()
self.connect("clicked", self.click)
def click(self,event):
print self.label
def set_bg_color(self, bg):
bgc = self.cm.alloc_color(bg)
for state in self.states:
self.st.bg[state] = bgc
self.set_style(self.st)
self.child.set_use_markup(True)
elements = ["H","C"]
root = gtk.Window(gtk.WINDOW_TOPLEVEL)
root.connect("destroy", lambda w: gtk.main_quit())
table = gtk.Table(1,2,gtk.TRUE)
root.add(table)
c,r = 0,0
for atom in elements:
button = ColoredButton(label=atom)
if atom == "H":
button.set_bg_color("red")
else:
button.set_bg_color("blue")
table.attach(button,c,c+1,r,r+1)
button.show()
c+=1
table.show()
root.show()
gtk.main()
Wie man sehen kann, will ich den H-Button rot, und den He-Button blau hinterlegen. Beide sind aber blau. Was mach ich da falsch? Hilfe!
Noch etwas zum Einfärben: Das Ändern der fg-Farbe bewirkt anscheinend etwas anderes als ich erwartet hatte (hab gedacht das ist die Textfarbe). Muss ich für die Textfarbe wieder auf pango zurückgreifen? Und was ist überhaupt dieses fg?
Gruß, mawe
Verfasst: Freitag 11. Februar 2005, 19:06
von Dookie
Der Style gilt wohl für alle Buttons, also am besten mit einer Kopie arbeiten.
In der __init__ vom ColoredButton:
Dann gehts.
Die Fordergrundfarbe musst du im Label (button.child) ändern.
Code: Alles auswählen
def set_fg_color(self, fg):
fgc = self.child.get_colormap().alloc_color(fg)
for state in self.states:
self.child.modify_fg(state, fgc)
Gruß
Dookie