Perché viene calcolata la larghezza e l’altezza in pixel di una stringa in Tkinter differiscono tra piattaforme?

Ho uno script Python che deve calcolare l’esatta dimensione delle stringhe arbitrarie visualizzati nella arbitrario di caratteri per generare i diagrammi semplici. Posso farlo facilmente con Tkinter.

import Tkinter as tk
import tkFont
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
(x,y) = (5,5)
text = "yellow world"
fonts = []
for (family,size) in [("times",12),("times",24)]:
    font = tkFont.Font(family=family, size=size)
    (w,h) = (font.measure(text),font.metrics("linespace"))
    print "%s %s: (%s,%s)" % (family,size,w,h)
    canvas.create_rectangle(x,y,x+w,y+h)
    canvas.create_text(x,y,text=text,font=font,anchor=tk.NW)
    fonts.append(font) # save object from garbage collecting
    y += h+5
tk.mainloop()

I risultati sembrano dipendere dalla versione di Python e/o il sistema:

Python 2.5 Mac 0S X, ore 12: (63,12), volte 24: (128,24). Python 2.6 Mac OS X, ore 12: (64,14), volte 24: (127,27). Python 2.6 Windows XP, ore 12: (78,19), volte 24: (169,36) http://grab.by/grabs/d24a5035cce0d8032ea4e04cb8c85959.png

Dopo Ned Batchelder citato, ho scoperto che la dimensione del font è diverso da piattaforma a piattaforma. Non può essere una garanzia di insuccesso, come a lungo si bastone con Tkinter, che rimane coerente con se stesso. Ma il mio programma completo non non Tkinter per eseguire il disegno effettivo: appena si basa sulla dimensione del carattere calcoli per generare un output (in SVG o come script Python per essere inviato a Nodebox). E ‘ lì che le cose vanno veramente male:

Uscita di mocodo http://grab.by/grabs/f67b951d092dd1f4f490e1469a53bca2.png

(Si prega di guardare il immagine in dimensione reale. Notare che il principale tipo di carattere utilizzato per queste uscite non Volte, ma Trebuchet MS)

Ora ho il sospetto che queste differenze non possono essere evitati con Tkinter. Che altra soluzione cross-platform consiglieresti?

  • Hai prendere screenshot del testo in questi tipi di carattere, e confrontarli con i valori che si stanno ottenendo?
  • Non vedo che tipo di “cross-platform” la soluzione che si desidera avere… diverse piattaforme e diversi hardware di usare vari tipi di carattere risoluzioni di carattere e gli algoritmi di rendering. Non credo che si potrebbe ottenere un costante risposta per tutti.
  • Si prega di aggiornare le immagini se è possibile, come sono andato ora.
  • anzi, mi dispiace 🙁 TinyGrab sembra morto. Google mi da nessun immagine con il nome del file, e Wayback Machine mi dice: “No URL è stato catturato per questo dominio” per questa pagina in MODO. Ci sono altre opzioni? Non ho la copia locale.
  • Io ignoro se qualsiasi.
InformationsquelleAutor Aristide | 2010-05-27



