Horizontally scrollable column in tkinter using nested frames - python

I am using the grid geometry manager to create a table with the following widget structure:
Radiobuttons in columns 0 and 1
Horizontally scrollable Text (representing potentially long file names) in column 2
and progress bars in column 6 (with numerical values for columns 3 - 5 to be filled in later).
It's the horizontally scrollable Text that's giving me trouble. I tried creating a Listbox widget that lives in column 2 (as a child of the overall frame) and spans all the rows. This seemed promising, until it became apparent that the lines of text in the Listbox are not aligned with the rows of the parent grid.
I've been searching in vain for a way to pad each row of text in the Listbox so that the rows match up; but even if that were possible, I would prefer a more general, less kludgy solution.
Is there perhaps an easy way to make a single column scrollable that I'm missing? Is setGrid a possible solution?
(In order to see the problem with the code below, use the Select File or Select Folder buttons to load multiple audio files into the file list.)
#! /usr/bin/env python
#################################################
# This tool allows the user to select audio files
# (or folders containing audio files) and subject
# them to loudness analysis.
#################################################
import sys
import os
import codecs
import re
import Tkinter
from Tkinter import *
import tkFileDialog
from os import walk
from os import path
from Tkinter import Tk, Text, BOTH, W, N, E, S
from ttk import Frame, Button, Label, Style, Progressbar
from ScrolledText import *
from progressbar import ProgressBar
class Leveler_tk(Frame):
fileList = []
allowedExtensions = ['mp3','mp2','m4a','aiff','wav']
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initialize()
def initialize(self):
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(2,weight=1)
self.columnconfigure(2,pad=250)
self.columnconfigure(3, weight=1)
self.columnconfigure(4, weight=1)
self.columnconfigure(5, weight=1)
lbl1 = Label(self, text="Analyze")
lbl1.grid(pady=4, padx=5,row=0,column=0)
lbl2 = Label(self, text="Adjust")
lbl2.grid(pady=4, padx=5,row=0,column=1)
lbl3 = Label(self, text="File")
lbl3.grid(pady=4, padx=5,row=0,column=2)
lbl4 = Label(self, text="Integrated\nLoudness")
lbl4.grid(pady=4, padx=5,row=0,column=3)
lbl5 = Label(self, text="LRA")
lbl5.grid(pady=4, padx=5,row=0,column=4)
lbl6 = Label(self, text="Peak")
lbl6.grid(pady=4, padx=5,row=0,column=5)
lbl7 = Label(self, text="Progress")
lbl7.grid(pady=4, padx=5,row=0,column=6)
lbl8 = Label(self, text="Meets\nSpecs?")
lbl8.grid(sticky=W, pady=4, padx=5,row=0,column=7)
file_btn = Button(self, text="Select File",command=self.selectFile)
file_btn.grid(row=1,rowspan=2, column=8,padx=5,pady=4)
folder_btn = Button(self, text="Select Folder", command=self.selectFolder)
folder_btn.grid(row=3, rowspan=2, column=8,padx=5,pady=4)
def render(self):
count = 0
filebox = Listbox(self,selectmode=EXTENDED,setgrid=1)
scrollbar = Scrollbar(filebox, orient=HORIZONTAL)
scrollbar.config(command=filebox.xview)
filebox.grid(row=1, column=2, rowspan=len(self.fileList), columnspan=1, sticky=N+S+E+W)
filebox.config(xscrollcommand=scrollbar.set)
scrollbar.pack(side=BOTTOM, fill=X)
for file in self.fileList:
analyze = IntVar()
adjust = IntVar()
Radiobutton(self, text="", variable=analyze, value=count, borderwidth=0).grid(row=count+1, column=0)
Radiobutton(self, text="", variable=adjust, value=count, borderwidth=0).grid(row=count+1, column=1)
filebox.insert(END, file + "\n")
Progressbar(self, orient=HORIZONTAL,length=100, mode='determinate').grid(row=count+1, column=6)
count += 1
def addToList(self, name):
dot = re.search("\.(?=[^.]*$)",name)
extension = name[dot.end():]
if extension in self.allowedExtensions and not name in self.fileList:
self.fileList.append(name)
def selectFile(self):
input = tkFileDialog.askopenfilename(filetypes = [('MP3', '*.mp3'), ('MP2', '*.mp2'), ('M4A', '*.m4a'), ('AIFF', '*.aiff'), ('WAV', '*.wav')], multiple = 1)
for el in input:
if os.path.isfile(el) and ".DS_Store" not in el:
try:
self.addToList(el)
except:
tkMessageBox.showerror("Some error")
self.render()
def selectFolder(self):
input = tkFileDialog.askdirectory()
for (dirpath, dirnames, filenames) in walk(input):
for name in filenames:
if name != ".DS_Store":
self.addToList(dirpath + "/" + name)
self.render()
def main():
root = Tk()
app = Leveler_tk(root)
root.mainloop()
if __name__ == "__main__":
main()

