I want to change bg color of tkSimpleDialog to match my system default bg color:
GTK:
tk:
I tried to put config(bg='#CCC9C1') everywhere I can think of, but I managed to make only for some parts from dialog.
Is it possible to change bg color in tkSimpleDialog?
Code sample:
from Tkinter import *
import tkSimpleDialog
class MyDialog(tkSimpleDialog.Dialog):
def body(self, master):
Label(master, text="First:").grid(row=0)
Label(master, text="Second:").grid(row=1)
self.e1 = Entry(master)
self.e2 = Entry(master)
self.e1.grid(row=0, column=1)
self.e2.grid(row=1, column=1)
return self.e1 # initial focus
def apply(self):
first = int(self.e1.get())
second = int(self.e2.get())
print first, second # or something
root = Tk()
root.withdraw()
d = MyDialog(root)
Found way out. As mentioned root.config(...) changes appearance just on root window (side window that we always usually hide). For global settings we are encouraged to use Tk database file (i.e. named optionDB) which has same format as .Xdefaults (X resource database) file. Then we use it in a script like this:
root = Tk()
root.option_readfile('optionDB')
Even better, for some reason discouraged, we can set 'global' settings in a script directly:
root = Tk()
root.option_add('*background', '#CCC9C1')
root.option_add('*Entry*background', '#FFFFFF')
Available keywords are:
*font
*Label*font
*background
*Entry*background
*foreground
*Listbox*foreground
It looks like you may just need to use the tkinter.ttk library, which is the themed version of Tk as shown in this answer. Hope it helps.
Here's the reference for Python 2.x, currently 2.7: http://docs.python.org/library/ttk.html
Related
I'm trying to make a simple outline for a gui, and I'm getting the warning
"variable" May be undefined or defined from star imports: tkinter for all of my variables.
Here is my code:
from tkinter import *
class myApp :
def __init__(self, gui,) :
self.root = gui
self.bframe = Frame(self.root) # Create a container Frame at bottom
self.bframe.pack(side=BOTTOM)
self.xlabel = Label(self.root, text="Item ID") # Create the Label
self.xlabel.pack(side=LEFT)
self.xentry = Entry(self.root, bd=5) # Create the Entry box
self.xentry.pack(side=LEFT)
self.xentry.bind('<Return>', self.showStockItem)
self.xentry.focus_set() # Set focus in the Entry box
self.xopen = Button(self.root, text="Show", command=self.showStockItem) # Create the open Button
self.xopen.pack(side=LEFT)
self.xquit = Button(self.bframe, text="Quit", command=self.quitit) # Create the quit Button
self.xquit.pack(side=BOTTOM)
return
gui = Tk()
gui.title("Travel")
app = myApp(gui)
gui.mainloop()
from tkinter import *
In this line, you import everything from tkinter. This is not recommended, so linter will warn you. But if you really want to do this, it's OK, just ignore it.
To be better, you should explicitly import what you need. For example:
from tkinter import Tk, Label, Frame, Entry, Button
Consider using:
import tkinter as tk
and then, prefix all your calls like:
root = tk.Tk()
or,
variableName.pack(side = tk.LEFT)
and so on...
I am trying to display a tkinter window (with an image,in my case) that doesn't show on the taskbar. I've already tried using the method described here, but the person that answered didn't provide an example so I am unable to replicate it (and I'm using Windows 10 so maybe that is another factor to consider).
My code is here. I am using Python 3.5
from tkinter import Toplevel, Tk, Label, PhotoImage
win = Tk()
win.attributes('-alpha', 0.0)
win.iconify()
window = Toplevel(win)
window.geometry("500x500+100+100")
window.overrideredirect(1)
photo = PhotoImage(file="testfile.png")
label = Label(window, image=photo)
label.pack()
win.mainloop()
The linked question contained an interesting comment recommending to reverse what was done in that other answer. Along with this accepted answer that explains that what is needed is just to set the WS_EX_TOOLWINDOW style, a simple example is:
import tkinter as tk
import tkinter.ttk as ttk
from ctypes import windll
GWL_EXSTYLE=-20
WS_EX_TOOLWINDOW=0x00000080
def set_toolwindow(root):
hwnd = windll.user32.GetParent(root.winfo_id())
style = windll.user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE)
style = style | WS_EX_TOOLWINDOW
res = windll.user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, style)
# re-assert the new window style
root.wm_withdraw()
root.after(10, lambda: root.wm_deiconify())
def main():
root = tk.Tk()
root.wm_title("AppWindow Test")
button = ttk.Button(root, text='Exit', command=lambda: root.destroy())
button.place(x=10,y=10)
#root.overrideredirect(True)
root.after(10, lambda: set_toolwindow(root))
root.mainloop()
if __name__ == '__main__':
main()
How in TTK can I use the OS default loader theme instead of the tkinter one?
This is an example of a normal progress bar.
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry('400x250+1000+300')
progress_bar = Progressbar(root, orient=HORIZONTAL, length=100, mode='indeterminate')
progress_bar.pack(expand=True)
progress_bar.start()
root.mainloop()
I get a progress bar, but it isn't themed like the OS default progress bar is.
I thought that perhaps a style could make it look like that, so I listed the styles:
Style().theme_names() # ('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
I tried each one like so:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry('400x250+1000+300')
os_default_style = Style()
os_default_style.theme_use('THEME')
os_default_style.configure('osdefault.Horizontal.TProgressbar')
progress_bar = Progressbar(root, orient=HORIZONTAL, length=100, mode='indeterminate', style='osdefault.Horizontal.TProgressbar')
progress_bar.pack(expand=True)
progress_bar.start()
root.mainloop()
They produce ones that are similar, but none are the system. How do I make it look exactly like one used by the system?
I think is a little bit case sensitive the "default OS theme"... xpnative is the close to the native one and almost fool the eyes. I created an test to see the differences (note I use windows 7) and the result for default OS style reveal like xpnative is the winner. vista look same but is a little bigger that is all. Now if OS use simple theme, this two will not work, but other will do... For windows 10, classic tkinter theme is close to this OS theme, but tkinter.ttk will do same thing on windows 10... Is to sensitive this subject. Just on windows are some obstacles, I even do not mentioned Linux... Theme is not so important, if your project is making the job right and is close enough to default theme of the user OS from my view point is more than perfect.
Here is my test:
# Import
import tkinter as tk
import tkinter.ttk as ttk
# Logic
class Main:
def __init__(self, master):
self.master = master
# Create the progress bar
self.progress = ttk.Progressbar(self.master, value=0)
self.progress.pack(expand=False, fill="x", side="top", padx=5, pady=5)
self.progress.start()
# Create two layers for the theme
self.default = self.Layer("Default") # for default foundet ones
self.custom = self.Layer("Custom") # for manual input and debug purpose
# Create the entry and applay elements for the "custom layer"
self.entry = ttk.Entry(self.custom)
ttk.Button(self.custom, text="Apply...", width=15, command=lambda:self.ChangeTheme(self.entry.get().strip())
).pack(side="right")
self.entry.pack(expand=True, fill="x", side="left")
# Get a list of all default themes and create a button for each one
for theme in ttk.Style().theme_names(): self.ThemeDefault(theme)
def ThemeDefault(self, themeName:str) -> None:
ttk.Button(self.default, text=themeName, width=15, command=lambda:self.ChangeTheme(themeName)).pack(side="left")
def Layer(self, text:str) -> tk.Frame:
frame = tk.Frame(self.master)
label = tk.Label(frame, text=text, width=7, anchor="w")
frame.pack(expand=False, fill="x", side="top", padx=5, pady=5)
label.pack(side="left")
return frame
def ChangeTheme(self, themeName:str) -> None:
try: ttk.Style(self.master).theme_use(themeName)
except Exception as e: print(f">> EXCEPTION // {e}")
# Run if this file is the main opened one
if __name__ == "__main__":
root = tk.Tk()
Main(root)
root.mainloop()
This is what is look like the resoult.
Unfortunately, a 'truly native' widget is not possible in Tk. As you can see in the source, a theme simply sets a bunch of settings and it does not do anything you couldn't do yourself. However, finding a good theme will generally do a 'good enough' job (see ASI's answer for more details on this).
If you don't believe me, take a look at the ProgressbarDoLayout method (and related methods - found here) and you can see that Tk is handling the drawing itself and giving very little to the native software.
Try this -
from tkinter import *
from tkinter import ttk
root = Tk()
s = ttk.Style()
s.theme_use('winnative')
s.configure("Blue.Horizontal.TProgressbar", foreground='white',
background='blue')
P1 = ttk.Progressbar(root, style="Blue.Horizontal.TProgressbar",
orient="horizontal", length=600, mode="indeterminate",
maximum=4, value=1)
P1.pack()
root.mainloop()
I create a check button / box, with the following call
x=ttk.Checkbutton(tab1,state='disabled',command = lambda j=i,x=k: fCheckButton(j,x))
x.state(['selected'])
The box appears fine and is selected, but it appears on load up, with a black box in it, which seems to have nothing to do with the state of it.
I have looked for reasons why, but can't actually find anyone with the same problem.
thanks
I hit this problem when creating a Checkbutton object from within a class. I was declaring a local variable instead of a member variable in the class. The local variable was getting out of scope causing the checkbox value to not be either a 0 or a 1.
Wrong:
import tkinter as Tk
from tkinter import IntVar
from tkinter.ttk import Frame, Checkbutton
class TestGui(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
var1 = IntVar()
var1.set(1)
button = Checkbutton(parent,
text="Pick me, pick me!",
variable=var1)
button.grid()
root = Tk.Tk()
app = TestGui(root)
root.mainloop()
Fixed:
import tkinter as Tk
from tkinter import IntVar
from tkinter.ttk import Frame, Checkbutton
class TestGui(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.var1 = IntVar()
self.var1.set(1)
button = Checkbutton(parent,
text="Pick me, pick me!",
variable=self.var1) # note difference here
button.grid()
root = Tk.Tk()
app = TestGui(root)
root.mainloop()
I've had a similar issue on Windows 7.
After loading the app, one of my checkbuttons contained a filled square. But after clicking on it, it became a normal checkbutton:
In my case, it was because I had multiple checkbuttons sharing the same variable... After creating a separate Tk.IntVar() variable for each checkbutton, the problem disappeared.
import Tkinter as Tk
import ttk
root = Tk.Tk()
checkVar = Tk.IntVar()
x = ttk.Checkbutton(root, variable=checkVar, text="check 1")
x.pack()
checkVar2 = Tk.IntVar()
y = ttk.Checkbutton(root, variable=checkVar2, text="check 2")
y.pack()
root.mainloop()
I just learned how to use tkinter in Python (3.2.2), and I'm having some problem using the grid manager. When I put button.grid(sticky=SE), for example, the button is not being put in the bottom-right and is just being put in the upper-left, ignoring the sticky value. What am I doing wrong here? I tried to search it but I couldn't really find out what I am doing wrong.
You probably need to set a minimum size for the widget containing the button.
If you don't, the container widget may shrink to occupy only the space required to display the button. If so, the sticky option will be meaningless since the container widget gives no space to show any difference.
For example, using a tk.Frame as the container widget:
import Tkinter as tk
class SimpleApp(object):
def __init__(self, master, **kwargs):
title = kwargs.pop('title')
frame = tk.Frame(master, borderwidth=5, bg = 'cyan', **kwargs)
frame.grid()
button = tk.Button(frame, text = title)
button.grid(sticky = tk.SE)
frame.rowconfigure('all', minsize = 200)
frame.columnconfigure('all', minsize = 200)
def basic():
root = tk.Tk()
app = SimpleApp(root, title = 'Hello, world')
root.mainloop()
basic()
yields
PS. I don't have tkinter installed in Python3.2 so I can't test this, but I think the only change you need to make this work with Python3.2 is
import tkinter as tk
instead of
import Tkinter as tk
When you say "What am I doing wrong here", you need to post your code, otherwise how would anyone be able to guess what's wrong.
The following works fine, placing the button in the lower right corner (SE) of the grid cell - the default is center, not upper left (NW).
from tkinter import Button, Label, Entry, Tk, SE
root = Tk()
Label(text="Lots o' Stuff", width=30, height=15,
borderwidth=2, relief="raised").grid(rowspan=2)
Entry().grid(row=0, column=2)
Button(text="Hit Me").grid(row=1, column=2, sticky=SE)
root.mainloop()