Farbe von Widgets

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Ich habe kurzfristig beschlossen, mich mal mit PyGtk zu beschäftigen.
Mein erstes Programm (Ähnlichkeiten mit Hello World sind durchaus beabsichtigt :wink:):

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? :D
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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
[code]#!/usr/bin/env python
import this[/code]
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

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 :D
Ich wollte nur eine gtk-Variante von meinem Periodensystem programmieren. Da brauch ich die Farben.

Gruß, mawe
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Noch eine Frage:
Der Hintergrund ist jetzt nur unterhalb der Schrift gefärbt. Wie bekomme ich den gesamten Button farbig?

Gruß, mawe
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
Zuletzt geändert von Dookie am Mittwoch 9. Februar 2005, 22:53, insgesamt 2-mal geändert.
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

hab jetzt nen Border drumrum und Helium auch richtig beschriftet.

Dookie
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Gefällt mir!
Stellt sich nur dir Frage, warum das nicht mit den normalen GTK+ Buttons geht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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:
Bild
und hier das Script: Elements.py


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Du sollst ja auch nicht das Fenster langziehen :roll:

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
[code]#!/usr/bin/env python
import this[/code]
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Dookie, ich kann nur sagen WOW!! :shock: Das sieht einfach genial aus!
Vielen Dank!

Gruß, mawe
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hab gerade ein Update hochgeladen, mit etwas bereinigtem Code und noch zwei Labels, die über mehrere Tabellenzellen gehen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Geschafft! Nach stundenlagem Fluchen und Haareraufen (meine Frisur sieht jetzt so ähnlich aus wie die von meinem Avatar :D), 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 :wink:

Gruß, mawe
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mawe hat geschrieben:Keine Ahnung ob's auch besser/einfacher geht. Ich bin jetzt mal zufrieden :wink:
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!
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
[code]#!/usr/bin/env python
import this[/code]
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Der Style gilt wohl für alle Buttons, also am besten mit einer Kopie arbeiten.
In der __init__ vom ColoredButton:

Code: Alles auswählen

        self.st = self.get_style().copy()
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
[code]#!/usr/bin/env python
import this[/code]
Antworten