Updating status bar with opened file name - python

With amazing help of other stackoverflow users I have made this code for reading out some data out of a gcode file and doing some calculations on it. It is almost done and the last 2 things I have problem with are:
1) I would like the status bar update to display message "File [name of the uploaded file] is uploaded" after the gcode file will be uploaded with the button.
2) I would like to make executable for the program so it can be standalone and work on Mac OS and Windows. I have downloaded and installed (I am on mac) pyinstaller and I am performing some actions on my .py file, the end result looks like ready applications but they don't work.
Thank you in advance for help and all the inputs, I am a complete newbie in python but I have already learned so much from you.
This is the sample gcode file for tests: sample GCODE
And this is the code:
from tkinter import *
import re
from tkinter import messagebox
from tkinter import filedialog
# Here, we are creating our class, Window, and inheriting from the Frame
# class. Frame is a class from the tkinter module. (see Lib/tkinter/__init__)
class Window(Frame):
# Define settings upon initialization. Here you can specify
def __init__(self, master=None):
# parameters that you want to send through the Frame class.
Frame.__init__(self, master)
#reference to the master widget, which is the tk window
self.master = master
#with that, we want to then run init_window, which doesn't yet exist
self.init_window()
# Load the gcode file in and extract the filament value
def get_filament_value(self, fileName):
with open(fileName, 'r') as f_gcode:
data = f_gcode.read()
re_value = re.search('filament used = .*? \(([0-9.]+)', data)
if re_value:
return float(re_value.group(1))
else:
return 0.0
def read_gcode(self):
root.fileName = filedialog.askopenfilename(filetypes = (("GCODE files", "*.gcode"), ("All files", "*.*")))
volume = self.get_filament_value(root.fileName)
mass = volume * 1.13
price = mass * 0.175
self.volume_text.set('Volume is {:.2f} cm3'.format(volume))
self.mass_text.set('Mass is {:.2f} g'.format(mass))
self.price_text.set('Price is {:.2f} DKK'.format(price))
def client_exit(self):
exit()
def about_popup(self):
messagebox.showinfo("About", "This software is created by Bartosz Domagalski and helps to find used filament parameters from Sli3er generated GCODE")
#Creation of init_window
def init_window(self):
# changing the title of our master widget
self.master.title("Filament Data")
# allowing the widget to take the full space of the root window
self.pack(fill=BOTH, expand=1)
# creating a menu instance
menu = Menu(self.master)
self.master.config(menu=menu)
# create the file object)
file = Menu(menu)
help = Menu(menu)
# adds a command to the menu option, calling it exit, and the
# command it runs on event is client_exit
file.add_command(label="Exit", command=self.client_exit)
help.add_command(label="About", command=self.about_popup)
#added "file" to our menu
menu.add_cascade(label="File", menu=file)
menu.add_cascade(label="Help", menu=help)
#Creating the labels
l_instruction = Label(self, justify=CENTER, compound=TOP, text="Load GCODE file to find volume, \n weight and price of used filament.")
l_instruction.pack()
#Creating the button
gcodeButton = Button(self, text="Load GCODE", command=self.read_gcode)
gcodeButton.pack()
# gcodeButton.place(x=60, y=50)
#Label of the used filament
l1 = Label(self, text="")
l1.pack()
l2 = Label(self, text="")
l2.pack()
l3 = Label(self, text="")
l3.pack()
self.volume_text = StringVar()
l = Label(self, justify=CENTER, compound=BOTTOM, textvariable=self.volume_text)
l.pack()
l4 = Label(self, text="")
l4.pack()
self.mass_text = StringVar()
m = Label(self, justify=CENTER, compound=BOTTOM, textvariable=self.mass_text)
m.pack()
l5 = Label(self, text="")
l5.pack()
self.price_text = StringVar()
p = Label(self, justify=CENTER, compound=BOTTOM, textvariable=self.price_text)
p.pack()
#status Bar
status = Label(self, text="Waiting for file... ", bd=1, relief=SUNKEN, anchor=W)
status.pack(side=BOTTOM, fill=X)
# root window created. Here, that would be the only window, but you can later have windows within windows.
root = Tk()
root.resizable(width=False,height=False);
root.geometry("220x300")
#creation of an instance
app = Window(root)
#mainloop
root.mainloop()

Related

Tkinter GUI does not respond

