I am trying to make a desktop overlay for windows.
Here is my code:
from tkinter import *
from win32gui import SetWindowPos
from win32con import *
from win32api import Sleep
from threading import Thread
class Desktop:
def Desktop(self):
self.desktoptk = Tk()
tk = self.desktoptk
tk.overrideredirect(True)
tk.geometry(f'{tk.winfo_screenwidth()}x{tk.winfo_screenheight()}+0+0')
def sendtoback():
hwnd = tk.winfo_id()
print(hwnd)
def send():
while True:
Sleep(10)
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE)
Thread(target=send).start()
tk.after(200, sendtoback)
bg = PhotoImage(file=R'data\bg.png')
Bg = Label(image=bg)
Bg.image = bg
Bg.place(x=0, y=0)
tk.mainloop()
Desktop().Desktop()
I didn't found anything in the internet what helps me, and i haven't come up with a solution.
I need to make my window to be always on back (opposite of always on top).
Related
i have a problem in my code in python (tkinter) I have two files (ger_dentista.py) and (ger_paciente.py), each is a window, and I have another file called (main.py) that opens a window with two buttons, I want to click one of the (ger_dentista) files every time Or (ger_paciente) open. the window only opens one time, I'm using linux.
from tkinter import *
from tkinter import ttk
root = Tk()
class funcoes():
def janela2(self):
import ger_dentista
def janela3(self):
import ger_pacientes
class application(funcoes):
def __init__(self):
self.root = root
self.tela()
self.frames_da_tela()
self.widgets_frame()
root.mainloop()
def tela(self):
self.root.title('ODONTO DIGITAL')
self.root.configure(background='#483D8B')
self.root.geometry('800x600')
self.root.resizable(True, True)
self.root.minsize(width=600, height=480)
def frames_da_tela(self):
self.frame_1 = Frame(self.root)
self.frame_1.place(relx= 0.25, rely= 0.25, relwidth= 0.50, relheight= 0.46)
def widgets_frame(self):
self.bt_dentista = Button(self.frame_1, text='Gerenciar dentistas', command=self.janela2)
self.bt_dentista.place(relx=0.3, rely=0.21, relwidth=0.35, relheight=0.12)
self.bt_paciente = Button(self.frame_1, text='Gerenciar pacientes', command=self.janela3)
self.bt_paciente.place(relx=0.3, rely=0.34, relwidth=0.35, relheight=0.12)
self.bt_consulta = Button(self.frame_1, text='Gerenciar Consultas')
self.bt_consulta.place(relx=0.3, rely=0.48, relwidth=0.35, relheight=0.12)
self.bt_sair = Button(self.frame_1, text='Sair')
self.bt_sair.place(relx=0.3, rely=0.62, relwidth=0.35, relheight=0.12)
self.lb_pesquisar = Label(self.frame_1, text='O que deseja fazer?')
self.lb_pesquisar.place(relx=0.32 , rely=0.04)
application()
Use os module to open another script.
Example:
import os
os.startfile('C:/Users/my/Desktop/programming/tkinter/app.py')
#put in brackets your location to script, above location is just to demonstrate
And little coment to your code:
dont use from tkinter import *, use for example import tkinter as tk and if you need widget or something you can use for example from tkinter import Button
The function is copied from Tying to set non-interactable (click-through) overlay with TkInter
Not only is the window not click through, the png is also not transparent.
PNG is here: https://drive.google.com/file/d/1tlLl2hjPq38mc_c_PpMhkKDlP1HqvDY5/view
This is what the window looks like:
What am I missing?
from tkinter import*
import win32gui
from win32gui import GetForegroundWindow, ShowWindow, FindWindow, SetWindowLong, GetWindowLong, SetLayeredWindowAttributes
from win32con import SW_MINIMIZE, WS_EX_LAYERED, WS_EX_TRANSPARENT, GWL_EXSTYLE
def setClickthrough(hwnd):
try:
styles = GetWindowLong(hwnd, GWL_EXSTYLE)
styles |= WS_EX_LAYERED | WS_EX_TRANSPARENT
SetWindowLong(hwnd, GWL_EXSTYLE, styles)
SetLayeredWindowAttributes(hwnd, 0, 255, win32con.LWA_ALPHA)
except Exception as e:
print(e)
root = Tk()
root.geometry("100x100")
root.overrideredirect(1)
root.attributes('-topmost', 1)
pic = PhotoImage(file=r'on2.png')
root.wm_attributes("-transparentcolor", 'white')
boardbutton = Label(root, image=pic, bd=0,
bg='white')
boardbutton.pack()
setClickthrough(root.winfo_id())
root.mainloop()
I have took the code of the linked question and made it work. See code below:
from tkinter import *
from PIL import Image, ImageTk
import win32gui
import win32con
def setClickthrough(hwnd):
print("setting window properties")
try:
styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
win32gui.SetLayeredWindowAttributes(hwnd, 0, 255, win32con.LWA_ALPHA)
except Exception as e:
print(e)
# Dimensions
width = 1920 #self.winfo_screenwidth()
height = 1080 #self.winfo_screenheight()
root = Tk()
root.geometry('%dx%d' % (width, height))
root.title("Applepie")
root.attributes('-transparentcolor', 'white', '-topmost', 1)
root.config(bg='white')
root.attributes("-alpha", 0.25)
root.wm_attributes("-topmost", 1)
bg = Canvas(root, width=width, height=height, bg='white')
setClickthrough(bg.winfo_id())
frame = ImageTk.PhotoImage(file="example.png")
bg.create_image(1920/2, 1080/2, image=frame)
bg.pack()
root.mainloop()
The important difference between your try and the working example seems to be that there was in use the hwnd of a canvas instead of a window.
I'm not abel to do exactly what you wish for but I have provided some code that outputs me this and hopefully sadisfy your needs. The extra code just removes the decoration (overrideredirect(1)) and resizes the window to the img size, also it places it in the middle of the screen.:
from tkinter import *
from PIL import Image, ImageTk
import win32gui
import win32con
def setClickthrough(hwnd):
print("setting window properties")
try:
styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
win32gui.SetLayeredWindowAttributes(hwnd, 0, 255, win32con.LWA_ALPHA)
except Exception as e:
print(e)
def size_position_for_picture():
bbox = bg.bbox(img_id)
w,h = bbox[2]-bbox[0],bbox[3]-bbox[1]
x,y = sw/2-w/2,sh/2-h/2
root.geometry('%dx%d+%d+%d' % (w,h, x,y))
bg.configure(width=w,height=h)
root = Tk()
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
root.overrideredirect(1)
root.attributes("-alpha", 0.75)
root.attributes('-transparentcolor', 'white', '-topmost', 1)
bg = Canvas(root,bg='white',highlightthickness=0)
root.config(bg='white')
setClickthrough(bg.winfo_id())
frame = ImageTk.PhotoImage(file="example.png")
img_id = bg.create_image(0,0, image=frame,anchor='nw')
bg.pack()
size_position_for_picture()
setClickthrough(bg.winfo_id())
root.mainloop()
I have a function doing this for an application of mine as well, the code looks very similar to yours with some minor tweaks. You can try it out:
def set_clickthrough(hwnd, root):
# Get window style and perform a 'bitwise or' operation to make the style layered and transparent, achieving
# the clickthrough property
l_ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
l_ex_style |= win32con.WS_EX_TRANSPARENT | win32con.WS_EX_LAYERED
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, l_ex_style)
# Set the window to be transparent and appear always on top
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(0, 0, 0), 190, win32con.LWA_ALPHA) # transparent
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, root.winfo_x(), root.winfo_y(), 0, 0, 0)
And also, the following function to disable the clickthrough again
def disable_clickthrough(hwnd, root):
# Calling the function again sets the extended style of the window to zero, reverting to a standard window
win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, 0)
# Remove the always on top property again, in case always on top was set to false in options
win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, root.winfo_x(), root.winfo_y(), 0, 0, 0)
You can get the window handle (hwnd) by calling win32gui.FindWindow(None, root.title()).
With dearpygui, I would like to have the main window (the one that contains all the other windows) to always be on top, even if it does not have focus.
Here is what I have so far :
from dearpygui.core import *
from dearpygui.simple import *
with window('MainWindow', width=500, height=500):
add_button('Read screen')
I went with this solution for now. I'll edit my answer if it gets supported by the library. This is a feature in their roadmap for now (see this issue).
from multiprocessing import Process
from time import sleep
import win32con
import win32gui
from dearpygui.core import *
from dearpygui.simple import *
with window('MainWindow', width=500, height=500):
add_button('Read screen')
if __name__ == '__main__':
# you have to make a new process for this in order to be able
# to call win32gui.FindWindow on your displayed window
p = Process(target=start_dearpygui)
p.start()
# sleep for a while to let your window get displayed
sleep(4)
hwnd = win32gui.FindWindow('DearPyGui', None)
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 100, 100, 300, 200, 0)
after going through some stack overflow and external guides still was stuck with an odd problem thread starts but function not executing but used same type of setup in unity c# and visual studio C# windows application but works there fine any help would be appreciated
import tkinter
import threading
import PIL
import time
from datetime import datetime
from PIL import Image
import pyscreenshot as ImageGrab
from tkinter import *
from tkinter import messagebox
from tkinter import Tk, Label, Button, Entry
running=False
class app:
def __init__(self, master):
self.master = master
self.thread1=threading.Thread(target=self.screenshot)
master.title("Screenshot Taker")
Label(master, text="Interval between screenshots").grid(row=0,sticky=W)
self.E1=Spinbox(master, from_ = 5, to = 1000,state = "readonly")
self.E1.grid(row=0,column=2,padx=10)
Label(master, text="File prefix").grid(row=1,sticky=W)
self.E2=Entry(master)
self.E2.grid(row=1,column=2,padx=10)
self.B1=Button(master, text="start" ,command = self.start)
self.B1.grid(row=2,column=0,columnspan=3)
self.B2=Button(master, text="stop" ,command = self.stop)
self.B2.grid(row=2,column=1,columnspan=3)
def screenshot(self):
while(running):
im=ImageGrab.grab()
dt_string = datetime.now().strftime("%d_%m_%Y_%H_%M_%S")
name=str(self.E2.get())+str(dt_string)
logging.debug(name)
im.save(name+".png")
time.sleep(int(self.E1.get()))
def start(self):
running=True
self.thread1.start()
def stop(self):
running=False
self.thread1.join()
root = Tk()
app = app(root)
root.resizable(False, False)
root.mainloop()```
To access a global variable in python, you need to use "global var_name" in each function that needs to access it:
import tkinter
import threading
import PIL
import time
from datetime import datetime
from PIL import Image
import pyscreenshot as ImageGrab
from tkinter import *
from tkinter import messagebox
from tkinter import Tk, Label, Button, Entry
running=False
class app:
def __init__(self, master):
self.master = master
self.thread1=threading.Thread(target=self.screenshot)
master.title("Screenshot Taker")
Label(master, text="Interval between screenshots").grid(row=0,sticky=W)
self.E1=Spinbox(master, from_ = 5, to = 1000,state = "readonly")
self.E1.grid(row=0,column=2,padx=10)
Label(master, text="File prefix").grid(row=1,sticky=W)
self.E2=Entry(master)
self.E2.grid(row=1,column=2,padx=10)
self.B1=Button(master, text="start" ,command = self.start)
self.B1.grid(row=2,column=0,columnspan=3)
self.B2=Button(master, text="stop" ,command = self.stop)
self.B2.grid(row=2,column=1,columnspan=3)
def screenshot(self):
global running
while(running):
im=ImageGrab.grab()
dt_string = datetime.now().strftime("%d_%m_%Y_%H_%M_%S")
name=str(self.E2.get())+str(dt_string)
logging.debug(name)
im.save(name+".png")
time.sleep(int(self.E1.get()))
def start(self):
global running
running=True
self.thread1.start()
def stop(self):
global running
running=False
self.thread1.join()
root = Tk()
app = app(root)
root.resizable(False, False)
root.mainloop()
I created a tkinter frame with menus. The frame contains a button that generates a matplotlib figure window. When the figure window opens, all of the menus for the frame disappear (at least on a mac).
A minimal code example is shown below.
Any ideas would be much appreciated. Thanks!
#!/usr/bin/python
import matplotlib.pyplot as plt
import sys
if sys.version_info[0] < 3:
import Tkinter as tk
else:
import tkinter as tk
class a_window_with_a_menubar:
def __init__(self):
self.root = tk.Tk()
self.new_fig_button = tk.Button(master = self.root, text="Make figure", command = self.make_figure)
self.new_fig_button.grid(row = 0, column = 0, sticky = tk.W)
def make_figure(self):
self.fig1 = plt.figure(facecolor = 'white')
self.ax1 = self.fig1.add_subplot(111)
self.ax1.cla()
plt.show()
win = a_window_with_a_menubar()
tk.mainloop()
Note: the menus disappear whether I use the default tkinter menus or create my own.