Related

Adding a header line to a scrollable canvas with weights

I'm trying get a list of .xlsm files from a folder, and generate a scrollable canvas from which the tabs needed for import can be selected manually using the check buttons (all having the same tab format e.g. tab1, tab2, tab3, tab4).
The major issue I'm having is getting weights to work correctly for the headers in relation to their canvas columns, as longer file names distorts the weight.
I've tried playing with the weights and can't seem to figure out a workaround. I also attempted using treeview as an alternative but this seems to introduce far bigger issues with using checkbuttons. Would it possible to freeze the top row if the headers were placed inside the canvas itself, or could I implement something like a bind so that the header frames individual columns align with the width of the columns of the canvas frame?
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
class MainFrame:
def __init__(self, master):
master.geometry('1000x200')
self.master_tab = ttk.Notebook(master)
self.master_tab.grid(row=0, column=0, sticky='nsew')
# Sub-Classes
self.file_select = FileSelect(self.master_tab, main=self)
class FileSelect:
def __init__(self, master, main):
self.main = main
# ================== Primary Frame ==================
self.primary_frame = tk.Frame(master)
self.primary_frame.grid(row=0, column=0, sticky='NSEW')
master.add(self.primary_frame, text='Import Selection')
self.primary_frame.columnconfigure(0, weight=1)
self.primary_frame.rowconfigure(1, weight=1)
# ================== File Selection Frame ==================
self.selection_frame = tk.Frame(self.primary_frame)
self.selection_frame.grid(row=0, column=0, sticky='EW')
# Button - Select Directory
self.fp_button = tk.Button(self.selection_frame, text='Open:', command=self.directory_path)
self.fp_button.grid(row=0, column=0, sticky='W')
# Label - Display Directory
self.fp_text = tk.StringVar(value='Select Import Directory')
self.fp_label = tk.Label(self.selection_frame, textvariable=self.fp_text, anchor='w')
self.fp_label.grid(row=0, column=1, sticky='W')
# ================== Canvas Frame ==================
self.canvas_frame = tk.Frame(self.primary_frame)
self.canvas_frame.grid(row=1, column=0, sticky='NSEW')
self.canvas_frame.rowconfigure(1, weight=1)
# Canvas Header Labels
for header_name, x in zip(['File Name', 'Tab 1', 'Tab 2', 'Tab 3', 'Tab 4'], range(5)):
tk.Label(self.canvas_frame, text=header_name, anchor='w').grid(row=0, column=x, sticky='EW')
self.canvas_frame.columnconfigure(x, weight=1)
# Scroll Canvas
self.canvas = tk.Canvas(self.canvas_frame, bg='#BDCDFF')
self.canvas.grid(row=1, column=0, columnspan=5, sticky='NSEW')
self.canvas.bind('<Configure>', self.frame_width)
# Scrollbar
self.scroll_y = tk.Scrollbar(self.canvas_frame, orient="vertical", command=self.canvas.yview)
self.scroll_y.grid(row=1, column=5, sticky='NS')
# Canvas Sub-Frame
self.canvas_sub_frame = tk.Frame(self.canvas)
for x in range(5):
self.canvas_sub_frame.columnconfigure(x, weight=1)
self.canvas_frame_window = self.canvas.create_window(0, 0, anchor='nw', window=self.canvas_sub_frame)
self.canvas_sub_frame.bind('<Configure>', self.config_frame)
def config_frame(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox('all'), yscrollcommand=self.scroll_y.set)
def frame_width(self, event):
canvas_width = event.width
event.widget.itemconfigure(self.canvas_frame_window, width=canvas_width)
def directory_path(self):
try:
# Select file path
directory = filedialog.askdirectory(initialdir='/', title='Select a directory')
self.fp_text.set(str(directory))
os.chdir(directory)
# Updates GUI with .xlsm file list & checkboxes
if len(os.listdir(directory)) != 0:
y = -1
for tb in os.listdir(directory):
if not tb.endswith('.xlsm'):
print(str(tb) + ' does not have ;.xlsm file extension')
else:
y += 1
file_name = tk.Label(self.canvas_sub_frame, text=tb, anchor='w', bg='#96ADF3')
file_name.grid(row=y, column=0, sticky='EW')
for x in range(4):
tb_period = tk.Checkbutton(self.canvas_sub_frame, anchor='w', bg='#C2D0F9')
tb_period.grid(row=y, column=x+1, sticky='EW')
else:
print('No files in directory')
# Filepath error handling exception
except os.error:
print('OS ERROR')
if __name__ == '__main__':
root = tk.Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
MainFrame(root)
root.mainloop()
The simplest solution is to use two canvases, and then set up a binding so that whenever the size of the inner frame changes, you update the headers to match the columns.
It might look something like this:
def config_frame(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox('all'), yscrollcommand=self.scroll_y.set)
self.canvas.after_idle(self.reset_headers)
def reset_headers(self):
for column in range(self.canvas_sub_frame.grid_size()[0]):
bbox = self.canvas_sub_frame.grid_bbox(column, 0)
self.canvas_frame.columnconfigure(column, minsize = bbox[2])