I'm new to programming and I'm trying to run a program that asks a user for a directory which which they will move their files to.
import tkinter as tk
from tkinter import filedialog, ttk
class Unzip():
def __init__(self):
# initialising the screen name, size title
root = tk.Tk()
root.geometry('650x550')
root.title("Move Files")
root.resizable(0, 0)
root.configure(bg='#002060')
# Initialising the frame to insert our widget
top_frame = tk.Frame(root, bg='#002060')
button_top = tk.Frame(root, bg='#002060')
button_bottom = tk.Frame(root, bg='#002060')
footer_frame = tk.Frame(root, bg='#002060')
top_frame.pack(side='top', fill='both')
button_top.pack(side='top', fill='both')
button_bottom.pack(side='top', fill='both')
footer_frame.pack(side='bottom', fill='both')
# Setting the title name
label_title = tk.Label(top_frame, text='Move Files', font='Arial 36 bold', fg='#948a54',
bg='#002060', pady=60)
label_title.pack(side='top')
# call button to get output file
output_file = ttk.Button(button_bottom, text='Choose location to save files', width=25, command=self.output_path)
output_file.pack(side='left', padx=(120, 10), pady=10)
root.mainloop()
# Get output directory
def output_path(self):
self.output_file_dir = filedialog.askdirectory()
if __name__ == '__main__':
Unzip()
The problem is that when you run the program and try to run the output_file button, the program will not be responding. I decided to use the self because I wanted it to be accessible to other instance methods that I want to create that will use the directory output_path.
So what exactly are you expecting? Your program does respond, but it is not supposed to do anything with the information.
Try
def output_path(self):
self.output_file_dir = filedialog.askdirectory()
print(self.output_file_dir)
Do you see what happens?
Maybe example 2 from this link can help you: https://www.programcreek.com/python/example/95888/tkinter.filedialog.askdirectory

I can't seem to figure out how to update tkinter labels

