1

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

fingletoe
  • 67
  • 2
  • 9

1 Answers1

1

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()
j_4321
  • 15,431
  • 3
  • 34
  • 61
  • Thanks j_4321 - it kinda works - it doesn't work on windows 10 in python2.7 or 3.6 (just changed the imports) it effects just one box as you say but the fieldbackground doesn't change it stays white but the text does change. I then tried it on a debian 9 box and it does works as intended background green and text red (python 2.7) is there something I need to do to get it working in windows ? – fingletoe Jun 14 '18 at 07:34
  • 1
    Found https://stackoverflow.com/questions/42481707/can-i-change-the-color-of-python-ttk-combobox-under-windows Which hasn't been answered and is over a year old so not looking good for a windows solution :( – fingletoe Jun 14 '18 at 09:07
  • 1
    Got it working by adding style.theme_use("alt") after the style is defined - alters the look and feel a bit but works :) thankyou j_4231 – fingletoe Jun 14 '18 at 09:19
  • @fingletoe I am using linux so I forgot to mention the restrictions of windows default theme. I have added the theme change my answer so that other people won't have the same problem. – j_4321 Jun 14 '18 at 18:48