Canvas font

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Opa Hansi
User
Beiträge: 16
Registriert: Sonntag 12. März 2023, 10:21

Hallo,
ich will Text in einer bestimmten Schriftart ausgeben (Windows). Das funktioniert, soweit keine Leerzeichen im Fontnamen vorhanden sind:
Courier -> kein Problem, Courier New -> wird als Arial ausgegeben. Bei z.B. @MS PGothic passiert gar nichts.
Was ist die Ursache? Sind nur bestimmte Schriftarten erlaubt?

Ich hoffe auf Eure Erfahrung!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein ewiges Ärgernis, dieses Font-Thema. Was gibt denn https://docs.python.org/3/library/tkint ... t.families aus? Vielleicht ist darin ein Hinweis.
Opa Hansi
User
Beiträge: 16
Registriert: Sonntag 12. März 2023, 10:21

Hallo,
zb: @Microsoft JhengHei Light, Arial, Bahnschrift Light, Courier New, ...
Diese Schriftarten sind alle unter Windows installiert. Wenn ein Font mit Leerzeichen ausgewählt wird, kommt am Leerzeichen eine Fehlermeldung, weil hier die Schriftgröße erwartet wird. Dabei ist es egal, wie der Font übergeben wird.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@Opa Hansi: Hilfreich wäre vielleicht wenn du ein Minimalbeispiel zeigst, dass den Font setzt. Also do, dass man es ausprobieren kann.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und das tust, worum ich gebeten habe: die konkrete Liste der Fonts, die tkinter kennt, hier zu posten. Es geht darum rauszufinden, wie tkinter diese fonts sieht.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo Opa Hansi,

wichtig ist, den Namen der Schrift in Anführungszeichen zu setzen und
dass von tkinter das modul font importiert wird
Vor Jahren hab ich mir eine Schriftauswahl geschrieben.
Diese listet die im System bekannten Schriften auf und zeigt die gewählte an.

Code: Alles auswählen

import tkinter as tk
from tkinter import font
from functools import partial

class GUI_Schriftauswahl():
    """
    Erstellt die Gui mit der Beschreibung, den Schriftnamen,
    die Checkboxen zur Auswahl der Schrift und das Anzeigefeld    
    """
    def __init__(self, root):
        """
        verwendung hat die Inhalte None für zeichnen, formblatt fue Formblatt
        Schriften und symbole für Schriften der Symbolerstellung
        """
        self.root = root
        self.checkbutton_dict = {}
        self.schriftsatz = {}
        self.ausgewaehlte_schriften = {}
        self.ls_schriften = []
        self.schriftenliste = []
        self.gewaehlt = ""
        self.gewaehlte_Schrift = ""
        self.root = root
        self.schriften = font.families()
        self.anzeige = tk.StringVar()
        self.unterstrichen = 0
        self.toplevel = tk.Toplevel(self.root)
        self.toplevel.title(("Schriftauswahl"))
        beschrieb = (("Die vom System verfügbaren\n"
                       "Schriften sind aufgelistet.\n\n"
                       "Die anzuwendenden Schriften\n"
                       "auswählen.\n"))
        tk.Label(self.toplevel,text= beschrieb, width=35, relief='ridge', bd=5,
                 bg='lightyellow').pack(pady=5)
        self.rahmen = tk.Frame(self.toplevel, bg='cyan')#, width=1650, height=400)
        self.rahmen.pack()
        self.canvas = tk.Canvas(self.rahmen, bg="yellow", height=450, width=270)
        self.canvas.grid(column=0, row=0, sticky=tk.NW)

        self.felderrahmen = tk.Frame(self.canvas, bg='lightgreen', width=300,
                                     height=400)

        self.canvas.create_window(0, 0, window=self.felderrahmen, anchor='nw')

        self.ybar = tk.Scrollbar(self.rahmen, orient='vertical',
                                 command=self.canvas.yview)
        self.ybar.grid(column=2, row=0, sticky=tk.N+tk.S, padx=5)

        self.canvas.config(yscrollcommand=self.ybar.set)


        self.textfenster = tk.Canvas(self.rahmen, width=300,
                                     height=50, bg='white')
        self.textfenster.grid(row=2, column=0, columnspan=2,
                              pady=5)
        
        self.aufliste_schriften()
        for zeile, schriftart in enumerate(self.ls_schriften):
            self.schriftenliste.append(schriftart)
            self.anzeige_schrift = tk.Label(self.felderrahmen, text=schriftart,
                                         relief="raised", width=30,
                                         anchor="w")
            self.anzeige_schrift.grid(row=zeile, column=1)
            self.checkbutton_variable = tk.IntVar()Opa Hansi
            self.checkbutton_dict[zeile] = self.checkbutton_variable
            self.auswahl_schrift = tk.Checkbutton(self.felderrahmen,
                                    command=partial(self.auswahl, zeile),
                                    variable=self.checkbutton_variable)
            self.auswahl_schrift.grid(row=zeile, column=0, padx=3)

        self.felderrahmen.update_idletasks()
        groesse_anzeigefeld = self.felderrahmen.winfo_geometry()
        dimension_anzeigefeld = groesse_anzeigefeld.split('+')
        breite_hoehe = dimension_anzeigefeld[0].split('x')
        hoehe = breite_hoehe[1]
        self.canvas.config(scrollregion=(0, 0, 0, hoehe))
        self.toplevel.lift(self.root)
        
    def aufliste_schriften(self):
        """
        Setzt die Schriften in eine Menge um die Duplikate zu eliminieren.
        Aus der Menge ird eine sortierte Liste generiert.
        """
        ohne_duplikate = set(self.schriften)
        for schrift in ohne_duplikate:
            self.ls_schriften.append(schrift)
        self.ls_schriften.sort()

    def auswahl(self, zeile):
        """
        Werden Schriften an oder abgewaehlt,
        werden diese in das Dictionary self.ausgewaehlte_schriften
        aufgenommen Respektive gelöscht.
        """
        self.gewaehlte_schrift = self.schriftenliste[zeile]
        self.aktualisiere()
        an_ab_gewaehlt = self.checkbutton_dict[zeile].get()
        if an_ab_gewaehlt == True:
            self.ausgewaehlte_schriften[zeile] = self.gewaehlte_schrift
        else:
            del self.ausgewaehlte_schriften[zeile]    

    def aktualisiere(self):
        """
        Im Anzeigefenster wird die zuletzt gewaehlte Schrift angezeigt.
        """
        id_tuple = self.textfenster.find_all()
        if id_tuple != (): # Pruefung ob schon eine Schrift vorhanden ist
            self.textfenster.delete(id_tuple[0])
        schrift = f'"{self.gewaehlte_schrift}"'
        gewaehlt = self.textfenster.create_text(150, 40,
                                     text=self.gewaehlte_schrift,
                                     font=schrift)