How do I make the "plus sign" in Treeview follow indentations?

So, I am trying to make a database program for my needs, and to make it more visible attractive I want the plus sign to follow indentation from the files and folders it reads from a database? This is going to be a parent/child kind of view.
Here is what I want:
The open and closing +/- symbol follows the filename
The code for this I found during researching into this exact problem, but I cant differentiate the code to figure out what I am doing wrong.
Here is what I currently have:
Not following, and it seems to be appearing on its separate columns.
I've tried to add and remove columns, because to me, it seems like the problem is that they are being printed to their own column.
Here is my code (The code I found when searching is pasted at the bottom, I'm sorry to the author, I didnt make a not of where I found it.) (If you run it the scrollbar is way off btw..):
class FiletreeInfoApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
width = self.root.winfo_screenwidth()
height = self.root.winfo_screenheight()
self.root.geometry("%dx%d+0+0" % (width, height))
# Window Title
app_title = "File Structure Info"
self.root.title(app_title)
# Upper and lower Frames
self.upper_frame = ttk.Frame(self.root, relief="sunken", height=120)
self.upper_frame.pack(fill="x", pady=15, padx=30)
self.lower_frame = ttk.Frame(self.root, relief="sunken")
self.lower_frame.pack(fill="both", padx=15, pady=15, expand=True)
# Lower frames' Treeview
self.db_reader = ttk.Treeview(self.lower_frame, columns=("#0"), height=8)
ysb = ttk.Scrollbar(self.db_reader, orient='vertical', command=self.db_reader.yview)
xsb = ttk.Scrollbar(self.db_reader, orient='horizontal', command=self.db_reader.xview)
self.db_reader.configure(yscroll=ysb.set, xscroll=xsb.set)
self.db_reader.heading('#0', text='Path', anchor='w')
self.db_reader.column('#0', minwidth=25, width=70)
self.db_reader.pack(padx=30, pady=30, fill="both", side="left", expand=True)
ysb.pack(fill="y", anchor="e")
xsb.pack(fill="x", anchor="s")
self.info_entry = ttk.Entry(self.lower_frame)
self.info_entry.pack(side="right", fill="both", expand=True)
If I also try to remove the "columns="#0"" from the creation of the Treeview widget, I get what I want, but then nothing show up. Every entry is blank.
Every entry is blank, but indentation seems fine, just need the text in there
Here is the code I found:
import os
try:
# Python2
import Tkinter as tk
import ttk
except ImportError:
# Python3
import tkinter as tk
import tkinter.ttk as ttk
class DirectoryBrowser(tk.Frame):
def __init__(self, master, path):
self.path = os.path.abspath(path)
self.entries = {"": self.path}
self.root = None
# setup treeview and scrollbars
tk.Frame.__init__(self, master)
self.tree = ttk.Treeview(self)
ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
self.tree.heading('#0', text='Path', anchor='w')
self.tree.bind("<<TreeviewSelect>>", self.update_subtree)
# fill treeview with root dir and the subdirs
iid = self.insert("", "end", self.path)
self.tree.focus(iid)
self.process_directory(iid, self.path)
# add tree and scrollbars to frame
self.tree.grid(in_=self, row=0, column=0, sticky="nsew")
ysb.grid(in_=self, row=0, column=1, sticky="ns")
xsb.grid(in_=self, row=1, column=0, sticky="ew")
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.Y)
# testing ...
# returns a list of children belonging to last iid
print(self.tree.get_children(iid))
def insert(self, parent, index, path, name="", **kwargs):
"""
add new element to TreeView
"""
if "text" in kwargs:
err = "arg 'text' not available"
raise ValueError(err)
kwargs["text"] = path
if name:
kwargs["text"] = name
iid = self.tree.insert(parent, index, **kwargs)
self.entries[iid] = path
return iid
def process_directory(self, parent, path, depth=3):
if depth == 0:
return
for p in os.listdir(path):
abspath = os.path.join(path, p)
if os.path.isdir(abspath):
iid = self.insert(parent,
'end',
path=abspath,
name=p,
open=False)
self.process_directory(iid, abspath, depth-1)
# Callbacks
def update_subtree(self, event):
iid = self.tree.focus()
path = self.entries[iid]
print("%s: %s" % (iid, path))
print(iid in self.entries.keys())
#self.process_directory(iid, path)
def test():
root = tk.Tk()
mypath = "F:\\Github_bittib010"
app = DirectoryBrowser(root, path=mypath)
# testing ...
print(app.tree.get_children()) # returns root children
app.mainloop()
if __name__ == "__main__":
test()
Edit as answer to a question.
I used a for loop in its own function to open, add, commit and close. Here is the for-loop and the sqlite statement:
'''
# Execute command
c.execute("SELECT * FROM Windows10")
records = c.fetchall()
# Add data to ttk treeview
counter = 0
for record in records:
self.db_reader.insert('', tk.END, values=record[1], iid=record[0], open=False)
if counter != 0:
self.db_reader.move(record[0], record[5], counter)'''

