TomSchimansky / CustomTkinter

A modern and customizable python UI-library based on Tkinter
MIT License
11.63k stars 1.09k forks source link

CTkOptionMenu and CTkComboBox Display Issue #2570

Open HussainiProgrammer opened 2 months ago

HussainiProgrammer commented 2 months ago

The width of the label inside any CTkOptionMenu and the entry inside any CTkComboBox is greater than what it should be. I investigated the source code and I think the calculation of the xpad on the right of the label/entry isn't valid in the _create_grid() method of both classes. Is there anything I can do to fix this? Screenshots: python_ytdgkvYL3m python_ytdgkvYL3m

I am running this code on a Windows 11 laptop and I am using customtkinter 5.2.2 (latest version):

from customtkinter import *
#from CTkMessagebox import CTkMessagebox
import matplotlib.pyplot as plt
#from solution import getSolution

#data = open("theme.txt", "r+", encoding="utf-8")

theme = 'dark' # theme = data.readlines()[0].strip()
set_appearance_mode(theme)
set_default_color_theme("blue")

fg = {
    "dark": "#b71c1c",
    "light": "#d32f2f"
}

hover = {
    "dark": "#8b0000",
    "light": "#b71c1c"
}

plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Times New Roman'] + plt.rcParams['font.serif']
plt.rcParams['mathtext.default'] = 'regular'

spaceWidth = 0.02
objWidth = 1-2*spaceWidth

boxHeight = 0.09
listHeight = 3*boxHeight

buttonHeight = 0.06
spaceHeight = (1-2*boxHeight-2*listHeight-buttonHeight)/6

inputFrameSpaceWidth = 0.005
inputFrameSpaceHeight = 0.1
inputFrameChildHeight = 1-2*inputFrameSpaceHeight
insertButtonWidth = inputFrameChildHeight*boxHeight/objWidth

gInputFrameChildWidth = (1-6*inputFrameSpaceWidth-insertButtonWidth)/4
rInputFrameChildWidth = (1-5*inputFrameSpaceWidth-insertButtonWidth)/3

givenValuesDict = {}
givenKey = 0

requiredValuesDict = {}
requiredKey = 0

removeButtons: list[CTkButton] = []

currentHeight = 0

def insertGivenValue():
    global givenKey

    quantity = gQuantityOption.get()
    value = gValueEntry.get()
    unit = gUnitOption.get()
    objects = gObjectsEntry.get()

    frame = CTkFrame(gListFrame)
    frame.pack(fill='x', padx=4, pady=4)

    label = CTkLabel(frame, text=f"{quantity}: {value}{unit} of {objects}", font=font2)
    label.pack(side='left', padx=5)

    removeButton = CTkButton(frame, text="Remove", fg_color=fg[theme], hover_color=hover[theme], command=lambda key=givenKey: removeGivenValue(frame, key))
    removeButton.pack(side='right', padx=5, pady=3)

    removeButtons.append(removeButton)

    givenValuesDict[givenKey] = [quantity, value, unit, objects]
    givenKey += 1

def removeGivenValue(frame: CTkFrame, key: int):
    frame.destroy()
    del givenValuesDict[key]

def insertRequiredValue():
    global requiredKey

    quantity = rQuantityOption.get()
    unit = rUnitOption.get()
    objects = rObjectsEntry.get()

    frame = CTkFrame(rListFrame)
    frame.pack(fill='x', padx=4, pady=4)

    CTkLabel(frame, text=f"{quantity} in {unit} of {objects}", font=font2).pack(side='left', padx=5)

    removeButton = CTkButton(frame, text="Remove", fg_color=fg[theme], hover_color=hover[theme], font=font2, command=lambda key=requiredKey: removeRequiredValue(frame, key))
    removeButton.pack(side='right', padx=5, pady=3)

    removeButtons.append(removeButton)

    requiredValuesDict[requiredKey] = [quantity, unit, objects]
    requiredKey += 1

def removeRequiredValue(frame: CTkFrame, key: int):
    frame.destroy()
    del requiredValuesDict[key]

def solve():
    pass
    # if len(givenValuesDict) and len(requiredValuesDict):
    #     plt.text(0,0, "$" + getSolution(list(givenValuesDict.values()), list(requiredValuesDict.values())) + "$").set_fontsize(28)
    #     plt.axis('off')
    #     plt.gcf().canvas.manager.set_window_title('Solution Window')
    #     plt.show()

    # else: CTkMessagebox(root, title="Input Error", message="Please Enter the Given Values and the Required Values in Your Problem", icon='cancel')

def updateFont(event=None):
    global currentHeight
    if root.winfo_height() != currentHeight:
        currentHeight = root.winfo_height()
        ratio = min([root.winfo_width()/750, root.winfo_height()/750])
        font1.configure(size=round(18*ratio))
        font2.configure(size=round(14*ratio))
        font3.configure(size=round(26*ratio))

def updateTheme(event=None):
    global theme
    newTheme = themeOption.get().lower()
    if newTheme != theme:
        theme = newTheme

        # data.seek(0)
        # data.truncate()
        # data.write(theme)

        set_appearance_mode(theme)

        for button in removeButtons:
            if button.winfo_exists():
                button.configure(fg_color=fg[theme], hover_color=hover[theme])

root = CTk()
root.title("Problem Solver UI Sample")
root.minsize(600, 600)
#root.after(201, lambda: root.iconbitmap("icon.ico"))
root.after(202, lambda: root.state("zoomed"))