def main():
    root = tk.Tk()    
    auswahl = GUI_Schriftauswahl(root)    
    root.mainloop()


if __name__ == "__main__":
    main()
Gruss Peter
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das ist nicht robust falls in dem Namen " vorkommen. Besser wäre es dort ein Tupel mit dem Namen drin zu übergeben und `tkinter` dann die Wandlung in den entsprechenden Tcl-Wert zu überlassen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Opa Hansi
User
Beiträge: 16
Registriert: Sonntag 12. März 2023, 10:21

Ich habe schnell ein Minimalbeispiel geschrieben und siehe da, es funktioniert.
Also sitzt der Fehler vor dem Monitor.
Ich werde jetzt in meinem Code suche, es kann nur etwas ganz einfaches sein!
Erstmal vielen Dank!

Code: Alles auswählen

from tkinter import *
from tkinter import font as fo


def schrift(fenster,olb,eingabe,ftx,w):
        cs=olb.curselection()
        ctab=""
        if len(cs)!=0:                  #Auswahl
                ctab=olb.get(cs)
                eingabe.insert(0,ctab)
                ftx["text"]=ctab
                ftx["font"]=(ctab, 10)
                w.delete("all")
                w.create_text(5,10, text= ctab,anchor="w",fill="blue",font=(ctab, 10))
        else:
                w.delete(all)
                
def prg(fenster):
        olb=Listbox(fenster,height=12,width=29)
        olb.place(x =10, y =10)

        for font in sorted(fo.families()):    
                olb.insert("end",font)

        w = Canvas(fenster, bg="ghostwhite")
        w.place(x =200, y =80, width=300, height=50)
        
        ftx=Label(fenster,anchor="w", compound=TOP,text="",font="Arial 10")
        ftx.place(x =300, y =60, width=200, height=20)
        
        eingabe=Entry(fenster)
        eingabe.place(x=300,y=10,width=100,height=20)

        pb= Button(fenster, text="Schrift wählen", relief="raised",command=lambda:schrift(fenster,olb,eingabe,ftx,w))
        pb.place(x = 300, y = 40, width=100, height=20)

        
def main():
        fenster=fenster=Tk()
        fenster.geometry("512x256+20-20")
        prg(fenster)
        fenster.mainloop()

if __name__=="__main__":

    main()

Opa Hansi
User
Beiträge: 16
Registriert: Sonntag 12. März 2023, 10:21

Fehler gefunden:
Das ist falsch:

Code: Alles auswählen

fnt=esatz[10][nl+1:]+", "+esatz[10][:nl]
font=(fnt)
so sollte es sein:

Code: Alles auswählen

font=(esatz[10][nl+1:],esatz[10][:nl])
Danke für Eure Mühe!!!
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@Opa Hansi: eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 8.
Benutze keine Abkürzungen, was soll ein olb oder ein flx sein?
*-Importe benutzt man nicht und fo ist auch keine gute Abkürzung für font.
place benutz man nicht. Bei mir klebt da so ein canvas über allem.
In ›schrift‹ wird ctab ein leerer String zugewiesen, aber nie benutzt.

Code: Alles auswählen

import tkinter as tk
from functools import partial

def select_font(fonts, eingabe, font_text, canvas):
    canvas.delete("all")
    font_index = fonts.curselection()
    if font_index:
        fontname = fonts.get(font_index)
        eingabe.insert(0, fontname)
        font_text["text"] = fontname
        font_text["font"] = (fontname, 10)
        canvas.create_text(5, 10, text=fontname,
            anchor="w", fill="blue", font=(fontname, 10))
        
def main():
    fenster = tk.Tk()
    fonts = tk.Listbox(fenster, height=12, width=29)
    fonts.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N)
    frame = tk.Frame()
    frame.grid(row=0, column=1, padx=5, pady=5, sticky=tk.N)

    for fontname in sorted(tk.font.families()):
        fonts.insert("end", fontname)

    eingabe = Entry(frame)
    font_text = tk.Label(frame, anchor="w", compound=tk.TOP, text="", font="Arial 10")
    canvas = tk.Canvas(frame, bg="ghostwhite")
    button = tk.Button(frame, text="Schrift wählen", relief="raised",
        command=partial(select_font, fonts, eingabe, font_text, canvas))
    eingabe.pack()
    button.pack()
    font_text.pack()
    canvas.pack()
    fenster.mainloop()

if __name__=="__main__":
    main()
In Deinem ganzen Code kommt kein ›esatz‹ vor. Was ist denn nl? Wieder so eine kryptische Abkürzung.
Antworten