-1

I am trying to create a program that allows the user to change the font of the labels in the window. I am having trouble figuring out exactly how to recreate all the labels with the new fonts. Here is what I have so far:

import tkinter as tk
from tkinter import messagebox, colorchooser, simpledialog, filedialog, font

root = tk.Tk()
root.withdraw()

screenHieght = root.winfo_screenheight()  # height of the screen
screenWidth = root.winfo_screenwidth()  # width of the screen

windowHieght = screenHieght / 2  # Turtle window is half of screen size
windowWidth = screenWidth / 2

x = (screenWidth / 2) - (windowWidth / 2)
y = (screenHieght / 2) - (windowHieght / 2)

root.geometry('%dx%d+%d+%d' % (windowWidth, windowHieght, x, y))  # Some assistance from Google on centering the window
root.columnconfigure(3, weight=2)
root.columnconfigure(1, weight=1)
root.columnconfigure(5, weight=1)
root.rowconfigure(1, weight=2)
root.rowconfigure(3, weight=1)
root.rowconfigure(4, weight=1)
root.rowconfigure(5, weight=1)
root.configure(background="#a1dbcd")

def changeFont(selection):
    global selectedfont
    global setfontstyle
    print(selection)
    selectedfont = selection
    print(setfontstyle)

def changeSize(val):
    print(val)
    global setfontstyle
    global fontsize
    fontsize = val
    print(setfontstyle)

def newfontstyle():
    global setfontstyle
    global selectedfont
    global fontsize
    setfontstyle = font.Font(family = selectedfont, size = fontsize)


fontsize = tk.IntVar(root)
selectedfont = tk.StringVar(root)
setfontstyle = font.Font(family=selectedfont, size=12, weight='normal')

def atributes():
    while True:
        global setfontstyle
        global selectedfont
        global fontsize
        fontchoose = ["Arial", "Courier New", "Comic Sans MS", "Fixedsys", "MS Sans Serif", "MS Serif", "Symbol",
                      "System",
                      "Times New Roman", "Verdana"]

        selectedfont.set("Arial")
        # Variables and stuff

        label1 = tk.Label(root, text="Select your options", font=setfontstyle).grid(row=1, column=3, pady=10,
                                                                                    sticky=tk.E + tk.W + tk.N + tk.S)
        label2 = tk.Label(root, text="Font Style", font=setfontstyle).grid(row=3, column=5, pady=10,
                                                                           sticky=tk.E + tk.W + tk.N + tk.S)
        fontdropdown = tk.OptionMenu(root, selectedfont, *fontchoose, command=changeFont).grid(row=4, column=5, pady=10,
                                                                                               sticky=tk.E + tk.W + tk.N + tk.S)
        label3 = tk.Label(root, text="Font Size", font=setfontstyle).grid(row=3, column=1, pady=10,
                                                                          sticky=tk.E + tk.W + tk.N + tk.S)
        fontsize = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, command=changeSize).grid(row=4, column=1,
                                                                                                  pady=10,
                                                                                                  sticky=tk.E + tk.W + tk.N + tk.S)
        redoall = tk.Button(root, text="Recreate", font=setfontstyle, command=newfontstyle).grid(
            row=5, column=3, pady=10, sticky=tk.E + tk.W + tk.N + tk.S)

        # print(fontdropdown)
        root.deiconify()
        # root.wait_variable(selectedfont or fontsize)
        root.mainloop()

Thank you for the help. I have been struggling to figure out the answer for a couple of days.

Alex
  • 89
  • 1
  • 10
  • 1
    You don't need to recreate the labels. You can change the font of existing labels. See https://stackoverflow.com/a/4073037/7432 – Bryan Oakley May 02 '18 at 13:12
  • But how do I get all of the labels at once. Is there a way I could use a for loop or something? – Alex May 02 '18 at 13:16
  • 2
    If you read the link I posted, you don't have to do anything to the labels at all. GIve them all the same font object and then you only have to change the one font object. – Bryan Oakley May 02 '18 at 13:30
  • Sorry, I am a little bit confused. I am pretty sure that I am using `setfontstyle` as my font object. However, when I modify it, nothing changes – Alex May 02 '18 at 13:40
  • Unrelated to the question, why are you calling `mainloop` in a loop, or is that just an error in how you posted the code? Also, please post code that actually runs. When I run your code it does nothing (possibly because nothing calls `atributes`. – Bryan Oakley May 02 '18 at 14:18
  • Um, I'm not sure, should I change it to `update` instead? – Alex May 02 '18 at 14:20
  • Your `root.mainloop()` should be in the global name space with `root=Tk()`. In this case I would put `root.mainloop()` at the very bottom of your script. – Mike - SMT May 02 '18 at 14:34
  • No. You don't need `update` and you don't need to call `mainloop` in a loop. You don't need that `while True` loop at all. It serves no purpose. – Bryan Oakley May 02 '18 at 14:37

1 Answers1

1

You do not need to recreate anything. Since you are using a font object, all you need to do is modify that font object and any font that uses that object will instantly show the new font.

def changeFont(selection):
    setfontstyle.configure(family=selection)

def changeSize(val):
    setfontstyle.configure(size=val)

There are other bugs in your code, but this answers your specific question.

Here's a short example program that shows how the widgets change immediately when you change an attribute of the font:

import tkinter as tk
import tkinter.font

font_families = [
    "Arial", "Courier New", "Comic Sans MS", "Fixedsys",
    "MS Sans Serif", "MS Serif", "Symbol",
    "System", "Times New Roman", "Verdana"
]

def changeSize(val):
    appFont.configure(size=val)

def changeFont(family):
    appFont.configure(family=family)


root = tk.Tk()
root.geometry("400x200")

fontFamily = tk.StringVar(value="Arial")
fontSize = tk.IntVar(value=12)

appFont = tk.font.Font(family=fontFamily.get(), size=fontSize.get(), weight='normal')

size_widget = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL,
                       command=changeSize, variable=fontSize)
family_widget = tk.OptionMenu(root, fontFamily, *font_families, command=changeFont)
label = tk.Label(root, text="Hello, world", font=appFont)

label.pack(side="top", fill="both", expand=True)
size_widget.pack(side="bottom", fill="x", expand=False)
family_widget.pack(side="bottom", fill="x", expand=False)

root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685