Positioning text inside OptionMenu in tkinter python - python

hy I am working on tkinter python project.
I am trying to position text to the Left inside OptionMenu using anchor option but it does not seem to work. I am using ttk theme widgets.
Here is the code that I am trying currently.
s = ttk.Style()
s.configure('my.TMenubutton', font=("Cambria", fontSize, "bold"), background="white", anchor = W )
shapeMenu = ttk.OptionMenu(shapeFrame, shape, myShapes[1], *myShapes, style='my.TMenubutton', command=getShapes)
What I am doing wrong ?

It seems like there is no anchor option under TMenubutton. I tried TLabel, and it worked. Don't know if there is any side effect though.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('300x100')
CHART_TYPES = ('Reticle', 'Circle Grid', 'Checkerboard', 'Grille', 'Slanted Edge MTF')
s = ttk.Style()
s.configure('my.TLabel', font=("Cambria", 10, "bold"), background="white", anchor = 'w' )
chart_type = tk.StringVar()
chart_type.set(CHART_TYPES[0])
# chart_selector = tk.OptionMenu(root, chart_type, *CHART_TYPES)
chart_selector = ttk.OptionMenu(root, chart_type, *CHART_TYPES, style='my.TLabel')
# chart_selector.configure(anchor='w')
chart_selector.pack(expand=True, fill='x')
root.mainloop()

Related

Treeview moves after click on Combobox with Tkinter

I have developped a app in Python (tested with 3.8 and 3.9 on Windows 10) with Tkinter. I am using a Combobox and a Treeview. I want to change dynamically the width of dropdown listbox and I could do it by changing the style of TCombobox with the parameter postoffset.
However, everytime I click on the Combobox, the table next to it moves and extends its width by itself. I really don't know where this problem comes from.
I have created a simple code so that you can reproduce the problem.
import tkinter as tk
from tkinter import ttk
import tkinter.font as tkfont
def combo_configure(event, style):
combo = event.widget
long = max(combo.cget('values'), key=len)
font = tkfont.Font(family="Helvetica", size=10)
width = max(0,font.measure(long.strip() + '0') - combo.winfo_width())
style.configure('TCombobox', postoffset=(0,0,width,0))
win = tk.Tk()
win.geometry("850x250")
style = ttk.Style()
f = tk.Frame(win)
f.configure(bg="black")
f.pack()
combo = ttk.Combobox(f, style="TCombobox", values=["It's a test on Combobox style."], width=10)
combo.bind('<ButtonPress>', lambda e : combo_configure(e, style))
combo.pack(side="left")
tree = ttk.Treeview(f, column=["Column 1"], show='headings', height=10)
tree.heading(0, text="Column 1")
tree.column(0, anchor=tk.CENTER, width=125)
tree.pack()
win.mainloop()
Thanks.

Tkinter - How can I change the default Notebook border color?

Below is my example code:
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("400x300")
style=ttk.Style()
style.configure("TNotebook", highlightbackground="#848a98") # if I use another option like - background="#848a98" - the style changes, but with - highlightbackground="#848a98" - option the style doesn't change..
MainNotebook = ttk.Notebook(root, style="TNotebook")
MainNotebook.place(x=16, y=16)
Frame1=Frame(MainNotebook, background="#ffffff", width=200, height=150)
Frame1.pack()
Frame2=Frame(MainNotebook, background="#ffffff", width=200, height=150)
Frame2.pack()
MainNotebook.add(Frame1, text="Tab1")
MainNotebook.add(Frame2, text="Tab2")
root.mainloop()
my goal is change the default border color in "#848a98" but the option highlightbackground="#848a98" doesn't work. am I using the wrong instruction? how can I solve my issue?
I think this should do the work. So, as I read it, you need to change the color of the background for focused and not-focused apps; also, for no borders, set the highlight thickness to 0 (ZERO):
from tkinter import *
root = Tk()
e = Entry(highlightthickness=2)
e.config(highlightbackground = "red", highlightcolor= "red")
e.pack()
root.mainloop()

tkinter ttk treeview colored rows

