Tkinter overridedirect (minimizing and windows task bar issues) - python

What I'm trying to achieve is a Tkinter window, using overridedirect, that show up in your taskbar. You can minimize it like a normal window, and bring it back up like a normal window. The problem that I'm having right now is that I've achieved adding it to the taskbar, but for some reason when you minimize it and then bring it back, it's no longer on the taskbar.
# Imports
from tkinter import *
from ctypes import windll
# Some WindowsOS styles, required for task bar integration
GWL_EXSTYLE = -20
WS_EX_APPWINDOW = 0x00040000
WS_EX_TOOLWINDOW = 0x00000080
def set_appwindow(mainWindow):
# Honestly forgot what most of this stuff does. I think it's so that you can see
# the program in the task bar while using overridedirect. Most of it is taken
# from a post I found on stackoverflow.
hwnd = windll.user32.GetParent(mainWindow.winfo_id())
stylew = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
stylew = stylew & ~WS_EX_TOOLWINDOW
stylew = stylew | WS_EX_APPWINDOW
res = windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, stylew)
# re-assert the new window style
mainWindow.wm_withdraw()
mainWindow.after(10, lambda: mainWindow.wm_deiconify())
def main():
global mainWindow
# Default window configuration
mainWindow = Tk()
mainWindow.geometry('800x400')
mainWindow.resizable(width=False, height=False)
mainWindow.overrideredirect(True)
mainWindow.after(10, lambda: set_appwindow(mainWindow))
def exitGUI():
mainWindow.destroy()
def minimizeGUI():
mainWindow.state('withdrawn')
mainWindow.overrideredirect(False)
mainWindow.state('iconic')
def frameMapped(event=None):
mainWindow.overrideredirect(True)
mainWindow.state("normal")
mainWindow.iconbitmap("ANALOG.ico")
exitButton = Button(mainWindow, text='', bg='#212121', fg='#35DAFF',
command=exitGUI)
minimizeButton = Button(mainWindow, text='', bg="#212121", fg='#35DAFF',
command=minimizeGUI)
exitButton.place(x=780, y=0)
minimizeButton.place(x=759, y=0)
mainWindow.bind("<Map>", frameMapped) # This brings back the window
mainWindow.mainloop() # Window Loop
if __name__ == '__main__':
main()

Okay guys, I finally figured it out.
# Imports
from tkinter import *
from ctypes import windll
# Some WindowsOS styles, required for task bar integration
GWL_EXSTYLE = -20
WS_EX_APPWINDOW = 0x00040000
WS_EX_TOOLWINDOW = 0x00000080
lastClickX = 0
lastClickY = 0
def SaveLastClickPos(event):
global lastClickX, lastClickY
lastClickX = event.x
lastClickY = event.y
def Dragging(event):
x, y = event.x - lastClickX + mainWindow.winfo_x(), event.y - lastClickY + mainWindow.winfo_y()
mainWindow.geometry("+%s+%s" % (x , y))
def set_appwindow(mainWindow):
# Honestly forgot what most of this stuff does. I think it's so that you can see
# the program in the task bar while using overridedirect. Most of it is taken
# from a post I found on stackoverflow.
hwnd = windll.user32.GetParent(mainWindow.winfo_id())
stylew = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
stylew = stylew & ~WS_EX_TOOLWINDOW
stylew = stylew | WS_EX_APPWINDOW
res = windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, stylew)
# re-assert the new window style
mainWindow.wm_withdraw()
mainWindow.after(10, lambda: mainWindow.wm_deiconify())
def main():
global mainWindow, z
# Default window configuration
mainWindow = Tk()
mainWindow.geometry('800x400')
mainWindow.resizable(width=False, height=False)
mainWindow.overrideredirect(True)
mainWindow.after(10, lambda: set_appwindow(mainWindow))
mainWindow.bind('<Button-1>', SaveLastClickPos)
mainWindow.bind('<B1-Motion>', Dragging)
z = 0
def exitGUI():
mainWindow.destroy()
def minimizeGUI():
global z
mainWindow.state('withdrawn')
mainWindow.overrideredirect(False)
mainWindow.state('iconic')
z = 1
def frameMapped(event=None):
global z
mainWindow.overrideredirect(True)
mainWindow.iconbitmap("ANAL_OG.ico")
if z == 1:
set_appwindow(mainWindow)
z = 0
exitButton = Button(mainWindow, text='', bg='#212121', fg='#35DAFF',
command=exitGUI)
minimizeButton = Button(mainWindow, text='', bg="#212121", fg='#35DAFF',
command=minimizeGUI)
exitButton.place(x=780, y=0)
minimizeButton.place(x=759, y=0)
mainWindow.bind("<Map>", frameMapped) # This brings back the window
mainWindow.mainloop() # Window Loop
if __name__ == '__main__':
main()
Thanks for all your suggestions!