# problemsTab = root
problemsTab = CTkFrame(root, corner_radius=0); problemsTab.place(relx=0.2, rely=0, relwidth=0.8, relheight=1)

font1 = CTkFont("Calibri")
font2 = CTkFont("Calibri")
font3 = CTkFont("Calibri")

themeOption = CTkOptionMenu(root, values=["Dark", "Light"], font=font1, dropdown_font=font2, command=updateTheme)
themeOption.set(theme.capitalize())
themeOption.place(relx=0.05*0.2, rely=0.0236, relwidth=0.9*0.2, relheight=0.05)

gInputFrame = CTkFrame(problemsTab)
gInputFrame.place(relx=spaceWidth, rely=spaceHeight, relwidth=objWidth, relheight=boxHeight)

gQuantityOption = CTkComboBox(gInputFrame, values=["Quantity 1", "Quantity 2", "Quantity 3"], font=font1, dropdown_font=font2)
gQuantityOption.place(relx=inputFrameSpaceWidth, rely=inputFrameSpaceHeight, relwidth=gInputFrameChildWidth, relheight=inputFrameChildHeight)

gQuantityOption.set

gValueEntry = CTkEntry(gInputFrame, placeholder_text="Value", font=font1)
gValueEntry.place(relx=2*inputFrameSpaceWidth+gInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=gInputFrameChildWidth, relheight=inputFrameChildHeight)

gUnitOption = CTkComboBox(gInputFrame, values=["Unit 1", "Unit 2", "Unit 3"], font=font1, dropdown_font=font2)
gUnitOption.place(relx=3*inputFrameSpaceWidth+2*gInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=gInputFrameChildWidth, relheight=inputFrameChildHeight)

gObjectsEntry = CTkEntry(gInputFrame, placeholder_text="Objects", font=font1)
gObjectsEntry.place(relx=4*inputFrameSpaceWidth+3*gInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=gInputFrameChildWidth, relheight=inputFrameChildHeight)

gInsertButton = CTkButton(gInputFrame, text="+", command=insertGivenValue, font=font3)
gInsertButton.place(relx=5*inputFrameSpaceWidth+4*gInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=insertButtonWidth, relheight=inputFrameChildHeight)

gListFrame = CTkScrollableFrame(problemsTab)
gListFrame.place(relx=spaceWidth, rely=spaceHeight+boxHeight+spaceHeight, relwidth=objWidth, relheight=listHeight)

rInputFrame = CTkFrame(problemsTab)
rInputFrame.place(relx=spaceWidth, rely=spaceHeight+boxHeight+spaceHeight+listHeight+spaceHeight, relwidth=objWidth, relheight=boxHeight)

rQuantityOption = CTkComboBox(rInputFrame, values=["Quantity 1", "Quantity 2", "Quantity 3"], font=font1, dropdown_font=font2)
rQuantityOption.place(relx=inputFrameSpaceWidth, rely=inputFrameSpaceHeight, relwidth=rInputFrameChildWidth, relheight=inputFrameChildHeight)

rUnitOption = CTkComboBox(rInputFrame, values=["Unit 1", "Unit 2", "Unit 3"], font=font1, dropdown_font=font2)
rUnitOption.place(relx=2*inputFrameSpaceWidth+rInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=rInputFrameChildWidth, relheight=inputFrameChildHeight)

rObjectsEntry = CTkEntry(rInputFrame, placeholder_text="Objects", font=font1)
rObjectsEntry.place(relx=3*inputFrameSpaceWidth+2*rInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=rInputFrameChildWidth, relheight=inputFrameChildHeight)

rInsertButton = CTkButton(rInputFrame, text="+", command=insertRequiredValue, font=font3)
rInsertButton.place(relx=4*inputFrameSpaceWidth+3*rInputFrameChildWidth, rely=inputFrameSpaceHeight, relwidth=insertButtonWidth, relheight=inputFrameChildHeight)

rListFrame = CTkScrollableFrame(problemsTab)
rListFrame.place(relx=spaceWidth, rely=spaceHeight+boxHeight+spaceHeight+listHeight+spaceHeight+boxHeight+spaceHeight, relwidth=objWidth, relheight=listHeight)

solveButton = CTkButton(problemsTab, text="Find Solution", command=solve, font=font1)
solveButton.place(relx=spaceWidth, rely=5*spaceHeight+2*boxHeight+2*listHeight, relwidth=objWidth, relheight=buttonHeight)

root.bind('<Configure>', updateFont)
root.mainloop()
#data.close()
Akascape commented 2 months ago

@HussainiProgrammer Try adjusting the corner radius for all the comboboxes/optionmenus

HussainiProgrammer commented 2 months ago

@Akascape I tried random values for corner_radius, and the labels/entries still look the same

Akascape commented 2 months ago

@HussainiProgrammer Try to configure them separately.

combobox.configure(corner_radius=10)

HussainiProgrammer commented 2 months ago

@Akascape Again, nothing changed.

Akascape commented 2 months ago

@HussainiProgrammer Also change the height maybe. I somehow solved this issue by configuring the width height values.

HussainiProgrammer commented 2 months ago

@Akascape Configuring the corner_radius actually works when I use Option Menus instead of Combo Boxes (but I have to use root.bind("<Configure>", configureCornerRadius) for some reason), and I have already tried changing the width and height and tried all the placing methods (.place, .pack, .grid) but settled on .place because they all had the same issue anyway, and I prefer it.