Textfarbe und Schriftgröße

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Hi, bin ziemlich neu hier und hab einige Probleme.
Hab ein kleines Programm mit einer GUI in TK geschrieben, und das läuft soweit ganz gut. Nur MUSS ich das genze jetzt in gtk abliefern und versteh nur Bahnhof. :K
Mein Englisch ist nicht das beste, und mit rumprobieren komm ich nciht mehr weiter. Aber erstmal eins nach dem anderen.
Hier mein Testcode:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf8 -*-
import pygtk
pygtk.require('2.0')
import gtk
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Titel")
window.resize(800,600)
layout = gtk.Layout(None, None)
wellcome = gtk.Label("Testüberschrift")
layout.put(wellcome, 200, 0)
window.add(layout)
window.show_all()
So hab ichs geschafft ein Fenster in 800x600 herzukriegen und Text reinzuschreiben. (Super, gell!) :wink:
Wenn ichs total falsch mache wär ich über eine Berichtigung froh!

Wie bekomm ich nun den Text in ne andere Schriftgröße und Farbe? google hat mir diesmal nicht sonderlich geholfen.

Gruß Tom
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

zu PyGTK gab es eigentlich immer eine ganz gute Dokumentation unter pygtk.org. Zur Zeit erscheint dort leider nur eine temporäre(?) Drupal-Seite, sehr ärgerlich. Mit Google-Cache lassen sich die Seiten dennoch abrufen.

Du suchst die "Pango Markup Language" - damit lassen sich beispielsweise in gtk.Labels Text formatieren:

Code: Alles auswählen

label = gtk.Label()
label.set_markup("<span foreground='#ff0000'>Hallo Welt</span>")
Was die Verbesserungsvorschläge angeht: Du nutzt hier gtk.Layout() als Container für deine Widgets. In einem gtk.Layout() werden die Widgets mittels Koordinaten angeordnet. Das ist aber eigentlich die schlechteste Möglichkeit, Widgets anzuordnen. GTK kennt eine Reihe von Containern, die das Anordnen von Widgets um vieles einfacher machen, beispielsweise gtk.HBox(), gtk.VBox(), gtk.Table() etc.

All diese Container haben den Vorteil, dass sie den verfügbaren Platz unter den Widgets *automatisch* aufteilen und die Widgets beispielsweise auch darüber informieren, wenn zusätzlicher Platz zur Verfügung steht, etwa weil das Fenster vergrößert wurde. Mit diesen Containern lassen sich dann beispielsweise Textboxen oder Knöppe umsetzen, die sich automatisch der Fenstergröße anpassen. Das ist meines Wissens bei einem Layout-Container nur mit (viel) Handarbeit möglich.

Besten Gruß,

brb
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ok, danke mal soweit. Hat funktioniert ;-)
Das Tutorial von pygtk.org ist ja ansich ne tolle Sache, aber ich versteh leider nur die hälfte. Aber ich bin dann einfach mal so frei und frag hier munter weiter.

Code: Alles auswählen

import pygtk
pygtk.require('2.0')
import gtk
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Testfenster")
window.resize(800,600)

wellcomebox = gtk.HBox(True, 0)
wellcomebox.show()
wellcome = gtk.Label()
wellcome.set_markup("<span font='25.0'>Test </span><span foreground='#ff0000' font='20.0'>Überschrift</span>")
wellcomebox.pack_start(wellcome)

bearbeitungsbox1 = gtk.VBox(True, 0)
bearbeitungsbox1.show()

bearbeitungsart = gtk.RadioButton(None, "Bearbeitungsart 1")
bearbeitungsbox1.pack_start(bearbeitungsart, True, True, 0)
bearbeitungsart.show()

bearbeitungsart = gtk.RadioButton(bearbeitungsart, "Bearbeitungsart 2")
bearbeitungsbox1.pack_start(bearbeitungsart, True, True, 0)
bearbeitungsart.show()

bearbeitungsart = gtk.RadioButton(bearbeitungsart, "Bearbeitungsart 3")
bearbeitungsbox1.pack_start(bearbeitungsart, True, True, 0)
bearbeitungsart.show()