Related

How to save drawing on canvas as png file (linux)?

I am creating a painting application and I want to save my drawing on canvas widget as png file on my computer. This is my code:
from tkinter import *
from tkinter.filedialog import *
from functools import partial
from tkinter import Menu
from tkinter import filedialog,messagebox
from PIL import Image
from tkinter.colorchooser import askcolor
import pyscreenshot as ImageGrab
import pyautogui
class PaintingApp:
x=y=None
def __init__(self,window):
self.window = window
self.upper_frame = Frame(window)
self.upper_frame.grid(row=0,column=0, padx=10, pady=5,sticky="ew")
self.lower_frame = Frame(window)
self.lower_frame.grid(row=2, column=0, padx=10, pady=5,sticky="ew")
self.canvas= Canvas(self.lower_frame,width=500,height=530,bg="white")
self.canvas.grid()
self.objects = [] #objects on canvas
self.pen_size = 2
self.pcolor = "black"
self.pen = Button(self.upper_frame,text="Pen",command=partial(self.pen_draw,thickness=self.pen_size))
self.pen.grid(row=0,column=3,padx=(10,160))
self.bg = Button(self.upper_frame,text="Background",command= self.bgcolor) #change bg color
self.bg.grid(row=2,column=1,padx=(100,10))
self.upper_menu()
self.canvas.bind("<Button-1>", self.get_x_and_y)
self.canvas.bind("<B1-Motion>", lambda event, b=self.pen_size: self.pen_draw(b,event))
self.im = None
def save_pic(self,event=None):
file = asksaveasfilename(defaultextension=".png")
x = self.canvas.winfo_rootx() + self.canvas.winfo_x()
y = self.canvas.winfo_rooty() + self.canvas.winfo_y()
x1 = x + self.canvas.winfo_width()
y1 = y + self.canvas.winfo_height()
self.im=ImageGrab.grab(bbox=(x,y,x1,y1))
self.im.save(file[19:])
def pen_color(self,color):
self.pcolor= color
def get_x_and_y(self,event):
global x,y
x, y = event.x, event.y
def pen_draw(self,thickness,event=None):
global x,y
self.canvas.bind("<Button-1>", self.get_x_and_y) # Bind to pen_draw function
self.canvas.bind("<B1-Motion>", lambda event, b=self.pen_size: self.pen_draw(b,event))
if event != None:
self.objects.append(self.canvas.create_line((x, y, event.x, event.y), fill=self.pcolor,width=self.pen_size,capstyle=ROUND,smooth=True))
x, y = event.x, event.y
def upper_menu(self):
self.menubar = Menu(window)
self.menu1 = Menu(self.menubar, tearoff=0)
self.menu1.add_command(label="Save pic", command=self.save_pic)
self.menu1.add_separator()
self.menu1.add_command(label="Exit", command=window.destroy)
self.menubar.add_cascade(label="Settings", menu=self.menu1)
self.menu2 = Menu(self.menubar, tearoff=0)
self.menu2.add_command(label="Open pic")
self.menubar.add_cascade(label="Image", menu=self.menu2)
self.window.config(menu=self.menubar)
def bgcolor(self):
chosen_color = askcolor(color=self.canvas["bg"])[1]
self.canvas.configure(bg=chosen_color)
window = Tk()
window.geometry("500x450")
p = PaintingApp(window)
window.mainloop()
Now I have tried many many codes but it won't work. The code I provided above saves an all black picture which does not make any sense. I have tried using the module pyautogui as well but I still get the same result.
def save_pic(self,event=None):
file = asksaveasfilename(defaultextension=".png")
x = self.canvas.winfo_rootx() + self.canvas.winfo_x()
y = self.canvas.winfo_rooty() + self.canvas.winfo_y()
x1 = x + self.canvas.winfo_width()
y1 = y + self.canvas.winfo_height()
self.im=pyautogui.screenshot(region=(x,y,x1,y1))
self.im.save(file[19:])
If you use a screen shot library, you should wait until the backend UI framework(X11 in your case) finishes the drawing. Also you can use the PIL.ImageGrab.grab() in Pillow instead of pyscreenshot.
So do like this.(I fixed several errors in the original example, such as an incorrect path.)
...
from PIL import ImageGrab
...
class PaintingApp:
...
def save_pic(self,event=None):
file = asksaveasfilename(defaultextension=".png")
def grab_and_save():
x = self.canvas.winfo_rootx()
y = self.canvas.winfo_rooty()
x1 = x + self.canvas.winfo_width()
y1 = y + self.canvas.winfo_height()
self.im = ImageGrab.grab(bbox=(x,y,x1,y1))
self.im.save(file)
self.window.update()
self.window.after(1000, grab_and_save) # This waits 1000ms.
...
...
A better method will be to install Tkimg and export the bitmap on the canvas directly, but it will need some hard work. You can start with an unmaintained project, python-tkimg.

