from PIL import Image
from tkinter import filedialog as fd
import os
import ctypes
import tkinter
class ImageList:
path = ""
dir = ""
top = tkinter.Tk()
canvas = tkinter.Canvas()
canvas.pack()
def __init__(self):
self.path = os.path.expanduser('~/')
def findImage(self):
image = Image.open(self.dir, "rb")
image.show()
def fileExplorer(self, path):
self.canvas.destroy()
self.canvas = tkinter.Canvas()
self.canvas.pack()
obj = os.scandir(path)
for entry in obj:
if entry.is_dir():
#self.path = os.path.abspath(self.path)
b = tkinter.Button(self.canvas, text=entry.name, command=lambda: self.fileExplorer(os.path.abspath(entry).replace('//', '\\')))
b.pack()
elif entry.is_file():
b = tkinter.Button(self.canvas, text=entry.name, command=lambda: print(entry.name))
b.pack()
else:
obj.close()
self.top.mainloop()
As shown in the code above, I am trying to make exe that shows the subdirs and files after C:\Users using buttons in tkinter and repeating it by using recursion.
The first error is that in "os.path.abspath(entry).replace('//', '\')" shows path in a format of "C://Users" and I intended to change that to "C:\Users" using the replace method. However, using "\" doesn't replace "//" and still shows as the original format.
The second error is that after running the code, when I press any button it acts as if I pressed the last button in the tkinter window, meaning that it recursively called the last subdir or the file below "C:\Users".
I'm just getting used to python and this is my first time using stackoverflow. I'm sorry if I did not abide by any of the rules in stackoverflow. Thanks for anyone helping.
I am currently working on a project, and in the end I'd need to compile it. The issue that I am facing is that I am working with the .py file, but also 2 folders, one with all of the images, and one with all of the music...
I've looked around, but nothing answers the questions completely. I've seen that it was best to base64 encode my images, but that didn't seem to work for me... I tried UTF-8 characters and binary.
Any idea on how I could transform my 2 folders and my code file into a single .exe executable, that can be used on any computer?
Thanks
Angaros
Have you tried this kind of approach:
Let's assume you have some kind of layout like this
main.py
resources.py
data/img1.png
And in main.py:
import resources
import tkinter as tk
root = tk.Tk()
root.title("Test")
resources.load_images()
lbl = tk.Label(root, image=resources.IMG1)
lbl.place(relx=0.5, rely=0.5, anchor="c")
root.mainloop()
And in resources.py:
import tkinter as tk
IMG1 = None
def load_images():
global IMG1
IMG1 = tk.PhotoImage("data\\img1.png")
This works quite nicely, and can load your image.
Now let's make it work in one single exe file:
We don't need to change main.py, as it simply loads resources through our resources.py script.
We can load/save our image data using this script:
import base64
def load_data(filename):
with open(filename, mode="rb") as f:
return base64.b64encode(f.read())
print(str(load_data("data\\img1.png"), "utf-8"))
# R0lGOD ...
So we can now copy and paste this into our resources.py file, and change it to look like this:
import tkinter as tk
# here's our copied base64 stuff:
img1_data = '''
R0lGODlhEAAQALMAAAAAAP//AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA\nAAAAACH5BAEAAAIALAAAAAAQABAAQAQ3UMgpAKC4hm13uJnWgR
TgceZJllw4pd2Xpagq0WfeYrD7\n2i5Yb+aJyVhFHAmnazE/z4tlSq0KIgA7\n
'''
IMG1 = None
def load_images():
global IMG1
IMG1 = tk.PhotoImage(data=img1_data)
And now compile our main.py file using PyInstaller:
pyinstaller main.py --onefile
And we should see, once the task is complete, that there is a single executable file in dist, called main.exe.
I am trying to pass the path of an image and then opening it but i get this error for this line image = Image.open(path):
AttributeError: type object 'Image' has no attribute 'open'
from PIL import Image
from tkinter import *
class Menu:
def __init__(self,root):
self.root = root
self.root.title("Image")
self.image_entry = Entry(root)
self.image_entry.grid(row=0,column=1)
image_label = Label(root,text = "Enter the path of the image").grid(row=0)
images = Button(root,text="Show",command=lambda:[self.show(self.image_entry)]).grid(row=1,column=1)
root.mainloop()
def show(self,image_entry):
path=image_entry.get()
image = Image.open(path)
image.show()
The variable Image imported from PIL is being overwritten by the variable Image imported from Tkinter.
Possible solutions, in descending order of best-practice-ness:
Don't import things from tkinter using import *. Try importing only the names you need, for example from tkinter import Entry, Label, Button, Tk.
Choose an alias for PIL's Image that doesn't conflict with Tkinter's Image. For example, from PIL import Image as PILImage.
Switch the order of your imports so PIL's Image overwrites Tkinter's Image, instead of the other way around.
I am interested to create a single tkinter GUI in which i can define a path to run a python script located in a particular folder. The code is shown below. It can read the required .py file from the set of files in that folder using the path i have given and open the dialogue box for plot graphs too but doesnt do anything. When i click the plot graphs button rather it gives an error "AttributeError: 'int' object has no attribute 'display_graph'". Can anyone check and edit my code to help.(I am using spyder so tk is tkr). I know about py2exe, So i would appreciate if someone can help with tkinter GUI code. Thanks
My python script is Empdata.py and i used def display_graph(data) in it:
Code
import glob
import tkinter as tkr
import os
path = r'C:\Users\C253271\Desktop\Empower data\\'
allpyfiles =glob.glob(os.path.join(path, "*.py"))
for file in allpyfiles:
file =('Empdata')
def graph():
global v
file.display_graph(v.get())
root = tkr.Tk()
v = tkr.StringVar()
tkr.Button(root, text='Close',command=root.destroy).grid(row=2, column=1)
tkr.Button(root, text='Plot Graphs', command = graph).grid(row=2, column=0)
root.mainloop()
In the code from the question, file is a string. It thus does not have any methods. What you really want to do is to import the python file, such that its content is available.
To do so, you may use importlib
f = importlib.import_module("Empdata") # if you have Empdata.py in your folder
f.some_method()
Your example should therefore look something like
import Tkinter as tkr
import importlib
fn = "Empdata"
f = importlib.import_module(fn)
def graph():
global v
f.display_graph(v.get())
root = tkr.Tk()
v = tkr.StringVar()
tkr.Button(root, text='Close',command=root.destroy).grid(row=2, column=1)
tkr.Button(root, text='Plot Graphs', command = graph).grid(row=2, column=0)
root.mainloop()
What is the easiest way to show a .jpg or .gif image from Python console?
I've got a Python console program that is checking a data set which contains links to images stored locally. How should I write the script so that it would display images pop-up graphical windows?
Using the awesome Pillow library:
>>> from PIL import Image
>>> img = Image.open('test.png')
>>> img.show()
This will open the image in your default image viewer.
In a new window using Pillow/PIL
Install Pillow (or PIL), e.g.:
$ pip install pillow
Now you can
from PIL import Image
with Image.open('path/to/file.jpg') as img:
img.show()
Using native apps
Other common alternatives include running xdg-open or starting the browser with the image path:
import webbrowser
webbrowser.open('path/to/file.jpg')
Inline a Linux console
If you really want to show the image inline in the console and not as a new window, you may do that but only in a Linux console using fbi see ask Ubuntu or else use ASCII-art like CACA.
Since you are probably running Windows (from looking at your tags), this would be the easiest way to open and show an image file from the console without installing extra stuff like PIL.
import os
os.system('start pic.png')
Or simply execute the image through the shell, as in
import subprocess
subprocess.call([ fname ], shell=True)
and whatever program is installed to handle images will be launched.
In Xterm-compatible terminals, you can show the image directly in the terminal. See my answer to "PPM image to ASCII art in Python"
If you would like to show it in a new window, you could use Tkinter + PIL library, like so:
import tkinter as tk
from PIL import ImageTk, Image
def show_imge(path):
image_window = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(image_window, image=img)
panel.pack(side="bottom", fill="both", expand="yes")
image_window.mainloop()
This is a modified example that can be found all over the web.
Why not just display it in the user's web browser?
You cannot display images in a console window.
You need a graphical toolkit such as Tkinter, PyGTK, PyQt, PyKDE, wxPython, PyObjC, or PyFLTK.
There are plenty of tutorials on how to create simple windows and loading images in python.
You can also using the Python module Ipython, which in addition to displaying an image in the Spyder console can embed images in Jupyter notebook. In Spyder, the image will be displayed in full size, not scaled to fit the console.
from IPython.display import Image, display
display(Image(filename="mypic.png"))
I made a simple tool that will display an image given a filename or image object or url.
It's crude, but it'll do in a hurry.
Installation:
$ pip install simple-imshow
Usage:
from simshow import simshow
simshow('some_local_file.jpg') # display from local file
simshow('http://mathandy.com/escher_sphere.png') # display from url
If you want to open the image in your native image viewer, try os.startfile:
import os
os.startfile('file')
Or you could set the image as the background using a GUI library and then show it when you want to. But this way uses a lot more code and might impact the time your script takes to run. But it does allow you to customize the ui. Here's an example using wxpython:
import wx
########################################################################
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.SetBackgroundStyle(wx.BG_STYLE_PAINT) # Was wx.BG_STYLE_CUSTOM)
self.frame = parent
sizer = wx.BoxSizer(wx.VERTICAL)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
for num in range(4):
label = "Button %s" % num
btn = wx.Button(self, label=label)
sizer.Add(btn, 0, wx.ALL, 5)
hSizer.Add((1,1), 1, wx.EXPAND)
hSizer.Add(sizer, 0, wx.TOP, 100)
hSizer.Add((1,1), 0, wx.ALL, 75)
self.SetSizer(hSizer)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
#----------------------------------------------------------------------
def OnEraseBackground(self, evt):
"""
Add a picture to the background
"""
# yanked from ColourDB.py
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
dc.Clear()
bmp = wx.Bitmap("file")
dc.DrawBitmap(bmp, 0, 0)
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, size=(600,450))
panel = MainPanel(self)
self.Center()
########################################################################
class Main(wx.App):
""""""
#----------------------------------------------------------------------
def __init__(self, redirect=False, filename=None):
"""Constructor"""
wx.App.__init__(self, redirect, filename)
dlg = MainFrame()
dlg.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = Main()
app.MainLoop()
(source code from how to put a image as a background in wxpython)
You can even show the image in your terminal using timg:
import timg
obj = timg.Renderer()
obj.load_image_from_file("file")
obj.render(timg.SixelMethod)
(PyPI: https://pypi.org/project/timg)
You can use the following code:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
img = mpimg.imread('FILEPATH/FILENAME.jpg')
imgplot = plt.imshow(img)
plt.axis('off')
plt.show()
Displaying images in console using Python
For this you will need a library called ascii_magic
Installation : pip install ascii_magic
Sample Code :
import ascii_magic
img = ascii_magic.from_image_file("Image.png")
result = ascii_magic.to_terminal(img)
Reference : Ascii_Magic
2022:
import os
os.open("filename.png")
It will open the filename.png in a window using default image viewer.
The easiest way to display an image from a console script is to open it in a web browser using webbrowser standard library module.
No additional packages need to be installed
Works across different operating systems
On macOS, webbrowser directly opens Preview app if you pass it an image file
Here is an example, tested on macOS.
import webbrowser
# Generate PNG file
path = Path("/tmp/test-image.png")
with open(path, "wb") as out:
out.write(png_data)
# Test the image on a local screen
# using a web browser.
# Path URL format may vary across different operating systems,
# consult Python manual for details.
webbrowser.open(f"file://{path.as_posix()}")