Cannot create Entry widget with tkinter

I'm having some trouble creating an entry widget with tkinter. I've imported the necessary modules and have already created several buttons and check boxes. However I cannot figure out how to properly initialize the Entry. Here is my relevant code:
# Necessary Modules.------------------------------------------------------------
import win32com.client as win32
import re
from tkinter import *
from tkinter.filedialog import askopenfilename
import tkinter.messagebox
# Class for selecting the file.-------------------------------------------------
class FilenameClass():
def __init__(self):
self.location = 'User Import.txt'
def getFile(self, identity):
self.file_opt = options = {}
options['defaultextension'] = '.txt'
options['filetypes'] = [('Text Document (.txt)', '.txt'),
('all files', '.*')]
self.filename = askopenfilename(**self.file_opt)
if self.filename:
if 'User Import' in identity:
self.location = self.filename
app.get_txt_File['bg'] = '#0d0'
user_file = open(self.filename, 'r')
user_total = user_file.read()
remove_lines = user_total.splitlines()
for user in remove_lines:
regex_tab = re.compile('\\t')
user_info = regex_tab.split(user)
app.users.append(user_info)
else:
app.loadButton['bg'] = '#e10'
# Main Class.-------------------------------------------------------------------
class Application(Frame, Tk):
def __init__(self, master=None):
Frame.__init__(self, master)
self.users = []
self.fileOBJtxt = FilenameClass()
self.createWidgets()
def createWidgets(self):
# Define the default values for the options for the buttons
# Grid layout options
self.rowconfigure(0, minsize=5)
self.width = 54
self.grid(padx=5)
self.loadButton_gopt = {'row':1,'column':1,'padx': 2, 'pady': 5}
self.loadButton_wopt = {'width': round(self.width),'bg':'#e10'}
self.loadButton()
self.trainingCheckBox()
self.signatureInput()
def loadButton(self):
'''Button that calls the filename class which allows the user to select
the text file they wish to use.'''
self.get_txt_File = Button(self, text="Load User List", \
command=lambda: self.fileOBJtxt.getFile('User Import'))
for key, value in self.loadButton_wopt.items():
self.get_txt_File[key] = value
self.get_txt_File.grid(**self.loadButton_gopt)
def trainingCheckBox(self):
self.training_var = IntVar()
self.training = Checkbutton(text="Include training video?", \
variable=self.training_var).grid(row=2, sticky=W)
def signatureInput(self):
Label(text="Signature Name").grid(row=4, sticky=W)
entry = Entry(bg='#fff', width=50)
entry.grid(row=4, column=1, columnspan=4)
# Initialization parameters.----------------------------------------------------
if __name__ == '__main__':
app = Application()
app.master.title('User Notification Tool')
app.master.geometry('405x550+100+100')
app.master.resizable(width=False, height=False)
app.mainloop()
I'm not seeing any tracebacks, but I can't seem to get my Entry box to show up. What am I doing wrong?
EDIT: added entire code.
The problem with your entry field is you have not told it what frame/window to be placed in.
Change:
entry = Entry(bg='#fff', width=50)
To:
entry = Entry(self, bg='#fff', width=50)
Make sure you always provide the window/frame that a widget is going to be placed in as the first argument. In this case it is self as self refers to a frame.
Keep in mind that your program will not be able to get() the string inside of your entry field because you have not defined it as a class attribute. So most likely you will need to change
This:
entry = Entry(bg='#fff', width=50)
entry.grid(row=4, column=1, columnspan=4)
To This:
self.entry = Entry(self, bg='#fff', width=50)
self.entry.grid(row=4, column=1, columnspan=4)
This change will be necessary in order for the rest of your application to be able to read or write to the entry widget.
Change
entry = Entry(bg='#fff', width=50)
to
entry = tk.Entry(bg='#fff', width=50)