how to disable a second window?

So I'm just trying to create a window with a shadow. I want to move both windows at the same time. so far it works. however, when i click on the edge, the "shadow" window comes to the fore. is there a possibility to leave the second window permanently in the background?
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class CFrame(Tk):
def __init__(self, parent=None, bg="#1b1e21", bd=1, bdcolor="lime"):
super().__init__(parent)
self.bg = bg
self.bd = bd
self.bdcolor = bdcolor
self.title("CFrame")
self.geometry("740x740+200+200")
self.overrideredirect(1)
self.bind("<B1-Motion>", self.dragWindow)
self.bind("<Button-1>", self.clickWindow)
self.shadow = Shadow()
self.headingFrame = Frame(self, bg="lime")
self.headingFrame.pack(fill="x")
self.mainFrame = Frame(self, bg=self.bg, highlightthickness=bd,
highlightbackground=self.bdcolor, highlightcolor=self.bdcolor)
self.mainFrame.pack(fill="both", expand="yes")
self.exitButton = ttk.Button(self.headingFrame, text="\u2613", command=self.programQuit)
self.exitButton.pack(side="right")
self.offSetX = 0
self.offSetY = 0
def dragWindow(self, event):
x = self.winfo_pointerx() - self.offSetX
y = self.winfo_pointery() - self.offSetY
x2 = self.winfo_pointerx() - self.offSetX - 10
y2 = self.winfo_pointery() - self.offSetY - 10
self.geometry("+%d+%d" % (x,y))
self.shadow.geometry("+%d+%d" % (x2,y2))
def clickWindow(self, event):
self.offSetX = event.widget.winfo_rootx() - self.winfo_rootx() + event.x
self.offSetY = event.widget.winfo_rooty() - self.winfo_rooty() + event.y
def programQuit(self):
ex = messagebox.askyesno("Quit?", "Quit?")
if ex == 1:
self.destroy()
class Shadow(Tk):
def __init__(self):
super().__init__()
self.title("Shadow")
self.geometry("760x760+190+190")
self.overrideredirect(1)
self.attributes("-alpha", 0.3)
self.bg = Frame(self, bg="black")
self.bg.pack(fill="both", expand="yes")
if __name__ == '__main__':
cf = CFrame()
cf.mainloop()
maybe a little bit too much code, but i think you can it imagn better with the whole example
I already did something like this here. It works by binding to "<FocusIn>" on your dummy shadow window and calling .focus_force() on the main window. Like this:
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class CFrame(tk.Tk):
def __init__(self, bg="#1b1e21", bd=1, bdcolor="lime"):
super().__init__()
self.bg = bg
self.bd = bd
self.bdcolor = bdcolor
super().geometry("740x740+200+200")
super().overrideredirect(True)
super().bind("<B1-Motion>", self.drag_window)
super().bind("<Button-1>", self.click_window)
self.shadow = Shadow()
self.heading_frame = tk.Frame(self, bg="lime")
self.heading_frame.pack(fill="x")
self.main_frame = tk.Frame(self, bg=self.bg, highlightthickness=bd,
highlightbackground=self.bdcolor,
highlightcolor=self.bdcolor)
self.main_frame.pack(fill="both", expand="yes")
self.exit_button = ttk.Button(self.heading_frame, text="\u2613",
command=self.program_quit)
self.exit_button.pack(side="right")
self.offset_x = 0
self.offset_y = 0
self.shadow.bind("<FocusIn>", self.focus_main)
def focus_main(self, event):
super().focus_force()
def drag_window(self, event):
x = self.winfo_pointerx() - self.offset_x
y = self.winfo_pointery() - self.offset_y
x2 = self.winfo_pointerx() - self.offset_x - 10
y2 = self.winfo_pointery() - self.offset_y - 10
super().geometry("+%d+%d" % (x,y))
self.shadow.geometry("+%d+%d" % (x2,y2))
def click_window(self, event):
self.offset_x = event.widget.winfo_rootx() - self.winfo_rootx() + event.x
self.offset_y = event.widget.winfo_rooty() - self.winfo_rooty() + event.y
def program_quit(self):
result = messagebox.askyesno("Quit?", "Are you sure you want to quit?")
if result:
super().destroy()
self.shadow.destroy()
class Shadow(tk.Tk):
def __init__(self):
super().__init__()
super().geometry("760x760+190+190")
super().overrideredirect(True)
super().attributes("-alpha", 0.3)
super().config(bg="black")
if __name__ == "__main__":
cf = CFrame()
cf.mainloop()
Also I removed the frame from the shadow window and replaced it with <tkinter.Tk>.config(bg="black").
Another thing: Is there a point to calling .title(...) when you are going to use .overrideredirect(True)?

