2010-05-27 12 views
27

Ho uno script Python che deve calcolare la dimensione esatta delle stringhe arbitrarie visualizzate in caratteri arbitrari per generare semplici diagrammi. Posso farlo facilmente con Tkinter.Perché la larghezza e l'altezza calcolate in pixel di una stringa in Tkinter differiscono tra le piattaforme?

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, times 12: (63,12), times 24: (128,24). Python 2.6 Mac OS X, times 12: (64,14), times 24: (127,27). Python 2.6 Windows XP, times 12: (78,19), times 24: (169,36) http://grab.by/grabs/d24a5035cce0d8032ea4e04cb8c85959.png

Dopo Ned Batchelder accennato, ho scoperto che la dimensione dei caratteri è diversa da una piattaforma all'altra . Potrebbe non essere un rompicapo finché si rimane con Tkinter, che rimane coerente con se stesso. Ma il mio complete program non non utilizza Tkinter per eseguire il disegno reale: si basa solo sui calcoli della dimensione del carattere per generare un output (in SVG o come uno script Python da inviare a Nodebox). Ed è lì che le cose vanno davvero male:

Output of mocodo http://grab.by/grabs/f67b951d092dd1f4f490e1469a53bca2.png

(.. Si prega di guardare il image in real size Si noti che il carattere principale utilizzato per queste uscite non è Times, ma Trebuchet MS)

ora il sospetto che tali discrepanze non possono essere evitate con Tkinter. Quale altra soluzione multipiattaforma raccomanderesti?

+1

Hai preso screenshot del testo in questi caratteri, e confrontarli con i valori che si stanno ottenendo? –

+0

Non vedo che tipo di soluzione "multipiattaforma" desideri avere ... diverse piattaforme e diversi hardware utilizzano varie risoluzioni dei font e algoritmi di rendering dei font. Non penso che potresti avere una risposta costante per tutti loro. –

+1

Si prega di aggiornare le immagini, se possibile, come sono andati ora. – Nae

risposta

19

Hai due problemi. Diamo loro uno placcaggio alla volta

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

Queste due versioni di Python utilizzano diverse versioni di tk. Nella mia mac box, 2.5 usa tk versione 8.4.19 e 2.6 usa 8.5.7. Nella versione 8.5.2 di tk c'erano alcune modifiche alle funzionalità di misurazione dei caratteri di tk. Supponendo che i cambiamenti fossero miglioramenti, penso che sia sicuro assumere che i numeri ottenuti da Python 2.6 siano più accurati di quelli da 2.5.

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

Ovviamente, dagli screenshot che si includono, il PC utilizza un font più grande e quindi si ottengono numeri più grandi per la misurazione. La domanda è, perché? Stai specificando la dimensione del carattere in punti (1/72 di pollice). Affinché Tk (o qualsiasi sistema di rendering) possa renderizzare il carattere, è necessario sapere quanti pixel sono in un pollice sul display effettivo. Ciò varierà su diversi sistemi, e Tk non riceve sempre un numero preciso dal SO sottostante per fare i suoi calcoli.

Storicamente, Apple e Microsoft si sono standardizzati su 72ppi e 96ppi indipendentemente dal display effettivo, quindi i numeri saranno sempre diversi. Per ulteriori informazioni sulle differenze nel modo in cui Mac e Windows calcolano la densità dei pixel, consultare l'articolo Dots Per Inch su wikipedia.

Si potrebbe provare a risolvere ciò specificando un carattere in pixel piuttosto che in punti.Puoi farlo usando numeri negativi per la dimensione del carattere.

Infine, una cosa che potresti aggiungere al tuo piccolo codice di esempio è stampare il risultato del comando font.actual() - potresti vedere qualcosa di diverso tra finestre e mac, il che spiegherebbe le differenze. Questo ti dice esattamente quale font viene usato da Tk.

+0

Grazie mille per la risposta, mi hai fatto capire e risolvere i due problemi: Il primo è venuto dalla mia versione di Python 2.6: ovvero 2.6.1, che effettivamente soffre di un bug di regressione riguardante il font metriche: l'aggiornamento a Python 2.6.5 era la soluzione facile Anche il secondo problema scompariva quando ho usato numeri negativi per specificare la dimensione dei caratteri. havior è stato effettivamente spiegato nella documentazione di Tk su http://www.tcl.tk/man/tcl8.4/TkCmd/tk.htm, che non conoscevo. Tutte le pietre ora e sono molto grato! – Aristide

+0

@Aristide: se la mia risposta o qualsiasi altra risposta ti aiuta, considera di contrassegnare la risposta come "accettata" - fa parte del tuo dovere di domanda-richiedente. –

+0

la tua risposta mi ha aiutato. L'ho già segnalato come utile, ma per il resto del mio dovere, il sistema continua a dire: "Puoi accettare questa risposta e assegnare la tua taglia in 10 ore". Suppongo che ci sia un ritardo minimo di 24 ore. Ti assicuriamo che riproverò volentieri domani! – Aristide

5

Non hai fatto nulla di sbagliato: la dimensione dei caratteri corrisponde a diversa da piattaforma a piattaforma.

Non sono sicuro del motivo per cui la versione di Python è importante, ma le differenze sono solo di un pixel, quindi potrebbe essere un arrotondamento o un rendering diverso dello stesso carattere.

+2

la versione python importa perché la versione tk è importante - le misure dei caratteri sono cambiate tra tk 8.4.xe 8.5.x (le versioni usate da python 2.5 e 2.6, –

6

Dopo aver cercato per anni ho finalmente trovato un modo per ottenere la larghezza di un testo in qualsiasi font 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 provato questo per diversi tipi di carattere e dimensioni, per quanto ne so funziona.

Questa è una foto dell'uscita: This is a picture of the output

+0

questo fermerà tutti gli utenti che pensano che sia divertente digitare WWWWWWWWWW in modo che non si adatti allo schermo !!!!!!!!!!! –

Problemi correlati