I am trying to set colors to rows in a tkinter treeview object, using tags and tag_configure.
There has been an earlier discussion on coloring rows which is rather old and seems to work no longer for Python3:
ttk treeview: alternate row colors
I have added a brief example. For me, all rows stay white, independent of whether I execute tag_configure prior or after the insert command.
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
w = tk.Label(root, text="Hello, world!")
w.pack()
lb= ttk.Treeview(root, columns=['number', 'text'], show="headings", height =20)
lb.tag_configure('gr', background='green')
lb.column("number", anchor="center", width=10)
lb.insert('',tk.END, values = ["1","testtext1"], tags=('gr',))
lb.insert('',tk.END, values = ["2","testtext2"])
lb.pack()
root.mainloop()
What has changed or what am I missing?
EDIT:
Seems that this is a new known bug with a workaround, but I don't get this working:
https://core.tcl-lang.org/tk/tktview?name=509cafafae
EDIT2:
I am now using tk Version 8.6.10 (Build hfa6e2cd_0, Channel conda-forge) and python 3.7.3. Can anyone reproduce this error with this version of python and tk?
You no longer need to use fixed_map the bug was fixed in tkinter version 8.6.
The following code works fine for me using tkinter 8.6 and python 3.8.2 running in Linux.
import tkinter as tk
import tkinter.ttk as ttk
def fixed_map(option):
return [elm for elm in style.map("Treeview", query_opt=option) if elm[:2] != ("!disabled", "!selected")]
root = tk.Tk()
style = ttk.Style()
style.map("Treeview", foreground=fixed_map("foreground"), background=fixed_map("background"))
w = tk.Label(root, text="Hello, world!")
w.pack()
lb= ttk.Treeview(root, columns=['number', 'text'], show="headings", height =20)
lb.tag_configure('odd', background='green')
lb.tag_configure('even', background='lightgreen')
lb.column("number", anchor="center", width=10)
lb.insert('', tk.END, values = ["1","testtext1"], tags=('odd',))
lb.insert('', tk.END, values = ["2","testtext2"], tags=('even',))
lb.insert('', tk.END, values = ["3","testtext3"], tags=('odd',))
lb.insert('', tk.END, values = ["4","testtext4"], tags=('even',))
lb.pack()
root.mainloop()
That answer of Chuck666 did the trick:
https://stackoverflow.com/a/60949800/4352930
This code works
import tkinter as tk
import tkinter.ttk as ttk
def fixed_map(option):
# Returns the style map for 'option' with any styles starting with
# ("!disabled", "!selected", ...) filtered out
# style.map() returns an empty list for missing options, so this should
# be future-safe
return [elm for elm in style.map("Treeview", query_opt=option)
if elm[:2] != ("!disabled", "!selected")]
root = tk.Tk()
style = ttk.Style()
style.map("Treeview",
foreground=fixed_map("foreground"),
background=fixed_map("background"))
w = tk.Label(root, text="Hello, world!")
w.pack()
lb= ttk.Treeview(root, columns=['number', 'text'], show="headings", height =20)
lb.tag_configure('gr', background='green')
lb.column("number", anchor="center", width=10)
lb.insert('',tk.END, values = ["1","testtext1"], tags=('gr',))
lb.insert('',tk.END, values = ["2","testtext2"])
lb.pack()
root.mainloop()
I hope that Chuck666 copies his answer here since I think he has earned the bonus if he shows up.

Why are Menubutton not working in this code?

Found a rather interesting way to create menus in the Tkinter GUI - Menubutton. But unfortunately this code does not work (or rather, when you click on Menubutton the bound Menu does not open):
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.option_add("*Menu.borderWidth", "0")
root.option_add("*Menu.activeBorderWidth", "0")
root.option_add("*Menu.background", "black")
style = ttk.Style(root)
menu = tk.Menu(root)
btn_menu = ttk.Menubutton(root, text='fegvd')
btn_menu.pack()
file = tk.Menu(btn_menu, tearoff=0, foreground='white')
file.add_command(label='ГЫГ')
style.configure('TMenubutton', background='black', foreground='white', indicatoron=0, menu=file, direction='delow', state='active')
root.mainloop()
Although, if I use not ttk.Menubutton, but tk.Menubutton, then everything works:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.option_add("*Menu.borderWidth", "0")
root.option_add("*Menu.activeBorderWidth", "0")
root.option_add("*Menu.background", "black")
menu = tk.Menu(root)
btn_menu = tk.Menubutton(root, text='fegvd')
btn_menu.pack()
file = tk.Menu(btn_menu, tearoff=0, foreground='white')
file.add_command(label='ГЫГ')
btn_menu.configure(background='black', foreground='white', indicator=0, menu=file, state='active')
root.mainloop()
Why? Tell me, please, what is the problem?
You cannot use the style to associate the menu with the menubutton. You need to do it exactly like you do with the tk menu:
btn_menu.configure(menu=file)

ttk Combobox set background colour programatically and dynamically