Pygame & Tkinter Musikplayer

Please can you help me I don't know what´s the problem.
This is the Error:
[Running] python -u "c:\Users\Leon\Desktop\Page Guis\Music Player Pro ++\unknown.py"
File "c:\Users\Leon\Desktop\Page Guis\Music Player Pro ++\unknown.py", line 49
mixer.music.play()
^
TabError: inconsistent use of tabs and spaces in indentation
[Done] exited with code=1 in 0.651 seconds
My code:
# -*- coding: utf-8 -*-
from pygame import mixer
import tkinter.filedialog
import sys
try:
import tkinter as tk
except ImportError:
import tkinter as tk
try:
import tkinter.ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import unknown_support
mixer.init()
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
unknown_support.init(root, top)
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
unknown_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
def load_song():
mixer.music.load(tk.filedialog.askopenfile())
mixer.music.play()
def pause_song():
mixer.music.pause()
def resume():
mixer.music.unpause()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x430+314+157")
top.minsize(120, 1)
top.maxsize(1370, 729)
top.resizable(1, 1)
top.title("Musik Player Pro ++")
top.configure(relief="groove")
top.configure(background="#000000")
top.configure(highlightbackground="#d9d9d9")
top.configure(highlightcolor="black")
self.menubar = tk.Menu(top,font="TkMenuFont",bg=_bgcolor,fg=_fgcolor)
top.configure(menu = self.menubar)
self.Canvas1 = tk.Canvas(top)
self.Canvas1.place(relx=0.867, rely=0.116, relheight=0.658
, relwidth=0.122)
self.Canvas1.configure(background="#000000")
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(highlightbackground="#d9d9d9")
self.Canvas1.configure(highlightcolor="black")
self.Canvas1.configure(insertbackground="#4fff53")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="#48ffff")
self.Canvas1.configure(selectforeground="white")
self.Label1 = tk.Label(top)
self.Label1.place(relx=0.667, rely=0.023, height=41, width=194)
self.Label1.configure(activebackground="#f9f9f9")
self.Label1.configure(activeforeground="black")
self.Label1.configure(background="#000000")
self.Label1.configure(disabledforeground="#a3a3a3")
self.Label1.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -slant italic -underline 1")
self.Label1.configure(foreground="#ffffff")
self.Label1.configure(highlightbackground="#d9d9d9")
self.Label1.configure(highlightcolor="black")
self.Label1.configure(text='''Volume''')
self.Scale1 = tk.Scale(top, from_=0.0, to=100.0)
self.Scale1.place(relx=0.767, rely=0.116, relwidth=0.0, relheight=0.665
, width=45, bordermode='ignore')
self.Scale1.configure(activebackground="#ececec")
self.Scale1.configure(background="#000000")
self.Scale1.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -underline 1")
self.Scale1.configure(foreground="#ffffff")
self.Scale1.configure(highlightbackground="#d9d9d9")
self.Scale1.configure(highlightcolor="black")
self.Scale1.configure(label="Volume")
self.Scale1.configure(relief="groove")
self.Scale1.configure(troughcolor="#d9d9d9")
self.tooltip_font = "TkDefaultFont"
self.Scale1_tooltip = \
ToolTip(self.Scale1, self.tooltip_font, '''Volume + / -''')
self.Label1_2 = tk.Label(top)
self.Label1_2.place(relx=0.017, rely=0.023, height=41, width=194)
self.Label1_2.configure(activebackground="#f9f9f9")
self.Label1_2.configure(activeforeground="black")
self.Label1_2.configure(anchor='w')
self.Label1_2.configure(background="#000000")
self.Label1_2.configure(compound='left')
self.Label1_2.configure(disabledforeground="#a3a3a3")
self.Label1_2.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -slant italic -underline 1")
self.Label1_2.configure(foreground="#ffffff")
self.Label1_2.configure(highlightbackground="#d9d9d9")
self.Label1_2.configure(highlightcolor="black")
self.Label1_2.configure(text='''Now playing:''')
self.Label2 = tk.Label(top)
self.Label2.place(relx=0.267, rely=0.279, height=101, width=164)
self.Label2.configure(activebackground="#f9f9f9")
self.Label2.configure(activeforeground="black")
self.Label2.configure(background="#000000")
self.Label2.configure(disabledforeground="#a3a3a3")
self.Label2.configure(font="-family {Segoe UI Black} -size 15 -weight bold -slant italic -underline 1")
self.Label2.configure(foreground="#ffffff")
self.Label2.configure(highlightbackground="#d9d9d9")
self.Label2.configure(highlightcolor="black")
self.Label2.configure(text='''Track Name''')
self.Button1 = tk.Button(top)
self.Button1.place(relx=0.017, rely=0.837, height=64, width=187)
self.Button1.configure(activebackground="#ffffff")
self.Button1.configure(activeforeground="#000000")
self.Button1.configure(background="#000000")
self.Button1.configure(cursor="fleur")
self.Button1.configure(disabledforeground="#a3a3a3")
self.Button1.configure(foreground="#ffffff")
self.Button1.configure(highlightbackground="#d9d9d9")
self.Button1.configure(highlightcolor="black")
self.Button1.configure(pady="0")
self.Button1.configure(relief="groove")
self.Button1.configure(text='''Resume''')
self.Button1.configure(command=resume)
self.Button1_1 = tk.Button(top)
self.Button1_1.place(relx=0.35, rely=0.837, height=64, width=187)
self.Button1_1.configure(activebackground="#ffffff")
self.Button1_1.configure(activeforeground="#000000")
self.Button1_1.configure(background="#000000")
self.Button1_1.configure(disabledforeground="#a3a3a3")
self.Button1_1.configure(foreground="#ffffff")
self.Button1_1.configure(highlightbackground="#d9d9d9")
self.Button1_1.configure(highlightcolor="black")
self.Button1_1.configure(pady="0")
self.Button1_1.configure(relief="groove")
self.Button1_1.configure(text='''Pause''')
self.Button1_1.configure(command=pause_song)
self.Button1_1_1 = tk.Button(top)
self.Button1_1_1.place(relx=0.683, rely=0.837, height=64, width=187)
self.Button1_1_1.configure(activebackground="#ffffff")
self.Button1_1_1.configure(activeforeground="#000000")
self.Button1_1_1.configure(background="#000000")
self.Button1_1_1.configure(disabledforeground="#a3a3a3")
self.Button1_1_1.configure(foreground="#ffffff")
self.Button1_1_1.configure(highlightbackground="#d9d9d9")
self.Button1_1_1.configure(highlightcolor="black")
self.Button1_1_1.configure(pady="0")
self.Button1_1_1.configure(relief="groove")
self.Button1_1_1.configure(text='''Load Song''')
self.Button1_1_1.configure(command=load_song)
from time import time, localtime, strftime
class ToolTip(tk.Toplevel):
"""
Provides a ToolTip widget for Tkinter.
To apply a ToolTip to any Tkinter widget, simply pass the widget to the
ToolTip constructor
"""
def __init__(self, wdgt, tooltip_font, msg=None, msgFunc=None,
delay=0.5, follow=True):
"""
Initialize the ToolTip
Arguments:
wdgt: The widget this ToolTip is assigned to
tooltip_font: Font to be used
msg: A static string message assigned to the ToolTip
msgFunc: A function that retrieves a string to use as the ToolTip text
delay: The delay in seconds before the ToolTip appears(may be float)
follow: If True, the ToolTip follows motion, otherwise hides
"""
self.wdgt = wdgt
# The parent of the ToolTip is the parent of the ToolTips widget
self.parent = self.wdgt.master
# Initalise the Toplevel
tk.Toplevel.__init__(self, self.parent, bg='black', padx=1, pady=1)
# Hide initially
self.withdraw()
# The ToolTip Toplevel should have no frame or title bar
self.overrideredirect(True)
# The msgVar will contain the text displayed by the ToolTip
self.msgVar = tk.StringVar()
if msg is None:
self.msgVar.set('No message provided')
else:
self.msgVar.set(msg)
self.msgFunc = msgFunc
self.delay = delay
self.follow = follow
self.visible = 0
self.lastMotion = 0
# The text of the ToolTip is displayed in a Message widget
tk.Message(self, textvariable=self.msgVar, bg='#FFFFDD',
font=tooltip_font,
aspect=1000).grid()
# Add bindings to the widget. This will NOT override
# bindings that the widget already has
self.wdgt.bind('<Enter>', self.spawn, '+')
self.wdgt.bind('<Leave>', self.hide, '+')
self.wdgt.bind('<Motion>', self.move, '+')
def spawn(self, event=None):
"""
Spawn the ToolTip. This simply makes the ToolTip eligible for display.
Usually this is caused by entering the widget
Arguments:
event: The event that called this funciton
"""
self.visible = 1
# The after function takes a time argument in milliseconds
self.after(int(self.delay * 1000), self.show)
def show(self):
"""
Displays the ToolTip if the time delay has been long enough
"""
if self.visible == 1 and time() - self.lastMotion > self.delay:
self.visible = 2
if self.visible == 2:
self.deiconify()
def move(self, event):
"""
Processes motion within the widget.
Arguments:
event: The event that called this function
"""
self.lastMotion = time()
# If the follow flag is not set, motion within the
# widget will make the ToolTip disappear
#
if self.follow is False:
self.withdraw()
self.visible = 1
# Offset the ToolTip 10x10 pixes southwest of the pointer
self.geometry('+%i+%i' % (event.x_root+20, event.y_root-10))
try:
# Try to call the message function. Will not change
# the message if the message function is None or
# the message function fails
self.msgVar.set(self.msgFunc())
except:
pass
self.after(int(self.delay * 1000), self.show)
def hide(self, event=None):
"""
Hides the ToolTip. Usually this is caused by leaving the widget
Arguments:
event: The event that called this function
"""
self.visible = 0
self.withdraw()
def update(self, msg):
"""
Updates the Tooltip with a new message. Added by Rozen
"""
self.msgVar.set(msg)
# ===========================================================
# End of Class ToolTip
# ===========================================================
if __name__ == '__main__':
vp_start_gui()
HERE IS THE ERROR PICTURE:
https://i.stack.imgur.com/eAs6q.png
https://i.stack.imgur.com/7qwDf.png
Thanks
Don't use a mix of tabs and space for indentation, it's not considered a good practice (python specific).
Now to fix it:
Go to terminal and type pip install autopep8
Once it's installed type the following command :
autopep8 -i yourfilename.py
3)You're good to go now!

