Refocusing Tkinter image window - python

Script2 displays an image and and closes the image after spacebar is being pressed. Script2 works perfectly alone.
Unfortunately when I use script1 to launch script2, I have to click/refocus the image window before I'm able to close the image with spacebar.
I've tried using win32gui module to refocus generated image window with separate script (focus.py). If I run focus.py by myself when the image is being displayed, I'm able to just press the spacebar and image window closes. However I've not been able to import focus.py script to script2.py succesfully (so that I would only have script1.py and script2.py.
script1:
action = raw_input("Pick a scenario: ")
if action == "1":
execfile("script2.py")
else:
print "Try again."
return self
script2:
import os, sys
import Tkinter
from PIL import Image, ImageTk
def close_window(event):
event.widget.quit()
root = Tkinter.Tk()
root.bind("<space>", close_window)
imagefile = "image1.png"
image1 = Image.open(imagefile)
root.geometry('%dx%d' % (image1.size[0],image1.size[1]))
tkpi = ImageTk.PhotoImage(image1)
label_image = Tkinter.Label(root, image=tkpi)
label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1])
root.mainloop()
focus.py
import win32gui
tk = win32gui.FindWindow(None, 'tk')
win32gui.SetForegroundWindow(tk)

Related

ImageGrab.grab not get widget of tkinter window, but screen area under it

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

IMG2PY for background label and icon in TKINTER

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?

How to minimize a tkinter app before taking screenshot and then maximize

I have a python tkinter app script which can take screenshots on pressing the button. But unfortunately while taking the screenshot, the window of the app also gets captured.
Here's the code of the app:
from PIL import ImageGrab
import tkinter as tk
from tkinter import filedialog
import time
def takeShot():
sc = ImageGrab.grab()
path = filedialog.asksaveasfilename(defaultextension='.png')
sc.save(path)
root = tk.Tk()
canvas1 = tk.Canvas(root,width=300,height=300)
canvas1.pack()
but = tk.Button(text='Take Screenshot',command=takeShot,bg='green',fg='white',font=10)
canvas1.create_window(150,150,window=but)
root.mainloop()
Though it takes the screenshot but app window also gets captured
I don't want that white window in the screenshot. I tried to minimize the window and then maximise by updating the function like this:
def takeShot():
root.withdraw()
sc = ImageGrab.grab()
root.deiconify()
path = filedialog.asksaveasfilename(defaultextension='.png')
sc.save(path)
but it didn't work.
Is there anyway to minimize the app then take the screenshot and then maximize it for save dialogue box so that fulscreen gets captured ??
You need to call root.update_idletasks() after the call to root.withdraw() to force tkinter to redraw the window (or in this case, to remove the window from view).
If you find that root.update_idletasks() doesn't cause the window to hide on your platform, you can try root.update(). update_idletasks should work, though.
I don't have the issue in my Windows running Python 3.8.1. However, I suggest to move the asksaveasfilename(...) right after root.withdraw() as asksaveasfilename(...) is a modal dialog and returns after it is closed:
def take_snapshot():
root.withdraw()
filename = filedialog.asksaveasfilename(initialdir='.', defaultextension='.png')
if filename:
image = ImageGrab.grab()
image.save(filename)
root.deiconify()

Not being able to load an image in python

I am trying to load an image into a canvas in python. However I am getting the error: TclError: couldn't recognize data in image file "C:\testimage\spongesea.jpg"
import Tkinter
from Tkinter import *
import time
import inspect
import os
from PIL import Image, ImageTk
class game_one:
def __init__(self):
global root
global canvas_one
root = Tk()
root.title(" Thanks Josh Dark
canvas_one = Tkinter.Canvas(root, bg="BLACK")
canvas_one.pack(expand= YES, fill= BOTH)
canvas_one.focus_set() #allows keyboard events
p = PhotoImage(file="C:\testimage\spongesea.jpg")
canvas_one.create_image(0, 0, image = p, anchor=NW)
root.grab_set()#I forget what this does. Don't change it.
root.lift()#This makes root appear in front of the other applications
ObjectExample = game_one()# starts the animation
I can open the image manually from the file, so it is not corrupted, and it is calling the correct place. Any ideas? Thanks
PhotoImage works only with GIF and PGM/PPM.
You have to use Image, ImageTk to work with other formats
from PIL import Image, ImageTk
image = Image.open("lenna.jpg")
photo = ImageTk.PhotoImage(image)
BTW: read PhotoImage and see "Garbage Collection problem" in note.

How to hide console when displaying an image with Tkinter

I have a simple code block that displays an image when the user press a button. When I save the script with .py extension, there is console at the background so I decided to save it as .pyw to hide it. Here is my code;
from tkinter import *
from PIL import Image
def open_image():
im = Image.open("tobi.jpg")
im.show()
root = Tk()
root.geometry("800x600+400+300")
buton = Button(root)
buton.config(text = "Show the image", command = open_image, activebackground = "yellow", bg = "lightgreen")
buton.pack()
mainloop()
I don't see cmd at the background since I save it as .pyw. However, when I click the button, just before opening the image I see console for a short time, then it dissappears. How can I avoid this, I want to hide console completely,
I dont know how to do this through pure tk but if subprocess is an option then you can do the following. Not a very good solution, since you have to use the subprocess module just to open an image... but anyways....
import tkinter as tk
import subprocess as s
root = tk.Tk()
def open_image():
s.call(["tobi.jpg"], shell=True)
button = Button(root)
button.config(text="Show the Image", command=open_image, activebackground="yellow", bg="lightgreen")
button.pack()
root.mainloop()
alternatively you could use os and use os.system("start my_file_name.jpg")
(assuming windows here)
With os.system the console will show but only very briefly.
Really doing the same thing, opening with PIL is just slower than others, so you see the console for a longer period.
U can use the following code:`
import win32console
import win32gui
win=win32console.GetConsoleWindow() # For closing command window
win32gui.ShowWindow(win,0)
This will close the cmd window at start itself, and will not show again. The cmd window may show for a very little time at first, as a blink, then it will not show. u can save in .py extention.
here the full code:`
from Tkinter import *
from PIL import Image
import win32console
import win32gui
win=win32console.GetConsoleWindow() # For closing command window
win32gui.ShowWindow(win,0)
def open_image():
im = Image.open("tobi.jpg")
im.show()
root = Tk()
root.geometry("800x600+400+300")
buton = Button(root)
buton.config(text = "Show the image", command = open_image, activebackground = "yellow", bg = "lightgreen")
buton.pack()
mainloop()

Categories