I have a row of widgets which contains a ttk.Combobox and I want to change the background colour of the widgets in the row when I tick a Checkbutton at the end of the row. With tkinter it is simple just to use configure but with ttk you have to use a theme which seems to be neither dynamic nor specific to a single widget. Is there a way to achieve this functionality ?
Thankyou.
in response to fhdrsdg's comment. I can't get it working but this code demonstrates it
import Tkinter as tk
import ttk
def skillUsed():
if chkUsedVar.get() == 1:
style.map('TCombobox', background=[('readonly','green')])
style.map('TCombobox', foreground=[('readonly','red')])
else:
style.map('TCombobox', background=[('readonly','white')])
style.map('TCombobox', foreground=[('readonly','black')])
root = tk.Tk()
style = ttk.Style()
cboxVar1 = tk.StringVar()
cboxVar1.set("spam")
cboxVar2 = tk.StringVar()
cboxVar2.set("silly")
chkUsedVar = tk.IntVar()
chk = tk.Checkbutton(root, text='Used', variable=chkUsedVar, command=skillUsed)
chk.grid(row=0, column=2)
combo01 = ttk.Combobox(root, values=['spam', 'eric', 'moose'], textvariable=cboxVar1)
combo01['state'] = 'readonly'
combo01.grid(row=0, column=0)
combo02 = ttk.Combobox(root, values=['parrot', 'silly', 'walk'], textvariable=cboxVar2)
combo02['state'] = 'readonly'
combo02.grid(row=0, column=1)
root.mainloop()
When the tick box is clicked the foreground goes red and when unticked it goes black. The issue is the background never changes (but doesn't error) and the style is applied globally to both comboboxes and I want to apply it to a single box.
I have a workaround which I will use just using tkinter's OptionMenu and everything I can find on the tinterweb implies it can't be done with ttk widgets but that seems a bit of a limit to ttk widgets but I have little to no experience with tkinter or ttk.
the workaround is :-
from Tkinter import *
def skillUsed():
if chkUsedVar.get() == 1:
opt01.configure(bg="#000fff000")
opt01.configure(highlightbackground="#000fff000")
opt01.configure(activebackground="#000fff000")
opt01.configure(highlightcolor="#000fff000")
opt01["menu"].configure(bg="#000fff000")
else:
opt01.configure(bg=orgOptbg)
opt01.configure(highlightbackground=orgOpthighlightbackground)
opt01.configure(activebackground=orgOptactivebackground)
opt01.configure(highlightcolor=orgOpthighlightcolor)
opt01["menu"].configure(bg=orgOptmenu)
root = Tk()
optionList = ('parrot','silly','walk')
varopt01 = StringVar()
varopt01.set(optionList[0])
chkUsedVar = IntVar()
opt01 = OptionMenu(root, varopt01, *optionList)
opt01.grid(row=0, column=0)
orgOptbg = opt01.cget("bg")
orgOpthighlightbackground = opt01.cget("highlightbackground")
orgOptactivebackground = opt01.cget("activebackground")
orgOpthighlightcolor = opt01.cget("highlightcolor")
orgOptmenu = opt01["menu"].cget("bg")
chk = Checkbutton(root, text='Used', variable=chkUsedVar, command=skillUsed)
chk.grid(row=0, column=1)
root.mainloop()
Thankyou
First, if you want to apply the style to a single combobox, give it a name like 'custom.TCombobox' so that it inherits from 'TCombobox' but doesn't change the default combobox style. Then all you have to do is set the style of your combobox to 'custom.TCombobox'.
Secondly, the background was not changing because it's the fieldbackground you want to change.
EDIT: What can be customized in a style depends on the ttk theme being used. For instance, the default Mac and Windows themes don't allow much customization and the fieldbackground color of the combobox cannot be changed. However, the 'alt' and 'clam' themes allow more customization.
Here is an example based on your code:
import tkinter as tk
from tkinter import ttk
def skillUsed():
if chkUsedVar.get() == 1:
style.map('custom.TCombobox', fieldbackground=[('readonly','green')])
style.map('custom.TCombobox', foreground=[('readonly','red')])
else:
style.map('custom.TCombobox', fieldbackground=[('readonly','white')])
style.map('custom.TCombobox', foreground=[('readonly','black')])
root = tk.Tk()
style = ttk.Style()
style.theme_use('alt')
cboxVar1 = tk.StringVar()
cboxVar1.set("spam")
cboxVar2 = tk.StringVar()
cboxVar2.set("silly")
chkUsedVar = tk.IntVar()
chk = tk.Checkbutton(root, text='Used', variable=chkUsedVar, command=skillUsed)
chk.grid(row=0, column=2)
combo01 = ttk.Combobox(root, values=['spam', 'eric', 'moose'], textvariable=cboxVar1)
combo01['state'] = 'readonly'
combo01.grid(row=0, column=0)
combo02 = ttk.Combobox(root, values=['parrot', 'silly', 'walk'], textvariable=cboxVar2, style='custom.TCombobox')
combo02['state'] = 'readonly'
combo02.grid(row=0, column=1)
root.mainloop()

Categories