How to execute a subprocess with multithreading

This program works and displays server latency on a small canvas, but because it takes the program time to ping the server and display the ping def display():, it is not possible to drag the window class WindowDraggable():, until the subprocess has finished, and thus there is lag when dragging the window. Can this lag be resolved with mutil-threading so the window can be dragged smoothly?
from tkinter import *
from PIL import ImageTk, Image
import subprocess
import _thread
host = "141.101.115.212" #host IP address
root = Tk()
root.overrideredirect(1)
im = Image.open("image.png")
width, height = im.size
canvas = Canvas(root, width=width, height=height)
canvas.pack()
image = ImageTk.PhotoImage(file="image.png")
canvas.create_image(0, 0, image=image, anchor=NW)
text = canvas.create_text(125, 75, anchor=CENTER)
def display():
global text
#Launches 'command' windowless and waits until finished; finds ping
suinfo = subprocess.STARTUPINFO()
suinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
x = subprocess.Popen(["ping.exe", "141.101.115.212"], stdout=subprocess.PIPE, startupinfo=suinfo)
#find latency with regex
x = str(x.communicate()[0])
lhs, rhs = x.split("Average = ")
lhs, rhs = rhs.split("\\", 1)
lhs, rhs = lhs.split("m")
if int(lhs) > 999:
lhs = "999" + "ms"
latency = lhs
canvas.itemconfig(text, text=latency, width=width)
canvas.itemconfig(text, font=("courier", 25, "bold"))
canvas.itemconfig(text, fill="white")
root.after(1000, display)
class WindowDraggable():
def __init__(self, label):
self.label = label
label.bind('<ButtonPress-1>', self.StartMove)
label.bind('<ButtonRelease-1>', self.StopMove)
label.bind('<B1-Motion>', self.OnMotion)
def StartMove(self, event):
self.x = event.x
self.y = event.y
def StopMove(self, event):
self.x = None
self.y = None
def OnMotion(self,event):
x = (event.x_root - self.x - self.label.winfo_rootx() + self.label.winfo_rootx())
y = (event.y_root - self.y - self.label.winfo_rooty() + self.label.winfo_rooty())
root.geometry("+%s+%s" % (x, y))
label = Label(root, text='drag me')
WindowDraggable(label)
label.pack()
#_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
root.after(0, display())
root.mainloop()
Rather than try to fight Tkinter's builtin loop/threading, use it:
def wait_for_it(proc):
proc.poll()
if proc.returncode is None: # subprocess hasn't finished yet
root.after(100, lambda: wait_for_it(proc)) # register a callback for 100ms
else:
display(proc.communicate()[0])
def display(x):
lhs, rhs = x.split("Average = ")
# the rest of your code goes here...
# instead of root.after(0, display)
wait_for_it(subprocess.Popen(['ping', 'google.com']))
As a slight aside, I highly recommend pasting your code on the Code Review Stack Exchange to get some style pointers and help simplifying it.

