I'm having a trouble to store a file location into a entry widget for my script using Tkinter:
So far I was able to have a browse button working perfectly, however, I cannot assing the variable value that I created parent.filename to store the file location into a entry widget like the photo below shows:
My script following below:
from Tkinter import *
import ttk
from PIL import ImageTk, Image
import os
import Tkinter, Tkconstants, tkFileDialog
class arquivos:
def __init__(self, parent):
parent.title('TEXT MINING - HMB QA')
self.gif1 = PhotoImage(file = 'tteste.gif')
label1 = Label(image=self.gif1)
label1.image = self.gif1
label1.grid(row = 0, column = 0, rowspan=13, sticky=NW)
Label(parent, text='File URL:').grid(row=0, column=1, sticky='e')
self.v1=Entry(parent, width=90)
self.v1.grid(row=0, column=2, sticky='we',columnspan=8)
self.button3 = Button(parent, text = "Browse", command
=self.loadtemplate, width = 10, height=1)
self.button3.grid(row=0, column=10, columnspan=2, sticky='w')
Label(parent, text='Filter RO List:').grid(row=1, column=1,
sticky='e')
self.v2=Radiobutton(parent, text="YES", value=1)
self.v2.grid(row=1,column=2, columnspan=1, sticky='w')
parent=Tk()
arquivos(parent)
parent.mainloop(
Regarding the function loadtemplate follows the code:
def loadtemplate(self):
parent.filename = StringVar()
parent.filename = tkFileDialog.askopenfilename(initialdir = "/",title
= "Select file",filetypes = (("jpeg files","*.jpg"),("all
files","*.*")))
print parent.filename
self.v20 = Entry(parent, textvariable=parent.filename, width=90)
self.v20.grid(row=0,column=2, sticky='we',columnspan=8)
When I hit the Browse button a box pops out and I can select the file directory:
The variable parent.filename assigned to store the file location also works, however, I'm not able to store the variable value into the entry widget self.v1
Any help will be highly appreciated
As is you're overwriting StringVar instance on parent.filename with a destination string. Use set method to set the value of the variable class
object in parent.filename instead.
Replace:
parent.filename = tkFileDialog.askopenfilename(initialdir = "/",title
= "Select file",filetypes = (("jpeg files","*.jpg"),("all
files","*.*")))
with:
parent.filename.set(tkFileDialog.askopenfilename(initialdir = "/",title
= "Select file",filetypes = (("jpeg files","*.jpg"),("all
files","*.*"))))
Related
I am creating an EXIF viewer using Tkinter. I need to load an image, which I am already doing, but I can't position it on top of my window into a frame. I used
top_frame = Frame(root)
top_frame.pack(side=TOP)
But I don't know how to position the picture I'm loading into it.
Everytime I load an image it adds it to the view, I'd like to delete the precedent one and add the new one. And this picture must be always inside a precise frame, independently on its size.
This is how I'm visualizing it now:
This is my code:
from tkinter import *
import PIL
from PIL import ImageTk, Image
from tkinter import filedialog
import tkinter as tk
from PIL.ExifTags import TAGS
from exifread.tags import exif
root = tk.Tk()
root.title('Exif Viewer')
root.geometry('500x550')
root.iconbitmap("../icons/exif.png")
def browse_image():
global image_object, image_loaded_label
image_loaded_label = None
root.filename = filedialog.askopenfilename(initialdir="/", title="Select An Image",
filetypes=(("jpeg files", "*.jpeg"), ("png files", "*.png")))
image_object = Image.open(root.filename)
image_loaded = ImageTk.PhotoImage(image_object)
image_loaded_label = Label(image=image_loaded)
image_loaded_label.pack()
image_loaded_label.image = image_loaded
def rotate_image(direction):
global image_object
angle = {"left":90, "right":-90}[direction]
image_object = image_object.rotate(angle)
rotated_tk = ImageTk.PhotoImage(image_object)
image_loaded_label.config(image=rotated_tk)
image_loaded_label.image = rotated_tk #Prevent garbage collection
def get_exif():
global image_object
exif_data = image_object._getexif()
for tag_id in exif_data:
tag_name = TAGS.get(tag_id, tag_id)
value = exif_data.get(tag_id)
print(f"{tag_name:25}: {value}")
top_frame = Frame(root)
top_frame.pack(side=TOP)
bottom_frame = Frame(root)
bottom_frame.pack(side=BOTTOM)
browse_button = Button(bottom_frame, padx=20, pady=5, text="Load image", command=browse_image)
browse_button.grid(row=1, column=0)
browse_button.pack()
rotate_left_button = Button(bottom_frame, padx=10, pady=5, text="Rotate left", command=lambda: rotate_image("left"))
rotate_left_button.pack(side=LEFT)
rotate_right_button = Button(bottom_frame, padx=10, pady=5, text="Rotate right", command=lambda: rotate_image("right"))
rotate_right_button.pack(side=RIGHT)
get_exif = Button(bottom_frame, padx=20, pady=5, text="Get EXIF", command=get_exif)
get_exif.pack(side=TOP)
exit_button = Button(bottom_frame, padx=20, pady=5, text="Exit", command=root.quit)
exit_button.pack()
root.mainloop()
I want to convert the image formats of all images in a folder using tkinter. all extensions I want in a combobox but I don't know why this code doesn't work .no error is displayed.
from tkinter import filedialog, StringVar
from tkinter import ttk
root=tkinter.Tk()
root.geometry("800x600")
#defining functions
def get_folder():
global folder_path
folder_path = filedialog.askdirectory(initialdir='./', title="Select Folder")
print(folder_path)
def get_extension():
change_to = com.get()
change_from = "py"
files=os.listdir(folder_path)
for file in files:
if (".%s"%change_from) in file:
newfile=file.replace((".%s"%change_from),".%s"%change_to)
os.rename((folder_path+'/'+file),(folder_path+'/'+newfile))
#defining widgets for frames
folder_label = tkinter.Label(from_frame)
browse_button = tkinter.Button(from_frame, text="Browse", command=get_folder)
change_button = tkinter.Button(button_frame, text="Change Extension", command=get_extension)
change_button.pack()
#defining combobox
com = StringVar()
list_combo = ['.png','.jpg','.jpeg', '.svg', '.tif','.bmp','.gif','ppm']
combox = ttk.Combobox(root, width = 25, font = 'arial 19 bold', value = list_combo, state = 'r', textvariable = com)
combox.place(x= 190, y= 190)
combox.set('select type')
root.configure(bg = 'coral1')
root.mainloop()```
Is this what You want:
from tkinter import Tk, Button, Label, StringVar, Frame
from tkinter.ttk import Combobox
from tkinter.filedialog import askdirectory
import os
def convert_extensions():
path = dir_lbl.cget('text')
from_ = from_var.get()
to_ = to_var.get()
files_from = [f'{path}/{file}' for file in os.listdir(path) if file.split('.')[-1] == from_]
files_to = ['.'.join(file.split('.')[:-1]) + '.' + file.split('.')[-1].replace(from_, to_) for file in files_from]
for from_file, to_file in zip(files_from, files_to):
os.rename(from_file, to_file)
print(f'{"-" * 100}\n'
f'{"From:": <10} {from_file}\n'
f'{"To:": <10} {to_file}\n')
root = Tk()
root.geometry('500x200')
Button(root, text='Choose Directory', command=lambda: dir_lbl.config(text=askdirectory())).pack(pady=5)
dir_lbl = Label(root, text='')
dir_lbl.pack(pady=5)
options_frame = Frame(root)
options_frame.pack(pady=5)
from_var = StringVar(value='Convert from')
list_combo = ['png', 'jpg', 'jpeg', 'svg', 'tif', 'bmp', 'gif', 'ppm']
Combobox(options_frame, value=list_combo,
textvariable=from_var, state='r').pack(side='left', padx=5, pady=5)
to_var = StringVar(value='Convert to')
Combobox(options_frame, value=list_combo,
textvariable=to_var, state='r').pack(side='left', padx=5, pady=5)
Button(root, text='Convert', command=convert_extensions).pack(pady=5)
root.mainloop()
This however allows more control in that You can choose both the extension to convert and to which one convert.
This is pretty basic so if You have any questions, ask. I will probably add a detailed explanation later but for now this is all I can do. Oh and btw that three line print function is not necessary at all and it probably should be made to display that in tkinter window or sth but otherwise it can be removed.
I'm new to python and I'm wondering how to validate if label text exists. I'm getting an error:
Below's my full code. You can see the function validate at the bottom, and I'm figuring out how to make the label work in if else condition.
import openpyxl, os
import glob
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
class Root(Tk):
def __init__(self):
super(Root, self).__init__()
#Add a widget title
self.title("Automated filling up of form in iPage")
#Set widget width and height
self.minsize(300, 200)
#Display browse button
self.displayForm()
def doubleQuote(self, word):
return '"%s"' % word
def displayForm(self):
#Display label frame
self.labelFrame = ttk.LabelFrame(self, text = "Open Excel File")
self.labelFrame.grid(column=1, row=2, pady=5, sticky=NW)
#Create browse button
self.button = ttk.Button(self.labelFrame, text = "Browse a File",command = self.openFileDialog)
self.button.grid(column=1, row=1, padx=5, pady=5)
ttk.Label(self, text="Cell From:").grid(column=0, row=0, padx=5)
ttk.Label(self, text="Cell To:").grid(column=0, row=1, padx=5)
self.cf = StringVar()
self.ct = StringVar()
self.cellFrom = ttk.Entry(self, textvariable=self.cf)
self.cellTo = ttk.Entry(self, textvariable=self.ct)
self.cellFrom.grid(column=1, row=0, pady=5)
self.cellTo.grid(column=1, row=1, pady=5)
self.cf.trace("w",self.validate)
self.ct.trace("w",self.validate)
self.submitBtn = ttk.Button(self, text='Submit', command=self.validate)
self.submitBtn.grid(column=1, row=3, pady=5, sticky=NW)
def openFileDialog(self):
#Create a file dialog
self.filename = filedialog.askopenfilename(initialdir = "/", title = "Select A File", filetype =
[("Excel files", ".xlsx .xls")])
self.label = ttk.Label(self.labelFrame, text = "", textvariable=self.fl)
self.label.grid(column = 1, row = 2)
#Change label text to file directory
self.label.configure(text = self.filename)
self.label.trace("w",self.validate)
#Return tail of the path
self.trimmed = os.path.basename(self.filename)
#Pass tail variable
self.openSpreadsheet(self.trimmed)
def openSpreadsheet(self, tail):
#Open excel spreadsheet
self.wb = openpyxl.load_workbook(tail)
self.sheet = self.wb['Sheet1']
#Return data from excel spreadsheet
for rowOfCellObjects in self.sheet[self.cf.get():self.ct.get()]:
#Loop through data
for link in rowOfCellObjects:
#Remove www and firstlightplus.com text
self.cleanURL = link.value.replace("www.", " ").replace(".firstlightplus.com", "")
print(self.cleanURL)
def validate(self, *args):
#Retrieve the value from the entry and store it to a variable
if self.cf.get() and self.ct.get() and self.label["text"]:
print("normal")
self.submitBtn.config(state='normal')
else:
print("disabled")
self.submitBtn.config(state='disabled')
root = Root()
root.mainloop()
I believe the problem is the validate function can be called before the openFileDialog function. This way, the label attribute is being accessed before it has been created.
A simple solution would be initialize the attribute in the displayForm function:
def displayForm(self):
#Display label frame
self.labelFrame = ttk.LabelFrame(self, text = "Open Excel File")
self.labelFrame.grid(column=1, row=2, pady=5, sticky=NW)
self.label = None
# ... Rest of the code
And then, before accessing the attribute, test if it exists:
def validate(self, *args):
#Retrieve the value from the entry and store it to a variable
if self.cf.get() and self.ct.get() and self.label and self.label["text"]:
print("normal")
self.submitBtn.config(state='normal')
else:
print("disabled")
self.submitBtn.config(state='disabled')
Here is my full Python code:
from tkinter import *
import glob
import os
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
import pyautogui
import datetime
#date & time
now = datetime.datetime.now()
root = tk.Tk()
root.title("SIGN OFF")
root.minsize(840, 800)
# Add a grid
mainframe = tk.Frame(root)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
mainframe.pack(pady=100, padx=100)
# Create a Tkinter variable
tkvar = tk.StringVar(root)
# Directory
directory = "C:/Users/eduards/Desktop/work/data/to-do"
choices = glob.glob(os.path.join(directory, "*.jpg"))
tkvar.set('...To Sign Off...') # set the default option
# Dropdown menu
popupMenu = tk.OptionMenu(mainframe, tkvar, *choices)
tk.Label(mainframe, text="Choose your sign off here:").grid(row=1, column=1)
popupMenu.grid(row=2, column=1)
label2 = tk.Label(mainframe, image=None)
label2.grid(row = 4, column = 1, rowspan = 10)
# On change dropdown callback.
def change_dropdown(*args):
""" Updates label2 image. """
imgpath = tkvar.get()
img = Image.open(imgpath)
img = img.resize((240,250))
photo = ImageTk.PhotoImage(img)
label2.image = photo
label2.configure(image=photo)
tk.Button(mainframe, text="Open", command=change_dropdown).grid(row=3, column=1)
def var_states():
text_file = open("logfile.txt", "a")
text_file.write("TIME: %s, USER: %s, One %d, Two %d\n" % (now,os.getlogin(), var1.get(), var2.get()))
text_file.close()
print("One %d, Two %d" % (var1.get(), var2.get()))
var1 = IntVar()
Checkbutton(mainframe, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(column = 2, row=1, sticky=W)
var2 = IntVar()
Checkbutton(mainframe, text="May Contain Statement.", variable=var2).grid(column = 2, row=2, sticky=W)
var3 = IntVar()
Checkbutton(mainframe, text="Cocoa Content (%).", variable=var3).grid(column = 2, row=3, sticky=W)
var4 = IntVar()
Checkbutton(mainframe, text="Vegetable fat in addition to Cocoa butter", variable=var4).grid(column = 2, row=4, sticky=W)
var5 = IntVar()
Checkbutton(mainframe, text="Instructions for Use.", variable=var5).grid(column = 2, row=5, sticky=W)
var6 = IntVar()
Checkbutton(mainframe, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6).grid(column = 2, row=6, sticky=W)
var7 = IntVar()
Checkbutton(mainframe, text="Nutritional Information Visible", variable=var7).grid(column = 2, row=7, sticky=W)
var8 = IntVar()
Checkbutton(mainframe, text="Storage Conditions", variable=var8).grid(column = 2, row=8, sticky=W)
var9 = IntVar()
Checkbutton(mainframe, text="Best Before & Batch Information", variable=var9).grid(column = 2, row=9, sticky=W)
var10 = IntVar()
Checkbutton(mainframe, text="Net Weight & Correct Font Size.", variable=var10).grid(column = 2, row=10, sticky=W)
var11 = IntVar()
Checkbutton(mainframe, text="Barcode - Inner", variable=var11).grid(column = 2, row=11, sticky=W)
var12 = IntVar()
Checkbutton(mainframe, text="Address & contact details correct", variable=var12).grid(column = 2, row=12, sticky=W)
def user():
user_input = os.getlogin()
tk.Label(mainframe, text = user_input, font='Helvetica 18 bold').grid(row = 0, column = 1)
user()
def save():
# pyautogui.press('alt')
# pyautogui.press('printscreen')
# img = ImageGrab.grabclipboard()
# img.save('paste.jpg', 'JPEG')
var_states()
tk.Button(mainframe, text = "Save", command = save).grid(row = 20, column = 1)
root.mainloop()
When I run the code, there will be a dropdown of jpg files. Currently It shows the full directory like so:
I have created a post earlier on how to trim down the path and got something like this:
files = os.listdir("C:/Users/eduards/Desktop/work/data/to-do")
print(files)
But If I use that code above, it will not open the path when clicked open because it doesn't have the full path name.
What I am trying to do is, cut down the path name for display purposes and open the image by following the original full path.
As an example:
The current drop-down menu shows C:/Users/eduards/Desktop/work/data/to-do/img1.jpg
My desired result is img1.jpg but in the background open the whole path of above.
Copy comment: this is what I have tried
directory = os.path.splitdrive("C:/Users/eduards/Desktop/work/data/to-do")
choices = glob.glob(os.path.join(directory[1:], "*.jpg"))
, but says
expected str, bytes or os.Pathlike, not tuple.
Have added [1:] because the path is split into 2 and returning the 2nd part of it.
Question: Show only the filename in OptionMenu but get original full path from selection.
Create your own OptionMenu which holds from all images the full path in a dict and shows only the filename as options.
Define your own widget FileNameOptionMenu by inheriting from (tk.OptionMenu)
class FileNameOptionMenu(tk.OptionMenu):
def __init__(self, parent, directory, extension, callback):
Get from all images the full path and extract the filename.
Save every full path in a dict using the filename as key and the full path as value.
# Save result from `glob` in a `dict`
self.glob = {}
for fpath in glob.glob(os.path.join(directory, "*.{}".format(extension))):
filename, extension = os.path.splitext(os.path.split(fpath)[1])
self.glob[filename] = fpath
Define a variable which holds the selected option for later usage.
Init the inherited tk.OptionMenu with the list of the keys from the dict.
Pass the class method self.command as command=.
Save the callback for later usage.
self.selected = tk.StringVar(parent, 'Select a image...')
super().__init__(parent, self.selected, *list(self.glob),
command=self.command)
self.callback = callback
This class method get called on every click option selection.
On call, it calls the self.callback, which is ImageLabel.configure, with the full path of the selected option.
def command(self, val):
self.callback(image=self.glob.get(self.selected.get()))
Define your own widget ImageLabel by inheriting from (tk.Label).
This class extends the tk.Label.configure to handle .configure(image=<full path> instead of .configure(image=<image object>.
class ImageLabel(tk.Label):
def __init__(self, parent):
super().__init__(parent, image=None)
Overload the inherited class method tk.Label.configure.
Catch the name argument image= and replace the passed full path with a image object.
def configure(self, **kwargs):
key = 'image'
if key in kwargs:
# Replace the filepath with the image
fpath = kwargs[key]
img = Image.open(fpath)
img = img.resize((240, 250))
self._image = ImageTk.PhotoImage(img)
kwargs[key] = self._image
Call the original tk.Label.configure to show the image
super().configure(**kwargs)
Usage:
import tkinter as tk
from PIL import Image, ImageTk
import glob, os
class App(tk.Tk):
def __init__(self):
super().__init__()
self.label_image = ImageLabel(parent=self)
self.label_image.grid(row=2, column=0)
self.option_menu = \
FileNameOptionMenu(parent=self,
directory='C:/Users/eduards/Desktop/work/data/to-do',
extension='jpg',
callback=self.label_image.configure
)
self.option_menu.grid(row=0, column=0)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5
With my current code, it does not matter whether I click on "Input Folder" - Change or "JukeBox" change the result always gets displayed in "JukeBox" entry. This is incorrect, using class and self how can I change the code to display result from "Input Folder" - Change in "Input Folder" entry and the result from "Jukbox" - Change in "Jukebox" entry?
Also, how can I save the selected folders to a file so that it is there on app exit and re open?
My code:
import os
from tkinter import *
from tkinter import filedialog
inPut_dir = ''
jukeBox_dir = ''
def inPut():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='Input Folder')
inPut_dir = StringVar()
inPut_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, inPut_dir)
def jukeBox():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='JukeBox')
jukeBox_dir = StringVar()
jukeBox_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, jukeBox_dir)
root = Tk()
root.geometry("640x240")
root.title("Settings")
frametop = Frame(root)
framebottom = Frame(root)
frameright = Frame(framebottom)
text = Label(frametop, text="Input Folder").grid(row=5, column=2)
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
text = Label(frametop, text="JukeBox").grid(row=6, column=2)
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
ButtonA = Button(frametop, text="Change", command=inPut).grid(row=5, column=28)
ButtonB = Button(frametop, text="Change", command=jukeBox).grid(row=6, column=28)
ButtonC = Button(frameright, text="OK").grid(row=5, column=20, padx=10)
ButtonD = Button(frameright, text="Cancel").grid(row=5, column=15)
frametop.pack(side=TOP, fill=BOTH, expand=1)
framebottom.pack(side=BOTTOM, fill=BOTH, expand=1)
frameright.pack(side=RIGHT)
root.mainloop()
See attached image:enter image description here
Your code has both:
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
and
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
with jukeBox_dir/row 6 overriding inPut_dir/row 5
Therefore, in def input:
where you have:
entry.insert(0, inPut_dir)
You'll get the result in row 5 (jukebox_dir)