bearbeitungsart = gtk.RadioButton(bearbeitungsart, "Bearbeitungsart 4")
bearbeitungsbox1.pack_start(bearbeitungsart, True, True, 0)
bearbeitungsart.show()

window.add(wellcomebox)
window.add(bearbeitungsbox1)

window.show_all()
Ich taste mich langsam vor. Nur warum wird immer nur eine Box angezeigt? Und wie schaff ichs das die Überschrift immer oben steht? Egal wie groß das fenster ist? Kann ich die boxen auch irgendwie schachteln?

Gruß Tom
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

ein Fenster (gtk.Window) kann immer nur ein Child haben.

Code: Alles auswählen

window.add(wellcomebox)
window.add(bearbeitungsbox1)
Wird daher also wohl nicht funktionieren. Was du machen musst: Du fügst deinem Fenster beispielsweise eine HBox hinzu und packst alle anderen Widgets und auch Container in diese HBox. Container wie HBox und VBox oder Tables können nämlich mehrere Childs verwalten.

Wenn dir die entsprechenden Artikel in der Original-Doku zu unverständlich erscheinen, gibt es hier noch eine kleine deutschsprachige Einführung in grafische Oberflächengestaltung mit Glade. Ich persönlich bin aber eigentlich der Meinung, dass man zumindest mal ein kleines Programm "von Hand" erstellt haben sollte, bevor man sich mit Glade auseinander setzt. Andererseits ist Glade natürlich eine tolle Möglichkeit, sich mal anzusehen, wie man Container und Widgets nach seinen Vorstellungen arrangiert.

Besten Gruß,

brb
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ok, danke! Klappt!
Ich hab keine andere Wahl als die GUI per Hand zu schreiben. Das Programm soll auf einer Maschinensteuerung zum Einsatz kommen auf der ich keine Pakete installieren kann. Da läuft ein Debian mit Xfce Desktop. Das Paket python-glade2 ist nicht installiert. Leider auch kein python-tk. Also bleibt nur Gtk zu verstehen.
Das Programm selbst ist fast fertig. Jetzt muß ich nur noch gtk richtig verstehen. Mit Tk wars ja einfach. Nur für gtk fehlen mir Deutsche 'Schriftstücke'.

Jetzt muß ich nur noch ganz dahinterkommen wie ich die Radiobuttons, Checkboxen und Entry-Zeilen so in Boxen schachtle das am Ende alles wieder in einem Fenster ist.
Dann werd ich mich damit beschäftigen wie ich das ganze abfrage, wie ich Dialogboxen ("So nicht! Deine Eingabe ergibt keinen sinn!"), und zu guter letzt eine Statusanzeige die zeigt wie weit die Berechnunge fortgeschritten sind und eine Grafische Zeichnung der Werkstücke erstelle.

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

wellnestom hat geschrieben:Ich hab keine andere Wahl als die GUI per Hand zu schreiben. Das Programm soll auf einer Maschinensteuerung zum Einsatz kommen auf der ich keine Pakete installieren kann. Da läuft ein Debian mit Xfce Desktop. Das Paket python-glade2 ist nicht installiert.
Ich denke nicht dass du python-glade brauchst. So wie ich das in erinnerung habe ist ja libglade eh Teil von PyGTK. Ansonsten GtkBuilder versuchen, Glade sollte auch dieses Format unterstützen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ich hab glade installiert damit ich mir das mit den boxen genauer anschauen kann. Aber ich bin da etwas altmodisch. :)
Ich will verstehen was ich mache, und arbeite immer lieber mit nem Texteditor und geh den steinigen Weg zu Fuß. So hab ichs auch mit XHTML, CSS, PHP und in dem Zusammenhang auch SQL geschafft.
Ein Mann - und gedit! :wink:

Vielleicht wird auch anderen geholfen wenn sie eure Antworten auf meine Fragen lesen. Ihr helft nicht nur mir, sondern der ganzen Menschheit! - Ist das nicht ne coole Rechtfertigung für meine Fragen? :)

Gruß Tom
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ich mache Fortschritte!
Jetzt hab ich folgende Frage:
Wie erreiche ich es das nach dem drücken der enter-Taste in einem entry-Feld eine Funktion aufgerufen wird, und dannach das selbe entry-Feld wieder mit blinkendem Cursor auf eine neue Eingabe wartet?