Python Tkinter Custom Window

I have this simple Tkinter Custom Window. I am a beginner and only learnt tkinter a few months ago. I have no experience in real software development. So, I would like to know if the way it was coded is acceptable? I know that when i say acceptable , it could mean a lot of things. I just want to know what are the things i should improve in my coding style & the way i think?
import Tkinter as tk
''' Creating Tkinter Tk instance '''
class Application(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.bind("<ButtonPress-1>", self.StartMove)
self.bind("<ButtonRelease-1>", self.StopMove)
self.bind("<B1-Motion>", self.OnMotion)
self.Init()
self.Layout()
self.AddButtons()
''' Setting Main Tk window size & styles '''
def Init(self):
self.geometry("1280x700+0+0")
self.overrideredirect(True)
self['background'] = '#201F29'
self['highlightthickness'] = 2
self['relief'] = 'groove'
'''Layout of the Tk window'''
def Layout(self):
self.exitmenu = tk.Frame(self)
self.exitmenu.place(x = 1217, y = 0)
self.container = tk.Frame(self,width = 1268,height = 648 , relief = 'flat',bd = 0)
self.container.place(x = 5,y = 40)
''' Adding Exit button and Minimize button to the Tk window'''
def AddButtons(self):
self.minibutton = tk.Button(self.exitmenu,text = '0',font=('webdings',8,'bold'),relief = 'flat' , command = self.minimize )
self.minibutton.pack(side = 'left')
self.exitbutton = tk.Button(self.exitmenu,text = 'r',font=('webdings',8),relief = 'flat' ,bg = '#DB6B5A', command = self.destroy )
self.exitbutton.pack(side = 'left')
def minimize(self):
self.overrideredirect(False)
self.wm_state('iconic')
self.overrideredirect(True)
'''Methods for moving window frame'''
def StartMove(self, event):
self.x = event.x
self.y = event.y
def StopMove(self, event):
self.x = None
self.y = None
def OnMotion(self, event):
x1 = self.x
y1 = self.y
x2 = event.x
y2 = event.y
deltax = x2 - x1
deltay = y2 - y1
a = self.winfo_x() + deltax
b = self.winfo_y() + deltay
self.geometry("+%s+%s" % (a, b))
def Main():
app = Application()
app.mainloop()
if __name__ == "__main__":
Main()
Read PEP-8 Install and run one or all of PEP8 checker, pyFlakes, pyChecker, pylint.
The first thing that stands out is that docstrings are supposed to be within the function rather than before it - then they become a part of the function code and can be accessed by help.

Categories