I wish to take screenshot of python tkinter window (NOT the entire computer scrren). I applied following codes:
import pyautogui
import tkinter as tk
root= tk.Tk()
# Define tkinter window
canvas1 = tk.Canvas(root, width = 300, height = 300)
canvas1.pack()
# Define fuction to take screenshot
def takeScreenshot ():
myScreenshot = pyautogui.screenshot()
myScreenshot.save('screenshot.png')
# Define fuction to take screenshot
myButton = tk.Button(text='Take Screenshot', command=takeScreenshot, bg='green',fg='white',font= 10)
canvas1.create_window(150, 150, window=myButton)
root.mainloop()
I wish to grab screenshot of only the window defined by "tk.Canvas(root, width = 300, height = 300)"
But, I am capturing the entire screren.
Can somebody please let me know how do we go about this in python ?
You can get the region of the canvas and pass them to screenshot():
def takeScreenshot():
# get the region of the canvas
x, y = canvas1.winfo_rootx(), canvas1.winfo_rooty()
w, h = canvas1.winfo_width(), canvas1.winfo_height()
pyautogui.screenshot('screenshot.png', region=(x, y, w, h))
Since you are on windows you should be able to employ the win32 API,
Contrary to this you could use more simple solutions such as PyScreenshot
Take the following code for example:
from pyscreenshot import grab
im = grab(bbox=(100, 200, 300, 400))
im.show()
“
As you can see you can use bbox to take screenshot that is at co-ordinates (100, 200) and has a width of 300 and a height of 400.
This would require you knowing the position of the windows before hand- which you can do in Tkinter I believe.”
I found this information from previous SO questions. Here is another snippet that may help you.
Here's how you can do it using PIL on win32. Given a window handle (hwnd), you should only need the last 4 lines of code. The preceding simply search for a window with "firefox" in the title. Since PIL's source is available, you should be able to poke around the ImageGrab.grab(bbox) method and figure out the win32 code you need to make this happen.
from PIL import ImageGrab
import win32gui
toplist, winlist = [], []
def enum_cb(hwnd, results):
winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)
firefox = [(hwnd, title) for hwnd, title in winlist if 'firefox' in title.lower()]
# just grab the hwnd for first window matching firefox
firefox = firefox[0]
hwnd = firefox[0]
win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
Suggestions I found include:
How to do a screenshot of a tkinter application?
How to Get a Window or Fullscreen Screenshot in Python 3k? (without PIL)
I hope this helps, sometimes all it takes is a good google search. If this help you please select this as the correct answer
Edit
Depending upon the contents of the window you could use this- if it is a drawing.
“ You can either generate a postscript document (to feed into some other tool: ImageMagick, Ghostscript, etc)”
from Tkinter import *
root = Tk()
cv = Canvas(root)
cv.create_rectangle(10,10,50,50)
cv.pack()
root.mainloop()
cv.update()
cv.postscript(file="file_name.ps", colormode='color')
root.mainloop()
Look at this if you are trying to save a drawing https://www.daniweb.com/programming/software-development/code/216929/saving-a-tkinter-canvas-drawing-python
You would need to define the rectangle for the screenshot
instead of myScreenshot = pyautogui.screenshot()
use the following in place of it:
myScreenshot = pyautogui.screenshot(region=(0,0, 300, 400))
The 4 points describe where you want the screenshot
https://pyautogui.readthedocs.io/en/latest/screenshot.html
Related
I am trying to build a program which gets me an enlarged photo of the text I want, for this I decided to use tkinter, win32gui and pygetwindow modules after taking some tips from already asked problems on stack overflow am having the following problems:
(1)I don't know how to get the hwnd value of the tkinter window which I created.
(2)I can't get hwnd value even if I know how to get it as the window is created after the complete code has run.
So please suggest me solutions to the problem
This is my code:
from tkinter import *
import win32gui
import pygetwindow as gw
#making the tkinter window
root = Tk()
root.title('DaysLeft')
#getting all the windows with their hwnd values
hwnd=gw.getAllWindows()
print(hwnd)
win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
mainloop()
The above code gives error below as expected:.
line 26, in <module>
win32gui.SetForegroundWindow(hwnd)
TypeError: The object is not a PyHANDLE object
You can use PIL for taking a screenshot and win32gui or pygetwindow to get windows location.
Install PIL by saying
pip install Pillow
then your working code would be:
from tkinter import *
from win32gui import FindWindow, GetWindowRect
import pygetwindow as gw
from PIL import ImageGrab
def ss():
win = gw.getWindowsWithTitle('DaysLeft')[0]
winleft = win.left+9
wintop = win.top+38 #change 38 to 7 to not capture the titlebar
winright = win.right-9
winbottom = win.bottom-9
final_rect = (winleft,wintop,winright,winbottom)
img = ImageGrab.grab(final_rect)
img.save('Required Image.png')
#making the tkinter window
root = Tk()
root.title('DaysLeft')
root.after(3000,ss)
root.mainloop()
Why am i subtracting some amount from the pixels? its because, windows has decorations like drop shadow effect to the windows, which are also part of the windows and will be included in the screenshot, so i used this to get rid of those extra pixels.
Or if your still reluctant on using win32gui then, change the function to:
from win32gui import FindWindow, GetWindowRect
from PIL import ImageGrab
......
def ss():
win = FindWindow(None, 'DaysLeft')
rect = GetWindowRect(win)
list_rect = list(rect)
list_frame = [-9, -38, 9, 9] #change -38 to -7 to not capture the titlebar
final_rect = tuple((map(lambda x,y:x-y,list_rect,list_frame))) #subtracting two lists
img = ImageGrab.grab(bbox=final_rect)
img.save('Image.png')
What is after method? It just calls the function after 3000 ms, i.e, 3 seconds. We are basically giving the system some time to build the GUI and capture screenshot.
Hope it helped, do let me know if any errors or doubts.
Cheers
I am trying to create a translucent window in Tkinter like the one in windows 11
How to do this? If we cannot do this can we capture a part of a screen and blur it using cv2 and use it as a continuously updating background?
No, this is not directly possible with tkinter. But:
If you use PIL, you can get the location of the window, and then take a screenshot, then blur it and then make it your app background. But this wont work if user tries to move/resize the application. But here is a rough code:
from tkinter import *
from PIL import ImageTk, ImageGrab, ImageFilter # pip install Pillow
root = Tk()
root.overrideredirect(1) # Hide the titlebar etc..
bg = Canvas(root)
bg.pack(fill='both',expand=1)
root.update()
# Get required size and then add pixels to remove title bar and window shadow
left = root.winfo_rootx()
top = root.winfo_rooty()
right = left + root.winfo_width()
bottom = top + root.winfo_height()
root.withdraw() # Hide the window
img = ImageGrab.grab((left,top,right,bottom)) # Get the bg image
root.deiconify() # Show the window
img = img.filter(ImageFilter.GaussianBlur(radius=5)) # Blur it
img = ImageTk.PhotoImage(img)
bg.create_image(0,0, image=img, anchor='nw') # Show in canvas
label = Label(root,text='This is a translucent looking app')
bg.create_window(bg.winfo_width()/2,bg.winfo_height()/2,window=label) # Position in the center
root.mainloop()
Output with tkinter:
tkinter is not the best choice if you are trying to go for a modern look, use PyQt and check qtacrylic
Output with PyQt:
For live blur (native Windows blur) use "BlurWindow":
python -m pip install BlurWindow
from tkinter import *
from ctypes import windll
from BlurWindow.blurWindow import blur
root = Tk()
root.config(bg='green')
root.wm_attributes("-transparent", 'green')
root.geometry('500x400')
root.update()
hWnd = windll.user32.GetForegroundWindow()
blur(hWnd)
def color(hex):
hWnd = windll.user32.GetForegroundWindow()
blur(hWnd,hexColor=hex)
e = Entry(width=9)
e.insert(0,'#12121240')
e.pack()
b = Button(text='Apply',command=lambda:[color(e.get())])
b.pack()
root.mainloop()
Try to capture the image of a widget in tkinter window by following code, but just get the screen area under tkinter window.
import ctypes
import platform
from time import sleep
import tkinter as tk
from PIL import ImageGrab
if platform.system() == "Windows" and platform.release() == "10":
ctypes.windll.shcore.SetProcessDpiAwareness(1)
root = tk.Tk()
root.geometry("+0+0")
var = tk.StringVar()
var.set("Hello World")
entry = tk.Entry(root, width=40, bg='green', takefocus=False, textvariable=var)
entry.pack()
root.update()
# sleep(1)
x, y = entry.winfo_rootx(), entry.winfo_rooty()
width, height = entry.winfo_width(), entry.winfo_height()
im = ImageGrab.grab(bbox=(x, y, x+width, y+height)) # Grab image on screen
im.show()
root.mainloop()
It will be OK if line # sleep(1) replaced by sleep(1). Had been tried method update or update_idletasks, all got same results.
Is there any method to finalize tkinter window immediately ? So I don't need to sleep one second each time to grap image of a widget. Or I get wrong way to go it, any suggestion is welcome.
It is obvious right? It needs to take some time to show the window but the screenshot is captured quite quickly. What do I suggest? Put it inside a function and take advantage of the after method here.
def screenshot():
im = ImageGrab.grab(bbox=(x, y, x+width, y+height)) # Grab image on screen
im.show()
root.after(1000,screenshot) # Depending on the time required to take show the window
Working in a EXE file with background and Icon embed, I read some ideas about to use img2py in order to create module.py that can be imported into the EXE with pyinstaller.
I successfully create the imagebg.py (BG2.png Background) and imageico.py (ico2.ico Icon) modules using img2py. But there is no example or way to set that images into the modules in the tkinter label as background and the icon into the code.
Please anybody can help me.
Main code where must be imported BG ad ICON modules and use them as background and Icon images for tkinter GUI
#Main code GUI tkinter
import imagebg #from here we must import PNG_File.png for Background
import imageico #from here we must import ICO_File.ico for Icon
import wx #from img2py installation
from tkinter import *
root=Tk()
#set windows size
root.resizable(width=False, height=False)
root.geometry("925x722")
#set title
root.title("SOFT1)")
#frame 1
f1=Frame(root, width=345,height=475,bg="light
grey",highlightbackground="black",highlightthickness=4)
f1.place(x=20,y=235)
#set a image as BG
Logo=PhotoImage(file="PNG_File.png")
lab6=Label(root, image=Logo)
lab6.place(x=0, y=0)
#set a image as ICON
root.iconbitmap("ICO_File.ico")
mainloop()
The module imagebg.py for backgroud generated with IMG2PY
BG2 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAAsUAAAKECAIAAABgrdCGAAAACXBIWXMAAA7EAAAOxAGVKw4b'
b'AAAgAElEQVR4nOzdd2Ab5d0H8Oe0hy1vecYjcZw4cfYimwQIEEbYhQJlFgqU3UFZLR2M9i2l'
b'tLRlFcouI5Qww15hZJEdO4kdOx7xtiVrj7v3DwdFlmXppu4kfT9/Wfbdc78YY339TMrpdBIA'
b'AAAAAVRyFwAAAABJD3kCAAAAhEKeAAAAAKGQJwAAAEAo5AkAAAAQCnkCAAAAhEKeAAAAAKGQ'
b'JwAAAEAo5AkAAAAQCnkCAAAAhEKeAAAAAKGQJwAAAEAo5AkAAAAQCnkCAAAAhEKeAAAAAKGQ'
b'JwAAAEAo5AkAAAAQCnkCAAAAhEKeA..... to much characters to be placed in this post
The module imageico.py for icon generated with IMG2PY
from wx.lib.embeddedimage import PyEmbeddedImage
ico2 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAAsUAAAKECAYAAADvz0fRAAAABHNCSVQICAgIfAhkiAAAIABJ'
b'REFUeJzs3WeAVNXdBvDnTi/b+7L0svSmIIKd2Gus0ZhiSeKreZOYmGpL15i8SdTEFKMpGkss'
b'GEuMqNFYsCAgHRZYWFiWsn12p7f7fkBwy8zszC1z7537/L7ozs6c82dh4dkz/3OOEAgERBAR'
b'ERERmZhF6wKIiIiIiLTGUExEREREpsdQTERERESmx1BMRERERKbHUExEREREpsdQTERERESm'
b'x1BMRERERKbHUExEREREpsdQTERERESmx1BMRERERKbHUExEREREpsdQTERERESmx1BMRERE'
b'RKbHUExEREREps.... to much characters to be placed in this post
Please any idea of how to use the modules as images for background and icon in the main code GUI Tkinter
You need to convert the wx.Image to PIL compatible image if you want to use it in tkinter application.
Below is an example based on your posted code:
import tkinter as tk
from PIL import Image, ImageTk
import imagebg
import imageico
# function to convert a wx.Image to PIL.ImageTk.PhotoImage
def wx2pil(wx_image):
image = wx_image.Image
w, h = image.GetWidth(), image.GetHeight()
data = image.GetData()
img = Image.frombytes('RGB', (w, h), bytes(data))
return ImageTk.PhotoImage(img)
root = tk.Tk()
root.resizable(False, False)
root.geometry('925x722')
root.title('SOFT1')
# use iconphoto() instead of iconbitmap()
root.iconphoto(False, wx2pil(imageico.ico2))
#set a image as BG
logo = wx2pil(imagebg.BG2)
tk.Label(root, image=logo).place(x=0, y=0)
#frame 1
f1 = tk.Frame(root, width=345, height=475, bg='lightgray', highlightbackground='black', highlightthickness=4)
f1.place(x=20, y=235)
root.mainloop()
Note that I use wxPython v4.1.0.
As it depends on wxPython, why don't you use wxPython for the GUI directly instead of tkinter?
I was recently trying to make a pdf viewer in python, so I set the minsize() and maxsize() of the window but it doesn't seem to work. Here is my code.
from pdf2image import convert_from_path
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
root4=tk.Toplevel()
root4.geometry("800x900")
root4.title("PDF Viewer")
root4.configure(bg="#202020")
root4.minsize(300, 200)
root4.maxsize(900, 800)
pdf_frame = tk.Frame(root4)
pdf_frame.pack(fill=tk.BOTH,expand=1)
scrol_y = tk.Scrollbar(pdf_frame,orient=tk.VERTICAL)
pdf = tk.Text(pdf_frame,yscrollcommand=scrol_y.set,bg="grey")
scrol_y.pack(side=tk.RIGHT,fill=tk.Y)
scrol_y.config(command=pdf.yview)
pdf.pack(fill=tk.BOTH,expand=1)
pages = convert_from_path(filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("pdf files","*.pdf"),("all files","*.*"))),size=(800,900))
photos = []
for i in range(len(pages)):
photos.append(ImageTk.PhotoImage(pages[i]))
for photo in photos:
pdf.image_create(tk.END,image=photo)
pdf.insert(tk.END,'\n\n')
root4.update()
root4.mainloop()
When your creating a parent window use Tk(), else using Toplevel() will create a Tk()(for which the minsize and maxsize doesnt apply) window without you asking for it and you mightve misunderstood that for your root4 window, so just say:
tk.Tk().withdraw()
root4 = tk.Tk()
This fixed the issue of two windows popping up, for me. Keep in mind the minsize() and maxsize() works, its just that you were trying it on the wrong window.