I’m writing a cross-platform text parser that, among other things, word wraps text so that another cross-platform program (which I don’t control) can properly render the text in a variable-length font. Word wrapping requires getting the pixel-width of the text, but width varies depending on which OS I run my program on. The following code, for example, says the word "Wings" has length 31 on OS X 10.10, but on Windows XP, it says 30.
from Tkinter import Tk
import tkFont
root = Tk()
font = tkFont.Font(family="Times New Roman", size=-12)
# Note the negative value of size, showing the font size is the same.
print font.measure("Wings”)
This means that text wrapped on one platform won’t be displayed properly when the other program is run on the other platform. If I word wrap on XP and display on OS X, the text that I wrapped assuming it was 30 pixels is now 31 pixels. That one extra pixel could cause an error in how the wrapped text displays on the other program, and that was from just one word. Longer words cause more pixel differences, which makes the word wrapper less accurate.
I’m aware that the Tkinter widths should be different because the different OS's render the font differently. Since the font I’m using in my actual program is wider in Windows than OS X, I’d like to have Tkinter use the Windows measurement, even if I’m on OS X. This seems to be the only way to get a cross-platform font measurement that doesn’t risk word wrapping too late. How can I go about doing this? If I can’t, how else could I get a cross-platform width measurement that's consistent, reasonably accurate, and not too small?
EDIT:
The program that reads the output of my program expects a string of text for it to display, and I cannot control how it displays it, or convince it to accept an image. The only thing I can control is that string.
Related
I am using some libraries that are using tkinter, and the font is so tiny I can't read it (a few pixels only). Here is a minimum working example:
from tkinter import *
root = Tk()
myLabel = Label(root, text = 'Hello, world!')
myLabel.pack()
root.mainloop()
The working example produces the tiny hello world in the window to the right: mwe tiny font
The rest of the image is showing the gitk gui as a size reference.
Is there a way to set the default font size in tkinter without changing the code? It could also be a problem with dpi settings?
I am on Arch linux, i3wm, using the nvidia proprietary driver
Add this line to the beginning of your code. change helevicta by the font you want to use, change 20 by the font size you want to use and change bold by any formatting options you want (you don't have to include any, and if you do, you can add more than one.) This line will set the font for any labels in the root window.
root.option_add("*Label.Font", "helvetica 20 bold")
I found a workaround to my problem.
Tkinter has an automatic way to determine the monitor size and it will set a tk scale variable accordingly. In my case the scaling value does the opposite of what it is supposed to do - larger scaling value leads to smaller font size. I still don't know why that is the case.
I ran strace on my minimum working example and found out that tkinter tries to read the file ~/.Tk.tcl and I can therefore use this file as a configuration file.
Putting tk scaling 1.0 into ~/.Tk.tcl solved the problem for me. You can experiment with the scaling value to increase/decrease the overall scaling of the gui components.
Looking at strace it also tries to read ~/.Tk.py, ~/.example.tcl and ~/.example.py.
Yes you can set default font for tkinter widgets. Refer to this thread
https://stackoverflow.com/questions/15462647/modify-the-default-font-in-python-tkinter#:~:text=2%20Answers&text=Tkinter%20has%20several%20built%2Din,them%20will%20change%20as%20well.
So, the idea here is that the given text, which happens to be Devanagari character such as संस्थानका कर्मचारी and I want to convert given text to image. Here is what I have attempted.
def draw_image(myString):
width=500
height=100
back_ground_color=(255,255,255)
font_size=10
font_color=(0,0,0)
unicode_text = myString
im = Image.new ( "RGB", (width,height), back_ground_color )
draw = ImageDraw.Draw (im)
unicode_font = ImageFont.truetype("arial.ttf", font_size)
draw.text ( (10,10), unicode_text, font=unicode_font, fill=font_color )
im.save("text.jpg")
if cv2.waitKey(0)==ord('q'):
cv2.destroyAllWindows()
But the font is not recognized, so the image consists of boxes, and other characters that are not understandable. So, which font should I use to get the correct image? Or is there any better approach to convert, the given text in character such as those, to image?
So I had a similar problem when I wanted to write text in Urdu onto images, firstly you need the correct font since writing purely with PIL or even openCV requires the appropriate Unicode characters, and even when you get the appropriate font the letters of one word are disjointed, and you don't get the correct results.
To resolve this you have to stray a bit from the traditional python-only approach since I was creating artificial datasets for an OCR, i needed to print large sets of such words onto a white background. I decided to use graphics software for this. Since some like photoshop even allows you to write scripts to automate processes.
The software I went for was GIMP, which allows you to quickly write and run extensions.scripts to automate the process. It allows you to write an extension in python, or more accurately a modified version of python, known as python-fu. Documentation was limited so it was difficult to get started, but with some persistence, I was able to write functions that would read text from a text file, and place them on white backgrounds and save to disk.
I was able to generate around 300k images from this in a matter of hours. I would suggest if you too are aiming for large amounts of text writing then you too rely on python-fu and GIMP.
For more info you may refer to the GIMP Python Documentation
Right now I'm working hard to finish a project named Pihpone; I've been following the adafruit tutorial and I've also bought all the items that were suggested by them
The problem is that..the code was written for 2,8" while I have a 3.5" screen
I've succeeded in making some changes like modifying the 320x240 with 480x320
Still not enough but I dont know what to do further; pls come with any suggestion;
Here are the screenshots:
Before
After
https://github.com/climberhunt/Piphone/archive/master.zip
From there you can download the code made by Adafruit; you can find the code in piphone.py.
The code in piphone.py appears to be using the pygame module to do the graphics. The problem is all the hardcoded coordinates and sizes for things like the Buttons. To fix this, the values must be computed at run-time and depend on the display resolution. Line 255 sets the display mode.
screen = pygame.display.set_mode(modes[0], FULLSCREEN, 16)
After doing that, you can get a video display information object from pygame.display.Info() and obtain the width and height of the current video mode, then use those values to scale and position the buttons.
You may also need to create different sets of image files for the various sizes of display you want the program to support.
I have continued making progress on my python roguelike, and dived further into this tutorial: http://roguebasin.roguelikedevelopment.org/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod . I also made my own font to use in this game, but I'm not sure how to do so. This is a link to the font image I'm currently using: http://i.imgur.com/j6FdNky.png . In the python code, it sets a custom font to 'arial10x10.png' which is that font image. I tried making an image from my own font, but it got really distorted.
Does anyone know how I could implement my own font? Also, I'm using libtcod, and I only have my own font in a .ttf format.
Thanks.
To render your TrueType font to a bitmap in the way that libtcod expects, you should use a separate library -- font rendering is a surprisingly complex task. FreeType is a very popular open source library for font rendering. You can find a Python interface here: http://code.google.com/p/freetype-py/. You will only need to use FreeType in a tool you'll use when developing your roguelike, not in your actual game.
First, determine what characters you will be using in your roguelike. Determine how to layout these characters on your font sheet. You can also simply choose to use the same layout as the one in the image you posted -- that's a sheet with 32 columns, starting at the space character (character 32).
Using your font rendering library, render each character by itself at the desired size. Pay attention to the size generated for each -- for instance, a '.' will be small and a 'w' will be large, even at the same font size. You must not just calculate a height, but a height above the baseline and a height below the baseline. (Example: if 'A' and 'g' are both 16 pixels tall, it's possible that you'll still need a rectangle taller than 16 pixels to align both correctly within it -- baseline-to-baseline.) Find the smallest rectangle size that will accommodate all of these sizes -- this is how large each cell in your font sheet must be.
Once you know how large your sheet will be, make another pass through all the desired letters to construct your bitmap, putting each letter in its cell. As far as y-positioning goes, all baselines must be aligned. If some characters are wider than others, you can choose to center or to left-align each character within its cell. (Each of these will come with its own weirdnesses -- you're really going to want a fixed-width font for a roguelike.)
Additional tips:
Use antialiasing. This'll make your font easier on the eyes than pure
monochrome.
Don't use colour, render your font in grayscale. libtcod has
functionality to generate coloured text from your grayscale
fontsheet.
Consider whether you want a square font or not. The advantage of a
square font is that "circles" in your roguelike world will look like
circles on the screen. The disadvantage is that square fonts are
generally "uglier" and harder to read.
Question
I have created several GUI projects so far, but they all have one fatal mistake. When I make a window smaller, (which usually uses only one frame.) several of the widgets will disappear. Is there anyway to make the widgets 'aware' of the size of their frame?
What I have tried so far
I have tried to use this:
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
to specify the size of the window, but since many widgets use values other than pixels, it never works. I am also unsure as to whether it updates constantly or only when the window is spawned. (Text uses the size of the characters... etc)
Specs
Python 2.7.3
Windows 7/ Mac OSX Lion
This is generally quite easy, and often just happens by default. It all depends on how you use pack and grid. Without seeing your code it's going to be hard to give you useful information.
Can you show us a really small program that illustrates the problem and is an accurate indication of how you lay out your GUIs?