3 Replies
  1. 19

    Hai due problemi. Analizziamoli uno alla volta

    1: la differenza tra python 2.5 e 2.6 sulla stessa piattaforma con lo stesso font

    Queste due versioni di python utilizzare diverse versioni di tk. Sul mio mac box, 2.5 utilizza tk versione 8.4.19 e 2.6 utilizza 8.5.7. Nella versione 8.5.2 di tk sono state alcune modifiche al font di funzioni di misura di tk. Supponendo che i cambiamenti sono stati miglioramenti, penso che sia lecito ritenere che i numeri si ottiene da python 2.6 sono più precisi di quelli da 2.5.

    2: la differenza tra python 2.6 su mac e 2.6 sul PC.

    Ovviamente, dalle immagini ci sono, il PC è in uso un font più grande e, quindi, si ottengono grandi numeri per la misurazione. La domanda è, perché? Si specifica la dimensione del carattere in punti (1/72 di pollice). In ordine per Tk (o di qualsiasi sistema di rendering) per rendere il tipo di carattere, ha bisogno di sapere quanti pixel sono in un pollice sul display effettivo. Questo può variare su diversi sistemi, e Tk non è sempre dato un numero preciso dal sistema operativo sottostante, per fare i suoi calcoli.

    Storicamente, Apple e Microsoft hanno standardizzato il 72ppi e 96 ppi indipendentemente dall’effettiva di visualizzazione, in modo che i numeri sono sempre andando essere diversi. Per ulteriori informazioni sulle differenze nel modo in cui il mac e windows calcolare la densità di pixel vedere il Punti Per Pollice articolo su wikipedia.

    Si potrebbe provare a risolvere il problema specificando un tipo di carattere in pixel piuttosto che in punti. È possibile farlo utilizzando i numeri negativi per la dimensione del carattere.

    Infine, una cosa che si potrebbe aggiungere al vostro piccolo codice di esempio è quello di stampare il risultato della font.actual() comando — si potrebbe vedere qualcosa di diverso tra windows e mac caselle, il che spiegherebbe le differenze. Questo ti dice esattamente quale tipo di carattere utilizzato da Tk.

    • Grazie mille per la tua risposta! Mi hai fatto capire e risolvere i due problemi. Il primo è venuto dalla mia versione di Python 2.6: vale a dire, 2.6.1, che in realtà soffre di un bug di regressione riguardanti il formato del carattere: aggiornamento per Python 2.6.5 era la soluzione più facile. Il secondo problema è sparito anche quando ho usato i numeri negativi per specificare la dimensione del font. Questo comportamento è stato, in realtà, ha spiegato il Tk documentazione tcl.tk/man/tcl8.4/TkCmd/tk.htm, che non sapevo. Tutte le rocce e sono molto grato!
    • Se la mia risposta o qualsiasi altra risposta è di aiuto, si prega di considerare la marcatura risposta e ‘accettato’ — è una parte del tuo dovere di una domanda-asker.
    • la tua risposta mi ha aiutato. Ho già segnato come utile, ma per il resto del mio dovere, il sistema continua a dire: “Si può accettare questa risposta e un premio di taglie in 10 ore”. Suppongo ci sia un ritardo minimo di 24 ore. Si prega di essere certi sarò lieto di riprovare domani!
  2. 7

    Dopo aver cercato per anni ho finalmente trovato un modo per ottenere la larghezza di un testo in qualsiasi carattere e dimensione!

    from tkinter import *
    
    Window = Tk()
    Window.geometry("500x500+80+80")
    
    frame = Frame(Window) # this will hold the label
    frame.pack(side = "top")
    
    # CALCULATE:
    measure = Label(frame, font = ("Purisa", 10), text = "The width of this in pixels is.....", bg = "yellow")
    measure.grid(row = 0, column = 0) # put the label in
    measure.update_idletasks() # this is VERY important, it makes python calculate the width
    width = measure.winfo_width() # get the width
    
    # PROOF IT WORKS:
    canvas = Canvas(frame, width = 400, height = 200, bg = "light green")
    canvas.grid(row = 1, column = 0, columnspan = 100) # collumnspan is 100 so that the line lines up with the text
    line = canvas.create_line(0, 10, width, 10, width = 4) # make a line the same length as the text
    canvas.create_text(10, 20, font = ("Purisa", 10), text = "... "+str(width)+" Pixels", anchor = "nw")

    La linea che faccio è la prova che questo funziona per qualsiasi tipo di carattere.

    Ho testato questo per diversi tipi di carattere e dimensioni, a quanto ne so funziona.

    Questa è una foto di output:
    Perché viene calcolata la larghezza e l'altezza in pixel di una stringa in Tkinter differiscono tra piattaforme?

    • questo fermerà tutti gli utenti che pensano che la sua divertente tipo WWWWWWWWWWW in modo che non si adattano allo schermo!!!!!!!!!!!
  3. 5

    Non hai fatto niente di sbagliato: la dimensione del font non diversi da piattaforma a piattaforma.

    Non so perché la versione di Python questioni, ma le differenze sono solo un pixel, quindi potrebbe essere diverso di arrotondamento o di rendering del carattere stesso.

    • la versione di python è importante perché il tk versione questioni — font misure cambiato tra tk 8.4.x e 8.5.x (versioni utilizzato da python 2.5 e 2.6, rispettivamente).

Lascia un commento