2010-05-27 18 views
27

Tengo un script de Python que necesita calcular el tamaño exacto de las cadenas arbitrarias que se muestran en fuentes arbitrarias para generar diagramas simples. Puedo hacerlo fácilmente con Tkinter.¿Por qué el ancho y la altura calculados en píxeles de una cadena en Tkinter difieren entre las plataformas?

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() 

Los resultados parecen depender de la versión de Python y/o el 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

Después de Ned Batchelder lo mencionó, he descubierto que el tamaño de las fuentes difiere de una plataforma a otra . Puede no ser un factor decisivo, siempre y cuando te quedes con Tkinter, que sigue siendo coherente consigo mismo. Pero mi complete program hace no usa para realizar el dibujo real: solo se basa en los cálculos del tamaño de fuente para generar una salida (en SVG o como una secuencia de comandos de Python que se enviará al Nodebox). Y es ahí donde las cosas van realmente mal:

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

(.. Por favor mira el image in real size Tenga en cuenta que la fuente principal que se utiliza para estas salidas no es Times, pero Trebuchet MS)

Ahora sospecho que tales discrepancias no se pueden evitar con Tkinter. ¿Qué otra solución multiplataforma recomendaría?

+1

¿Tomó capturas de pantalla del texto en estas fuentes, y compararlos con los valores que está recibiendo? –

+0

No veo qué tipo de solución de "plataforma cruzada" desea tener ... diferentes plataformas y hardware diferente usan varias resoluciones de fuente y algoritmos de representación de fuentes. No creo que puedas obtener una respuesta constante para todos ellos. –

+1

Actualice las imágenes si puede, ya que ahora se han ido. – Nae

Respuesta

19

Tiene dos problemas. Vamos a abordarlos uno a la vez

1: la diferencia entre pitón 2,5 y 2,6 en la misma plataforma con la misma fuente

Estas dos versiones de Python utilizan diferentes versiones de tk. En mi mac box, 2.5 usa tk versión 8.4.19 y 2.6 usa 8.5.7. En la versión 8.5.2 de tk hubo algunos cambios en las características de medición de fuentes de tk. Asumiendo que los cambios fueron mejoras, creo que es seguro asumir que los números que obtienes de python 2.6 son más precisos que los de 2.5.

2: la diferencia entre python 2.6 en el mac y 2.6 en la PC.

Obviamente, a partir de las capturas de pantalla que incluye, la PC usa una fuente más grande y así obtiene números más grandes para la medición. La pregunta es, ¿por qué? Está especificando el tamaño de fuente en puntos (1/72 de pulgada). Para que Tk (o cualquier sistema de representación) represente la fuente, necesita saber cuántos píxeles hay en una pulgada en la pantalla real. Esto variará en diferentes sistemas, y el sistema operativo subyacente no siempre le da un número exacto a Tk para hacer sus cálculos.

Históricamente, Apple y Microsoft se han estandarizado en 72ppi y 96ppi independientemente de la pantalla actual, por lo que los números siempre serán diferentes. Para obtener más información acerca de las diferencias en cómo Mac y Windows calculan la densidad de píxeles, consulte el artículo Dots Per Inch en wikipedia.

Puede intentar resolver esto especificando una fuente en píxeles en lugar de en puntos.Puedes hacer esto usando números negativos para el tamaño de la fuente.

Finalmente, una cosa que podría agregar a su pequeño código de ejemplo es imprimir el resultado del comando font.actual(); es posible que vea algo diferente entre sus ventanas y cuadros de mac, lo que explicaría las diferencias allí. Esto te dice exactamente qué fuente está usando Tk.

+0

¡Muchas gracias por su respuesta! Me hizo comprender y solucionar los dos problemas. El primero vino de mi versión de Python 2.6: a saber, 2.6.1, que en realidad sufre de un error de regresión con respecto a la fuente métricas: actualizar a Python 2.6.5 fue la solución fácil. El segundo problema desapareció también cuando usé números negativos para especificar el tamaño de las fuentes. El comportamiento se explicó en realidad en la documentación de Tk en http://www.tcl.tk/man/tcl8.4/TkCmd/tk.htm, que no sabía. Todas las rocas ahora y estoy muy agradecido! – Aristide

+0

@Aristide: Si mi respuesta u otra respuesta lo ayudan, considere marcar la respuesta como 'aceptada'; es parte de su deber como preguntador. –

+0

su respuesta me ayudó. Ya lo he marcado como útil, pero por el resto de mi trabajo, el sistema sigue diciendo: "Puede aceptar esta respuesta y otorgar su recompensa en 10 horas". Supongo que hay un retraso mínimo de 24 h. ¡Tenga la certeza de que volveré a intentar mañana! – Aristide

5

No ha hecho nada malo: el tamaño de las fuentes hace difieren de una plataforma a otra.

No estoy seguro de por qué la versión de Python importa, pero las diferencias son solo de un píxel, por lo que podría ser un redondeo diferente o una representación diferente de la misma fuente.

+2

la versión de python importa porque la versión de tk importa: las medidas de fuente cambiaron entre tk 8.4.x y 8.5.x (las versiones utilizadas por python 2.5 y 2.6, respectivamente). –

6

Después de buscar las edades, finalmente encontré la manera de obtener el ancho de algunos textos en cualquier fuente y tamaño.

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 línea que hago es prueba de que esto funciona para cualquier fuente.

He probado esto para diferentes fuentes y tamaños, hasta donde yo sé que funciona.

Esta es una foto de la salida: This is a picture of the output

+0

esto detendrá a todos los usuarios que piensan que es divertido escribir WWWWWWWWWWW para que no quepa en la pantalla !!!!!!!!!!! –

Cuestiones relacionadas