Gruß Tom
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

meinst du das?
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ja, genau!
Sorry, aber irgendwie find ich das selber nie. Liegt wahrscheinlich daran das ichs auch nur verstehe weil du mich mit der Nase draufstößt. :wink:
Jedenfalls bin ich jetzt (hoffentlich) bald am Ziel! Jetzt noch folgendes:

Wie kann ich in eine DrawingArea zeichnen?
Habs jetzt mal mit einer glade-Datei versucht. Wenn man ein wenig gtk verstanden hat, ist glade wirklich einfach.

Code: Alles auswählen

>>> mb=builder.get_object('malbereich')
>>> mb.draw_line(10,10,20,20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'gtk.DrawingArea' object has no attribute 'draw_line'
Gruß Tom
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo Tom,

*husträusper* :)

Anders gesagt: Du zeichnest nicht direkt auf das Ding, sondern auf einer Pixmap. Dort gibt es dann Funktionen wie "draw_line()" etc.
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Das hab ich auch schon mal versucht:

Code: Alles auswählen

>>> builder.add_from_file("rt.ui")
1L
>>> mb = builder.get_object('malbereich')
>>> pixmap=pixmap_new(mb, 50, 50, -1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'pixmap_new' is not defined
>>> pixmap = gtk.create_pixmap(mb, 50, 50, -1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.6/gtk-2.0/gtk/deprecation.py", line 64, in __call__
    raise TypeError(str(e).replace(func.__name__, self.oldname))
TypeError: drawable should be a GdkDrawable or None
Irgendwie kennt er davon gar nix.
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Hab jetzt versucht aus den Beispielen schlau zu werden.
Ergebniss: Sie funktionieren nicht!
Ich hab dann mal versucht Befehl für Befehl in den Interpreter einzugeben. Hier das Ergebniss:

Code: Alles auswählen

Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import gtk
>>> import GDK
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named GDK
Hab den Fehler bei mir auf Ubuntu 10.10 und auch auf Debian 6. Warum geht das nicht?
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Ich glaube, dass die in dem Beispiel auf eine selbst implementierte GDK-Bibliothek zugreifen - keine Ahnung. Normalerweise erfolgt der Zugriff auf GDK in PyGTK über gtk:

Code: Alles auswählen

>>> import gtk
>>> gtk.gdk
<module 'gtk.gdk' (built-in)>
>>> dir(gtk.gdk)
Sorry, mein obiger Link war wohl doch nicht sonderlich prall. Hilft dir dieses Beispiel nicht weiter: http://www.eurion.net/python-snippets/s ... 0Area.html ?

Achtung, in Zeile 151 wird versucht, eine Pixmap aus einer XPM zu erstellen. Das scheitert natürlich, wenn die Datei nicht existiert, was aber auch nicht weiter schlimm sein sollte.

Außerdem wird hier eine kleine Einführung versucht.

besten Gruß,

brb
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Also,
bis jetzt funktioniert ja alles...... ABER:
Wenn ich mit Cairo z.B. einen Halbkreis "cr.arc(50,50,40,1.57,0)" zeichne und den dann 'stroke', geht das nur wenn ichs direkt in der Interpreterkonsole mache. In einem fertigen Programm wird der Halbkreis nur für den Bruchteil einer Sekunde angezeigt - und dann isser wech!

Warum? Und vor allem - Was tu ich dagegen?

Gruß Tom
BlackJack

@wellnestom: Am besten mal eine minimale Anwendung schreiben, bei der man das Problem beobachten kann. Denn ohne Quelltext kann man da nicht viel sagen.
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Ok,
erstmal ein minimaler python Programm:

Code: Alles auswählen

import gtk
bu1 = gtk.Builder()
bu1.add_from_file("rdialog.ui")
window=bu1.get_object('window1')
darea1=bu1.get_object('drawingarea1')
cr1 = darea1.window.cairo_create()
cr1.set_line_width(1)
cr1.arc(50,50,40,1.507,0)
cr1.stroke()
gtk.main()
und die Datei "rdialog.ui":

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <property name="visible">True</property>
    <property name="modal">True</property>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="label" translatable="yes">Bitte Radius angeben</property>
            <attributes>
              <attribute name="scale" value="2,000000"/>
            </attributes>
          </object>
          <packing>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkHBox" id="hbox1">
            <property name="visible">True</property>
            <child>
              <object class="GtkVBox" id="vbox2">
                <property name="visible">True</property>
                <child>
                  <object class="GtkDrawingArea" id="drawingarea1">
                    <property name="width_request">100</property>
                    <property name="height_request">100</property>
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="lr1">
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkRadioButton" id="radiobutton1">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="active">True</property>
                    <property name="draw_indicator">True</property>
                  </object>
                  <packing>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkVBox" id="vbox3">
                <property name="visible">True</property>
                <child>
                  <object class="GtkDrawingArea" id="drawingarea2">
                    <property name="width_request">100</property>
                    <property name="height_request">100</property>
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="lr2">
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkRadioButton" id="radiobutton2">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="active">True</property>
                    <property name="draw_indicator">True</property>
                    <property name="group">radiobutton1</property>
                  </object>
                  <packing>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkVBox" id="vbox4">
                <property name="visible">True</property>
                <child>
                  <object class="GtkDrawingArea" id="drawingarea3">
                    <property name="width_request">100</property>
                    <property name="height_request">100</property>
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="lr3">
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkRadioButton" id="radiobutton3">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="active">True</property>
                    <property name="draw_indicator">True</property>
                    <property name="group">radiobutton1</property>
                  </object>
                  <packing>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="position">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkVBox" id="vbox5">
                <property name="visible">True</property>
                <child>
                  <object class="GtkDrawingArea" id="drawingarea4">
                    <property name="width_request">100</property>
                    <property name="height_request">100</property>
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="lr4">
                    <property name="visible">True</property>
                  </object>
                  <packing>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkRadioButton" id="radiobutton4">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="active">True</property>
                    <property name="draw_indicator">True</property>
                    <property name="group">radiobutton1</property>
                  </object>
                  <packing>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="position">3</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkHBox" id="hbox2">
            <property name="visible">True</property>
            <property name="spacing">50</property>
            <child>
              <object class="GtkLabel" id="label2">
                <property name="visible">True</property>
                <property name="label" translatable="yes">Radius:</property>
              </object>
              <packing>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="rentry">
                <property name="width_request">50</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">•</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="button1">
                <property name="label" translatable="yes">Ok</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
              </object>
              <packing>
                <property name="position">2</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
Ich hoffe das reicht.
BlackJack

@wellnestom: Es sieht so aus als wenn Du selbst dafür verantwortlich bist alles auf Anfrage neu zu Zeichnen: http://www.tortall.net/mu/wiki/PyGTKCairoTutorial

Zum Hintergrund: GUI-Toolkits speichern in der Regel kein Bild vom Inhalt der Fenster sondern malen immer alles neu wenn das Fenstersystem sagt, dass der Inhalt oder ein Teil davon neu gezeichnet werden soll. Zum Beispiel weil ein anderes Fenster einen Teil verdeckte und nun geschlossen wurde.
wellnestom
User
Beiträge: 29
Registriert: Sonntag 13. Februar 2011, 20:29

Und jetzt?
Dieses Auswahlfenster wird geöffnet, ich zeichne was rein, und weiter? Wenn ich die Befehle einzeln nacheinander in den Interpreter eingebe gehts ja. Nur wenn ichs in einem Programm hab, oder alles auf einmal in den Interpreter kopiere ists weg.
Wie soll ich das auf Anfrage neu zeichnen? Das Fenster wird in einer Funktion erstellt, falls bestimmte Bedingungen eintreten. Dann wird es wie oben geladen, mit Texten und 4 Zeichnungen gefüllt, und dann kann der User auswählen, und das Fenster wird geschlossen -> zurück zur Funktion.
Hab auch schon ein time.sleep(1) vor dem cr1.stroke() versucht um dem Fenster mehr Zeit zu geben. Klappt auch nicht.
Wenn du mir bitte einen kleinen Brocken Code auf Basis meines Codes oben posten könntest, würd ichs vielleicht verstehen.

Gruß Tom
BlackJack

@wellnestom: Die Anfrage kommt als Event. Wie man darauf reagiert wird doch im Tutorial gezeigt, dass ich verlinkt habe.
Antworten