I'm trying to write a script to accept an image, then process the image and put a grid over it. I haven't merged the script that modifies the image yet. I'm trying to put a front end on this, I'm planning on publishing the script in a DnD facebook group for others to use to overlay grids onto their battlemaps. I can't seem to have the GUI update the labels which display the pixel length of the image the user selects.
import tkinter as tk
from tkinter import filedialog
import imageGrid
import sys
from PIL import *
from PIL import Image
root= tk.Tk()
root.withdraw()
iWidth = tk.StringVar()
iHeight = tk.StringVar()
class pinger(tk.Tk):
def __init__(self, parent):
tk.Tk.__init__(self, parent)
self.parent = parent
self.initialize()
def initialize(self):
self.grid()
button = tk.Button(self,text="exit",command=lambda: closeProgram())
button.grid(column=3,row=9)
buttonOpen = tk.Button(self, text="Select an Image", command= lambda: openExplorer()
)
buttonOpen.grid(column=2, row=2)
labelSig = tk.Label(self, text='By Johnathan Keith, 2020. Ver 1.0')
labelSig.grid(column=3,row=10)
labelImgWidth = tk.Label(self, textvariable=iWidth)
labelImgWidth.grid(column=2,row=3)
labelStaticImg= tk.Label(self, text="Width of image, in pixels: ")
labelStaticImg.grid(column=1,row=3)
labelStaticHeight= tk.Label(self, text="Height of image, in pixels: ")
labelStaticHeight.grid(column=3,row=3)
labelImgHeight = tk.Label(self, textvariable=iHeight)
labelImgHeight.grid(column=4,row=3)
labelWidth = tk.Label(self, text='Enter the width of the grid, in pixels.')
labelWidth.grid(column=4,row=2)
labelDisclaim = tk.Label(self, text='Currently only works with jpegs')
labelDisclaim.grid(column=2, row=1)
def openFile(imagefilename):
Img = Image.open(imagefilename)
height, width = Img.size
iHeight.set(height)
iWidth.set(width)
def closeProgram():
app.destroy()
sys.exit()
def openExplorer():
app.filename= filedialog.askopenfilename(initialdir="/", title="Select an Image", filetypes=(("jpeg files", "*.jpg"),("all files", "*.*")))
if app.filename:
print(app.filename)
pinger.openFile(app.filename)
if __name__ == "__main__":
app = pinger(None)
app.title('Image Gridder')
app.minsize(height=680,width=480)
app.mainloop()
I've been searching through other SE questions and none of them seemed to work with the way my code is written. I'm trying to update the StringVar()'s iWidth and iHeight which will eventually allow the user to specify how they want the grid to overlay the image. I've tried moving them all over the code, in and out of the class, and nothing works. Also, StackExchange kinda butchered the indentation, so don't mind that.
Thank you!
It is because you have two instances of Tk(): root and app (pinger). StringVar iWidth and iHeight are within root scope, other widgets are within app scope. So the content of the StringVars are not shown in widgets within app.
You can remove root stuff and only have app as the only instance of Tk():
import tkinter as tk
from tkinter import filedialog
from PIL import Image
class pinger(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.initialize()
def initialize(self):
self.iWidth = tk.StringVar()
self.iHeight = tk.StringVar()
# row 1
labelDisclaim = tk.Label(self, text='Currently only works with jpegs')
labelDisclaim.grid(column=2, row=1)
# row 2
labelWidth = tk.Label(self, text='Enter the width of the grid, in pixels.')
labelWidth.grid(column=4,row=2)
buttonOpen = tk.Button(self, text="Select an Image", command=self.openExplorer)
buttonOpen.grid(column=2, row=2)
# row 3
labelStaticImg= tk.Label(self, text="Width of image, in pixels: ")
labelStaticImg.grid(column=1,row=3)
labelImgWidth = tk.Label(self, textvariable=self.iWidth)
labelImgWidth.grid(column=2,row=3)
labelStaticHeight= tk.Label(self, text="Height of image, in pixels: ")
labelStaticHeight.grid(column=3,row=3)
labelImgHeight = tk.Label(self, textvariable=self.iHeight)
labelImgHeight.grid(column=4,row=3)
# row 9
button = tk.Button(self,text="exit",command=self.closeProgram)
button.grid(column=3,row=9)
# row 10
labelSig = tk.Label(self, text='By Johnathan Keith, 2020. Ver 1.0')
labelSig.grid(column=3,row=10)
def openFile(self, imagefilename):
Img = Image.open(imagefilename)
height, width = Img.size
self.iHeight.set(height)
self.iWidth.set(width)
def closeProgram(self):
self.destroy()
def openExplorer(self):
filename= filedialog.askopenfilename(initialdir="/", title="Select an Image", filetypes=(("jpeg files", "*.jpg"),("all files", "*.*")))
if filename:
print(filename)
self.openFile(filename)
if __name__ == "__main__":
app = pinger()
app.title('Image Gridder')
app.minsize(height=680,width=480)
app.mainloop()

Tkinter "couldn't open "pyimage1": no such file or directory" error when trying to open an image

I have been trying to add a background image to my Interface but I always get the error:
"couldn't open "pyimage1": no such file or directory"
Also I am pretty new to python.
Already tried multiple methods with tkinter and PIL aswell as tkinter's canvas which didn't work either
This is the whole programm:
import tkinter as tk
from PIL import Image, ImageTk
class MainMenu:
def __init__(self, master):
#creating Main Frame and Window
master.title("Interface")
#Image
image = Image.open(r"Images\matrix.jpg")
photo = ImageTk.PhotoImage(image)
self.background_image = tk.PhotoImage(file=photo)
self.background_label = tk.Label(image=self.background_image)
self.background_label.place(x=0,y=0)
self.background_label.img = self.background_image
#Creating Widgets
self.label1 = tk.Label(master, text="Please Enter the text you would
like encrypted: ")
self.entry1 = tk.Text(master, height=5, width=20)
self.button = tk.Button(master, text="Submit", command=self.Submit)
#Adding Widgets to Grid
self.label1.grid(row=0, column=0, padx=5, pady=5)
self.entry1.grid(row=1, column=0, padx=5, pady=5)
self.button.grid(columnspan=2, pady=10)
#Configuration of Widgets and Main window
master.configure(bg="black")
self.button.configure(bg="light blue")
self.label1.configure(bg="black", fg="light blue")
self.entry1.configure(bg="light blue")
def Submit(self):
print("You entered: " + self.entry1.get())
root = tk.Tk()
Mm = MainMenu(root)
root.mainloop()
The main problem would be within these lines I am guessing:
image = Image.open(r"Images\matrix.jpg")
photo = ImageTk.PhotoImage(image)
self.background_image = tk.PhotoImage(file=photo)
self.background_label = tk.Label(image=self.background_image)
self.background_label.place(x=0,y=0)
self.background_label.img = self.background_image
As you can see I am trying to make an Interface or GUI and everything is working fine except the background image.
Try this:
image = Image.open("Images\matrix.jpg")
photo = ImageTk.PhotoImage(image)
#self.background_image = tk.PhotoImage(file=photo) -- Not needed, delete
self.background_label = tk.Label(image=photo)
self.background_label.image = photo
self.background_label.place(x=0,y=0)
#self.background_label.img = self.background_image -- Also not needed, delete
As far as I can tell this simply means you have used 'tk.PhotoImage' twice on a variable.
For example:
item1_image = tk.Label()
image = tk.PhotoImage('image.png')
item1_image.configure(image=tk.PhotoImage(image))
When you're pulling these variables out of different places in a large file, it is hard to keep track of whether 'PhotoImage' is used. I typically use it as early as possible to avoid the image not appearing.

Python Tk Label Error with StringVar

I'm going to create a program that resembles the image below. The interface uses one text entry for a name, one button, and two labels. The button should have the text Say hello and when the user clicks the button, the bottom label should display the name with Hi in front of it (see image below)
Here's what I've got
from tkinter import *
from tkinter.ttk import *
def say_hello():
name_var.set(name_entry.get())
def main():
global window, name_var, name_entry
window = Tk()
top_label = Label(window, text='Enter a name below')
top_label.grid(row=0, column=0)
name_var = StringVar()
name_entry = Entry(window, textvariable=name_var)
name_entry.grid(row=1, column=0)
hello_button = Button(window, text='Say hello', command=say_hello)
hello_button.grid(row=2, column=0)
bottom_label = Label(window, text='Hi ' + name_var)
bottom_label.grid(row=3, column=0)
window.mainloop()
main()
When I try to run it I get this error:
Traceback (most recent call last): File "C:\Program Files (x86)\Wing IDE 101 5.1\src\debug\tserver_sandbox.py", line 29, in <module> File "C:\Program Files (x86)\Wing IDE 101 5.1\src\debug\tserver_sandbox.py", line 24, in main builtins.TypeError: Can't convert 'StringVar' object to str implicitly
Everything works GUI wise, I'm just not sure how to get the last label that says "Hi Jack" to come up after pressing the button — i.e what my command should be in the hello_button line.
Here's your offensive code:
bottom_label = Label(window, text='Hi ' + name_var)
You can't really add a string and an instance of a class. A Tkinter StringVar isn't actually a string, but like a special thing for the gui to hold a string. That's why it can update automatically and stuff like that. Solution is simple:
bottom_label = Label(window, text = 'Hi ' + name_var.get())
Here's how I did it:
#!/usr/bin/env python2.7
import Tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
self.name_var = tk.StringVar()
tk.Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
self.top_label = tk.Label(self, text='Enter a name below')
self.top_label.grid(row=0, column=0)
self.name_entry = tk.Entry(self)
self.name_entry.grid(row=1, column=0)
self.hello_button = tk.Button(self, text='Say hello', command=self.say_hello)
self.hello_button.grid(row=2, column=0)
self.output = tk.Label(self, textvariable=self.name_var)
self.output.grid(row=3, column=0)
def say_hello(self):
self.name_var.set("Hi {}".format(self.name_entry.get()))
root = tk.Tk()
app = Application(master=root)
app.mainloop()
Ultimately it was very similar to your code. The only thing you were missing was how to use Tkinter.StringVar() correctly. You need to set the bottom label's textvariable to name_var when you create it, and then you should be good to go.
This simple class should do what you want:
from tkinter import Button, Tk, Entry,StringVar,Label
class App():
def __init__(self, **kw):
self.root = Tk()
# hold value for our output Label
self.s = StringVar()
# label above our Entry widget
self.l = Label(self.root, text="Enter name here").pack()
# will take user input
self.e = Entry(self.root)
self.e.pack()
self.b = Button(self.root, text="Say Hello",command=self.on_click).pack()
# textvariable points to our StringVar
self.l2 = Label(self.root, textvariable=self.s).pack()
self.root.mainloop()
# every time the Button is pressed we get here
# an update the StringVar with the text entered in the Entry box
def on_click(self):
self.s.set(self.e.get())
App()
You just need to create a couple of Labels, and Entry widget to take the name and a callback function to update the StringVar value so the label/name value gets updated.

Tkinter store entry box value as value for other file

This is my first python personal project. I am wanting to use Tkinter to create a window (GUARDIAN LOCATOR) that asks the user to input a value (enter sailor guardian) into the entry box. The rest of the program is dependent on what the user types in the entry box as I will be having if/else statements reacting to the sailor guardian entered.
The issue I am having is storing what is entered in the entry box as a variable to use in my main file for the if/else statements. I can get the value to print to the prompt window, but I haven't been able to store it successfully to a global variable.
My Tkinter window is in it's own class.
I have tried many different ways of doing this based on similar issues from stackoverflow, but I am getting an error every time. This is my base code that still produces the error.
Class file with the Tkinter window
class GuardianLocator:
def __init__(self, master):
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
print(self.entry.get())
and in my main working file
root = Tk()
locator = guardian_locator.GuardianLocator(root)
root.mainloop()
This is my test loop to see if it's working.
if locator.guardian_input() is "Sailor Moon":
print("hi")
else:
print("no")
Not sure exactly how your code is organized and where is your "test loop" located, but I assume it is after root.mainloop(). Thus the script can be as follows:
from tkinter import *
class GuardianLocator:
def __init__(self, master):
self._name = ""
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
self._name = self.entry.get()
print(self.entry.get())
root = Tk()
locator = GuardianLocator(root)
root.mainloop()
# this will be executed after the root window is closed.
print("Name is", locator._name)
Please note self._name = "" in the constructor. This instance variable can be used to store the name provided in your GuardianLocator window.

Categories

Resources