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()
Related
So, i've been learning a bit of tkinter and i've just found out that some things like buttons work differently from windows to linux... On windows everything works fine but on linux, when i over the button (with an image) it glows and, honestly, i can't figure out how to fix this.
from tkinter import *
import tkinter as tk
import PySimpleGUI as sg
root = tk.Tk()
root.title("Test")
root.geometry("500x500")
close_icon = PhotoImage(file='assets/Close Button.png')
close_button = tk.Button(root, image=close_icon, command=root.destroy, borderwidth=0)
close_button.pack()
if __name__ == "__main__":
root.mainloop()
What it should always look like:
What it looks like when i hover it:
Try to set option activebackground to be the same background color of the window.
color = root.cget("background")
close_button.configure(activebackground=color)
I'm a Python beginner that trying to learn my way through Tkinter, and I need your help.
Let say I create a simple button like this:
import tkinter as tk
window = tk.Tk()
button = tk.Button(text="Hello World!")
button.pack()
window.mainloop()
Is there a way that I can hide and then display the text again? Given that I can create two more buttons that will do the job of hiding and displaying. I have tried to use button.pack_forget(), but it will hide the entire button instead.
Any help would be appreciated.
To make it look like the buttons text vanishes,you can make the text color as same as the background color via cget method.
import tkinter as tk
def hide_text():
color = button['bg']
button.config(foreground=color, activeforeground=color)
window = tk.Tk()
button = tk.Button(text="Hello World!",command=hide_text)
button.pack()
window.mainloop()
Approach 2 ttk.Button:
import tkinter as tk
from tkinter import ttk
def hide_text():
button.config(text='')
window = tk.Tk()
button = ttk.Button(text="Hello World!",width=100,command=hide_text)
button.pack()
window.mainloop()
Approach3 using style:
import tkinter as tk
from tkinter import ttk
def change_button_style(event):
widget = event.widget
if widget['style'] == 'TButton':
widget.configure(style='VanishedText.TButton')
else:
event.widget.config(style='TButton')
BACKGROUND = '#f0f0f0'
FOREGROUND = '#000000'
window = tk.Tk()
window.configure(bg=BACKGROUND)
style = ttk.Style()
style.theme_use('default')
button = ttk.Button(text="Hello World!",style='VanishedText.TButton')
button.bind('<ButtonPress-1>',change_button_style)#,command=change_button_style
button.pack()
style.map('VanishedText.TButton',
foreground =[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)],
background =[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)],
focuscolor=[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)])
window.mainloop()
You Can Simply Config And Set Text :
import tkinter as tk
from tkinter import ttk
win=tk.Tk()
def hidetext():
button.config(text="")
button=ttk.Button(win,text="FooBar",command=hidetext)
button.pack()
win.mainloop()
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...
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'm experimenting with the new ttk Tile enhancements that ship with Python 2.7.
Windows 7: The code below demonstrates how the combobox dropdown shows up BEHIND our root window when the root window is configured as a topmost window ("always on top"). If you comment out the line """ root.attributes( '-topmost', 1 )""" then the combobox dropdown appears within the root window (as expected).
Anyone have any workarounds for this behavior so we can use comboboxes with 'topmost' windows?
# sample code that illustrates problem described above
import Tkinter as tkinter
import ttk
root = tkinter.Tk()
panelCombo = ttk.Frame( root )
panelCombo.pack( side='top', fill='x', padx=12, pady=8 )
valCombo = ( 'cat', 'dog', 'pig' )
varCombo = tkinter.StringVar()
varCombo.set( 'fish' )
cboCombo = ttk.Combobox( panelCombo, values=valCombo, textvariable=varCombo )
cboCombo.pack( side='left', anchor='w', padx=12, pady=8 )
# make our window 'alwaysontop'
root.attributes( '-topmost', 1 )
root.mainloop()
That's a known bug in the Tk toolkit. It was fixed in release 8.5.6. Maybe you just need to wait until that release makes its way into Python.