Updating status bar with opened file name

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()

How can I save the output of a python function that I run using a Tkinter button?

I created a program that creates a heatmap from text files containing the x, y, z (z is always 0), and intensity values for each pixel in a 201 x 201 pixel area. I'm now trying to use Tkinter to create a GUI that will allow me to browse for a text file, and then display the heatmap for the file that I choose, but I'm running into a few issues. Here's the code that I have so far:
import numpy as np
import matplotlib
import matplotlib.cm as cm
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import Tkinter as tk
import ttk as ttk
from tkFileDialog import askopenfilename
f = Figure(figsize=(5,5), dpi=100)
a = f.add_subplot(111)
a.clear()
def Separate(image):
'''Separate columns of text file into arrays'''
img = np.loadtxt(image)
intensity = np.array(image[:,0])
x = np.array(image[:,1])
y = np.array(image[:,2])
z = np.array(image[:,3])
return intensity, x, y, z
def constructImage(intensity, x, y):
'''Create a heatmap of the data'''
lenx = int(np.amax(x) - np.amin(x) + 1)
leny = int(np.amax(y) - np.amin(y) + 1)
intensity2 = intensity.reshape(lenx, leny)
a.clear()
a.imshow(intensity2, extent = (np.amin(x), np.amax(x), np.amin(y), np.amax(y)))
def SeparateandConstruct(image):
img = np.loadtxt(image)
intensity, x, y, z = Separate(img)
constructImage(intensity, x, y)
LARGE_FONT= ("Verdana", 12)
def callback():
'''Opens text file and runs Separate function'''
name = askopenfilename()
return name
class Application(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = ImageConstructor(container, self)
self.frames[ImageConstructor] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(ImageConstructor)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
#Image Constructor Frame
class ImageConstructor(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
#Title Label
label = ttk.Label(self, text="Image Constructor", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#Button to browse for a text file
browseButton = ttk.Button(self, text="Browse", command=callback)
browseButton.pack()
#Label displaying the path to the selected text file
filePath = ttk.Label(self, text="No File Selected", font=LARGE_FONT)
filePath.pack()
#Button that creates an image of the selected text file
constructButton = ttk.Button(self, text="Construct Image")
constructButton.pack()
#Canvas for the heatmap
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
#Button to close the program
quitButton = ttk.Button(self, text="Quit", command=controller.destroy)
quitButton.pack()
def main():
app = Application()
app.mainloop()
if __name__ == '__main__':
main()
The problem I'm having, is that I'm not sure how to save the output of the callback function after I use the browse button. I would like to have the filePath label update to display the file path to the selected text file and I also want to have the constructButton apply the SeparateandConstruct function to the text file that I choose, but I have no idea how to save the output of the callback function. Is there any way to save the output from a function to a variable if I run it using a tkinter button? I feel like this would be really easy to get working if I knew how to do that, but I haven't been able to figure it out.
Here's a short demo of how to make a callback modify a class instance attribute. The key idea is to make the callback a method of the class, so it can access the class's attributes.
Here I'm using it to update a tk.StringVar which is attached to the filename Label.
import Tkinter as tk
from tkFileDialog import askopenfilename
class Demo(object):
def __init__(self):
master = tk.Tk()
frame = tk.Frame(master)
frame.pack()
b = tk.Button(frame, text="Browse", command=self.getfilename_cb)
b.pack()
self.filename = tk.StringVar()
self.filename.set("No File Selected")
l = tk.Label(frame, textvariable=self.filename)
l.pack()
master.mainloop()
def getfilename_cb(self):
fname = askopenfilename()
if fname:
self.filename.set(fname)
Demo()

Categories

Resources