How to execute some code after changing tabs in tkinter? - python

I created an gui interface with tkinter which contains notebook tabs, the first tabs contains input file to upload csv file, in the second tab I want to read the uploaded file and show results, the problem is the content of the second tab was executed on loading the gui interface, how can I can execute the content of second tab only when the file was uploaded?
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
import os
import importlib
import csv
import os.path
class Notebook:
def __init__(self):
self.root = Tk()
self.root.title('Traitement fichier csv')
self.build_Menu()
self.build_NoteBook()
self.build_page_1()
self.build_page_2()
self.root.mainloop()
def build_Menu(self):
# MENU WIDGET CONFIGURATION
self.menu = Menu(self.root)
self.root.configure(menu=self.menu)
self.filemenu = [None] * 3
for f in range(1,3):
self.filemenu[f] = Menu(self.menu,tearoff=False)
#FILE MENU
self.menu.add_cascade(label='File', menu=self.filemenu[1])
for i in ['New','Open','Exit']:
if i == 'New':
self.filemenu[1].add_command(label=i,command=self.Add_New_Tab)
elif i == 'open':
self.filemenu[1].add_command(label=i,command=self.filedialog)
elif i == 'Exit':
self.filemenu[1].add_command(label=i,command=quit)
else:
self.filemenu[1].add_command(label=i)
# ADD NEW TAG CODE
def Add_New_Tab(self):
for k in range(2,3):
self.notebook.add(self.tab[k],text=f'Page {k}')
def build_NoteBook(self):
# NOTEBOOK WIDGET CONFIGURATION
self.notebook = ttk.Notebook(self.root,height=400,width=800)
self.tab = [None] * 10
global t
for t in range(1,10):
self.tab[t] = ttk.Frame(self.notebook)
self.notebook.add(self.tab[1],text='Importation des donnees',underline=0)
self.notebook.add(self.tab[2], text='Affichage des donnees apres traitement ')
# self.notebook.add(self.tab[3], text='Page 3')
# self.notebook.add(self.tab[4], text='Page 4')
self.notebook.pack(fill=BOTH, expand=YES, padx=5, pady=5)
#PAGE ONE CONTENTS
def build_page_1(self):
ttk.Button(self.tab[1], text='Ouvrir un fichier csv', command=self.filedialog).pack(side=LEFT,anchor=CENTER,padx=90,pady=5,fill=X,expand=1)
#ttk.Button(self.tab[1], text='close', command=quit).pack(side=LEFT, padx=90, fill=X, anchor=CENTER,expand=1)
def filedialog(self):
self.filename= filedialog.askopenfilename(initialdir = "/",title = "Select a file",filetypes = (("csv files","*.csv"),("all files","*.*")))
print(self.filename)
#os.system('python deleteNull.py')
#global filename
#filename=self.filename
importlib.import_module("deleteNull")
def build_page_2(self):
data = []
path="C:/Users/ThinkPad/Desktop/Python/fout.csv"
if(os.path.exists(path)):
input_file = 'fout.csv'
with open(input_file, "r") as source:
reader = csv.reader(source)
next(reader, None) # skip the headers
for row in reader:
data.append( [row[0], row[1],row[2],row[3],row[4]])
tree = ttk.Treeview(self.tab[2], columns = (1,2,3,4,5), height = 50, show = "headings")
tree.pack(side = 'left')
tree.heading(1, text="Matricule")
tree.heading(2, text="Date Inscription")
tree.heading(3, text="Cycle")
tree.heading(4, text="Specialité")
tree.heading(5, text="Durée cursus")
tree.column(1, width = 150)
tree.column(2, width = 150)
tree.column(3, width = 150)
tree.column(4, width = 150)
tree.column(5, width = 180)
scroll = ttk.Scrollbar(self.tab[2], orient="vertical", command=tree.yview)
scroll.pack(side = 'right', fill = 'y')
tree.configure(yscrollcommand=scroll.set)
for val in data:
tree.insert('', 'end', values = (val[0], val[1], val[2],val[3],val[4]) )
if __name__ == '__main__':
Notebook()

Related

tkinter, unable to call a function from outside of it's class

Put simply, i cannot call filterCBOs from the marked problem area within my program. It returns:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Anaconda\envs\SE_win64_py35\lib\tkinter\__init__.py", line 1550, in __call__
return self.func(*args)
File "<ipython-input-24-b9ade6a4c197>", line 116, in callFilters
Root.filterCBOs(self)
File "<ipython-input-24-b9ade6a4c197>", line 164, in filterCBOs
startDate = dt.datetime(year=int(self.fromDate.get()[2]),month=int(self.fromDate.get()[0]),day=int(self.fromDate.get()[1]))
AttributeError: 'Event' object has no attribute 'fromDate'
As you can see, this function works exactly as it should when it is called within init as well as when it is called by selecting a combobox value. It however does not work when it is called by binding the enter key to the entry fields within DateEntry. I am brand new to classes so im sure its something to do with it being called from within another class but I am lost as to how to navigate around this.
#================================================================================
# Imports
#================================================================================
import os
import pandas as pd
import datetime as dt
import tkinter as tk
from tkinter import ttk
startTimestamp=dt.datetime.now()
print('Starting ' + str(startTimestamp))
#================================================================================
# User Changable Variables
#================================================================================
#signaturePath = r'T:\Process Data\EDM\Signature Files'
#================================================================================
# Functions (mostly used to cleanup variables)
#================================================================================
#commented out because i ran this section once and saved to csv. saves me from indexing
#the directory during testing.
'''
def indexDirectory():
#filenames use the following format:
# yyyy.mm.dd.hh.mm.tool.toolSN.feature.sfc.sig
df = pd.DataFrame(columns=['FullPath', 'Timestamp', 'Feature', 'Machine', 'Tool'])
for root, dirs, files in os.walk(signaturePath):
for file in files:
splitter = file.split('.')
if len(splitter) != 10: #weird filename
continue #skip to next file
date=dt.datetime.strptime(splitter[0]+'-'+splitter[1]+'-'+splitter[2]+' '+splitter[3]+':'+splitter[4],'%Y-%m-%d %H:%M')
df = df.append({'FullPath' : os.path.join(root, file), \
'Timestamp' : date, \
'Feature' : splitter[7], \
'Machine' : os.path.basename(root), \
'Tool' : splitter[5] + '_' + splitter[6] \
}, ignore_index=True)
return df
with open(r'C:\Users\u1106710\Desktop\Index.csv', 'w+') as SaTemp:
indexDirectory().to_csv(SaTemp, header=True, index=False)
'''
# Index available signature files to a dataframe
#sigIndex=indexDirectory
sigIndex=pd.read_csv(r'D:\Tibbert\4) Scripts\Signature Analysis\Temp\Index.csv')
sigIndex['Timestamp'] = pd.to_datetime(sigIndex['Timestamp'])
#================================================================================
# Build GUI
#================================================================================
class DateEntry(tk.Frame):
def __init__(self, master, frame_look={}, **look):
args = dict(relief=tk.SUNKEN, border=1)
args.update(frame_look)
tk.Frame.__init__(self, master, **args)
args = {'relief': tk.FLAT}
args.update(look)
self.entry_1 = tk.Entry(self, width=2, **args)
self.label_1 = tk.Label(self, text='/', **args)
self.entry_2 = tk.Entry(self, width=2, **args)
self.label_2 = tk.Label(self, text='/', **args)
self.entry_3 = tk.Entry(self, width=4, **args)
self.entry_1.pack(side=tk.LEFT)
self.label_1.pack(side=tk.LEFT)
self.entry_2.pack(side=tk.LEFT)
self.label_2.pack(side=tk.LEFT)
self.entry_3.pack(side=tk.LEFT)
self.entries = [self.entry_1, self.entry_2, self.entry_3]
self.entry_1.bind('<KeyRelease>', lambda e: self._check(0, 2))
self.entry_2.bind('<KeyRelease>', lambda e: self._check(1, 2))
self.entry_3.bind('<KeyRelease>', lambda e: self._check(2, 4))
#PROBLEM HERE!
#self.entry_1.bind('<Return>', Root.filterCBOs)
#self.entry_2.bind('<Return>', Root.filterCBOs)
#self.entry_3.bind('<Return>', Root.filterCBOs)
def _backspace(self, entry):
cont = entry.get()
entry.delete(0, tk.END)
entry.insert(0, cont[:-1])
def _check(self, index, size):
entry = self.entries[index]
next_index = index + 1
next_entry = self.entries[next_index] if next_index < len(self.entries) else None
data = entry.get()
if len(data) > size or not data.isdigit():
self._backspace(entry)
if len(data) >= size and next_entry:
next_entry.focus()
def get(self):
return [e.get() for e in self.entries]
class Root(tk.Tk):
def __init__(self):
super(Root, self).__init__()
self.title("Filmcool Siganture Analysis")
self.minsize(width=800,height=600)
self.InitUI()
self.filterCBOs()
def InitUI(self):
#Setup Date Entry
self.fromDateLBL = tk.Label(self, text='Date Range')
self.fromDate = DateEntry(self)
self.toDateLBL = tk.Label(self, text='To')
self.toDate = DateEntry(self)
#Set Date Defaults
self.fromDate.entry_1.insert(0,'01')
self.fromDate.entry_2.insert(0,'01')
self.fromDate.entry_3.insert(0,'2014')
self.toDate.entry_1.insert(0,dt.date.today().month)
self.toDate.entry_2.insert(0,dt.date.today().day)
self.toDate.entry_3.insert(0,dt.date.today().year)
#Setup Feature Combobox
self.featureLBL = tk.Label(self, text='Feature')
self.featureCBO = ttk.Combobox(self, width=15)
self.featureCBO.bind('<<ComboboxSelected>>', self.filterCBOs)
#Setup Tool Combobox
self.toolLBL = tk.Label(self, text='Tool')
self.toolCBO = ttk.Combobox(self, width=15)
self.toolCBO.bind('<<ComboboxSelected>>', self.filterCBOs)
#Arrange UI Elements
self.fromDateLBL.grid(column=0,row=4)
self.fromDate.grid(column=1,row=4,sticky='e')
self.toDateLBL.grid(column=2,row=4,sticky='e')
self.toDate.grid(column=3,row=4)
self.featureLBL.grid(column=0, row=0, sticky='w')
self.featureCBO.grid(column=1, row=0)
self.toolLBL.grid(column=0, row=1, sticky='w')
self.toolCBO.grid(column=1, row=1)
def filterCBOs(self, event=None):
#Create and filter dataframe
df=sigIndex
#Filter by Date
#THROWS ERROR ON NEXT LINE
startDate = dt.datetime(year=int(self.fromDate.get()[2]),month=int(self.fromDate.get()[0]),day=int(self.fromDate.get()[1]))
endDate = dt.datetime(year=int(self.toDate.get()[2]),month=int(self.toDate.get()[0]),day=int(self.toDate.get()[1]))
print(startDate)
print(endDate)
df=df[(df['Timestamp'] >= startDate) & (df['Timestamp'] <= endDate)]
#Filter by Feature
if self.featureCBO.get() == "":
pass
else:
df=df[df['Feature'] == self.featureCBO.get()]
#Filter by Tool
if self.toolCBO.get() == "":
pass
else:
df=df[df['Tool'] == self.toolCBO.get()]
#print(df)
#Filter Feature CBO
self.featureCBO['values'] = df['Feature'].unique().tolist()
self.featureCBO['values'] = (*self.featureCBO['values'], '') #add empty line to end
#Filter Tool CBO
self.toolCBO['values'] = df['Tool'].unique().tolist()
self.toolCBO['values'] = (*self.toolCBO['values'], '') #add empty line to end
if __name__ == '__main__':
window = Root()
window.mainloop()
print('done')
The problem is with trying to reference the function as Root.filterCBOs). The function belongs to an instance of Root, so it needs to bemaster.filterCBOssincemaster` is being set to the root window.
self.entry_1.bind('<Return>', master.filterCBOs)

A customized menu bar without using the widget tk.Menu

I would like to personalized a menu bar. For example I want to delete the border that appears around the tk.Menu widget (with the add_command() method)
That's my code (I'm using Windows 10)
import tkinter as tk
from tkinter import ttk
dark_grey = "#212121"
dark_blue="#102A43"
blue_1="#243B53"
root = tk.Tk()
root.state('zoomed')
container = tk.Frame(root, bg = dark_grey)
container.grid_rowconfigure(0, weight = 0)
container.grid_columnconfigure(0, weight = 1)
menu_frame = tk.Frame(container, bg = dark_blue)
menu1 = tk.Menubutton(menu_frame, text = "Menu1", bg = dark_blue, fg =
"white", activebackground = blue_1, activeforeground =
"white")
menu1.grid(row = 0, column = 0)
submenu1 = tk.Menu(menu1, tearoff = 0, bg = dark_blue,
activebackground= blue_1, fg = "white",borderwidth = 0, activeborderwidth= 0)
submenu1.add_command(label = "Option 1.1")
submenu1.add_command(label = "Option 1.2")
menu1.configure(menu = submenu1)
menu_frame.grid(row = 0, column = 0, sticky = "ew")
container.pack(fill = tk.BOTH, expand = "True")
root.mainloop()
My idea is to create a menu without using tk.Menu and tk.MenuButton. I would like "bind" an <Enter> event to a label, in order to create a sort of drop down under the label. Is it possible?
Question: Customized menu bar without using the widget tk.Menu?
This example uses a tk.Toplevel as a popup window and displays the added tk.Menubutton.
The Submenu follows ths defined Style of the Top tk.Menubutton.
TODO:
Close the Popup Window if clicked outside or another Top Menubutton.
Extend with other than only tk.Menubutton
Keyboard support
import tkinter as tk
class Menu:
def __init__(self, parent, **kwargs):
self._popup = None
self._menubutton = []
self.parent = parent
self.parent.bind('<Button-1>', self.on_popup)
def on_popup(self, event):
w = event.widget
x, y, height = self.parent.winfo_rootx(), self.parent.winfo_rooty(), self.parent.winfo_height()
self._popup = tk.Toplevel(self.parent.master, bg=self.parent.cget('bg'))
self._popup.overrideredirect(True)
self._popup.geometry('+{}+{}'.format(x, y + height))
for kwargs in self._menubutton:
self._add_command(**kwargs)
def add_command(self, **kwargs):
self._menubutton.append(kwargs)
def _add_command(self, **kwargs):
command = kwargs.pop('command', None)
menu = self.parent
mb = tk.Menubutton(self._popup, text=kwargs['label'],
bg=menu.cget('bg'),
fg=menu.cget('fg'),
activebackground=menu.cget('activebackground'),
activeforeground=menu.cget('activeforeground'),
borderwidth=0,
)
mb._command = command
mb.bind('<Button-1>', self._on_command)
mb.grid()
def _on_command(self, event):
w = event.widget
print('_on_command("{}")'.format(w.cget('text')))
self._popup.destroy()
if w._command is not None:
w._command()
Usage:
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("200x200")
style = {'bg': "#102A43", 'fg': "white",
'activebackground': "#243B53", 'activeforeground': "white",
'borderwidth': 0}
menu1 = tk.Menubutton(self, text="Menu1", **style)
submenu1 = Menu(menu1)
submenu1.add_command(label="Option 1.1")
submenu1.add_command(label="Option 1.2")
menu1.grid(row=0, column=0)
menu2 = tk.Menubutton(self, text="Menu2", **style)
submenu2 = Menu(menu2)
submenu2.add_command(label="Option 2.1")
submenu2.add_command(label="Option 2.2")
menu2.grid(row=0, column=2)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6

display a log file in real time with tkinter text field (python2.7)

I am trying to write a GUI that can display the log file in real time (tail -f log). The new line from the log file can be printed out into the terminal, but it cannot be loaded into the text field (line #). Can any one tell me why it won't put back to the text field?
from Tkinter import *
import os, time
import tkFileDialog
class Controller(object):
def __init__(self, master):
""" Main interface:
master - the top level window
"""
self._master = master
frame1 = Frame(self._master)
label = Label(self._master, text="Select a Log File")
label.pack(side=TOP)
currentLogfile = StringVar(self._master)
LogfileList = [f for f in os.listdir('.') if os.path.isfile(f)]
currentLogfile.set(LogfileList[0])
chooseLog = OptionMenu(self._master, currentLogfile, *LogfileList, command = self.file_open)
chooseLog.config(width = "300")
chooseLog.pack(side=TOP)
self._master.config(menu=chooseLog)
self._Text=Text(frame1, bg = 'black', fg = 'white')
self._Text.pack(side = TOP,fill=BOTH, expand = True,pady=20)
w = Scrollbar(self._Text)
w.pack(side=RIGHT, fill=Y)
frame1.pack(side=TOP, fill=BOTH, padx=5,expand=True)
def file_open(self,filename):
#clear text field
self._Text.delete('1.0', END)
with open(filename,'r') as f:
loglines = follow(f)
for line in loglines:
#print line
self._Text.insert(END,line)
def follow(thefile):
thefile.seek(0,2)
while True:
line = thefile.readline()
if not line:
time.sleep(5)
continue
yield line
if __name__ == "__main__":
root=Tk()
c=Controller(root)
root.title("log")
root.geometry("750x500")
root.mainloop()

threading tkinter add label in frame during function execution

I write a pipeline for a lab, so I know it is impossible to insert a "console" in a GUI, so I made it with a Frame and I put label on it.
But the problem is, I am a beginner in threading, and I don't know how to use it to put my label into my frame after a function execution in a loop.
So this is my code (python 3.x) :
########
# IMPORTS #
########
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import *
from tkinter.messagebox import *
import os
import glob
from datetime import date, time, datetime
#########
# FUNCTION #
#########
def OneFile(path1,DB,path2,seq,seq2,typ,path3):
"""
This function is very long, take all the sequences of the input file and BLAST it to the Library DATABASE
path : path to the library databse
DB : library database name
path2 : path of the file with the query sequences
seq : name of the file with the query sequences append with a job ID
seq2 : name of the file with the query sequence
Typ : Nucleotide or Proteine
"""
from datetime import date, time, datetime
import subprocess
import platform
import time
OS = platform.system()
if OS == 'Linux' or OS == 'Darwin':
pathLibrary = path1+'/'
pathSequence = path2+'/'
pathFolder = path3+'/'
if OS == 'Windows':
pathLibrary = path1+'\\'
pathSequence = path2+'\\'
if typ not in [(1,1),(2,2),(1,2),(2,1)]:
showerror('Error : Missing Type !', "You do not choose your type\n(nucleotides or proteins)")
else:
library = DB
if os.path.isfile(pathLibrary+library) != True:
showerror('Error : Missing File !', "You must choose a Library Database file")
else:
if os.path.isfile(pathSequence+seq2) != True:
showerror('Error : Missing File !', "You must choose your sequence file")
else:
if typ == (1,1):
typ = "blastn"
if typ == (2,2):
typ = "blastp"
if typ == (1,2):
typ = "blastx"
if typ == (2,1):
typ = "tblastn"
if OS == 'Linux' or OS == 'Darwin':
t0 = time.time()
query = str(seq2)
blast = str(seq)+'_Blast.txt'
seqs = str(seq)+'_seqs.txt'
subprocess.call(typ+" -query "+pathSequence+query+" -db "+pathLibrary+library+" -evalue 1e-10 -out "+pathFolder+blast, shell=True)
subprocess.call("grep '\(Sbjct\|>\)' "+pathFolder+blast+" > "+pathFolder+seqs, shell=True)
t1 = time.time()
print('Job finish in '+str(round(t1-t0,2))+' seconds')
if OS == 'Windows':
t0 = time.time()
query = str(seq2)
blast = str(seq)+'_Blast.txt'
seqs = str(seq)+'_seqs.txt'
subprocess.call(typ+' -query '+pathSequence+query+' -db '+pathLibrary+library+' -evalue 1e-10 -out '+pathSequence+blast, shell=True)
print('Fichier n° '+str(1)+' '+str(seq2))
subprocess.Popen('findstr "Sbjct >" '+pathSequence+blast+' > '+pathSequence+seqs, shell=True)
t1 = time.time()
print('Job finish in '+str(round(t1-t0,2))+' seconds')
#######
# CLASS #
#######
class GraphicalUserInterface():
#principal application
def __init__(self):
#constructor
self.fen = Tk()
self.fen.title("Starch Enzyme Pipeline")
#first label
self.label1 = Label(self.fen, text="Folder with your set(s) : ")
self.label1.grid(row=0, columnspan=2, sticky="W")
#first button
self.browse1 = Button(self.fen)
self.browse1.config(text="Browse",command=self.folderPath)
self.browse1.grid(row=1,column=0, sticky="W")
#label to show the path
self.varLabel1 = StringVar()
self.pathLabel1 = Label(self.fen, textvariable=self.varLabel1, relief=SUNKEN)
self.pathLabel1.grid(row=1,column=1, sticky="EW")
#second title
self.label2 = Label(self.fen, text="Folder with your library database(s) ")
self.label2.grid(row=2,column = 0, columnspan=2 , sticky="W")
#second button
self.browse2 = Button(self.fen)
self.browse2.config(text="Browse",command=self.folderPath2)
self.browse2.grid(row=3,column=0, sticky="W")
#label to show the path for database
self.varLabel2 = StringVar()
self.pathLabel2 = Label(self.fen, textvariable=self.varLabel2, relief=SUNKEN)
self.pathLabel2.grid(row=3,column=1, sticky = "EW")
#Frame wrappe listBox and other
self.frameListBoxAll = Frame(self.fen)
self.frameListBoxAll.grid(row=6,columnspan=2)
#list box label
self.labListBox1 = Label(self.frameListBoxAll, text="Your sets :",padx=10)
self.labListBox1.grid(row=0,column=0)
self.labListBox2 = Label(self.frameListBoxAll, text="Your library database :",padx=10)
self.labListBox2.grid(row=0,column=1)
#frame with listbox1
self.frame1 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
self.frame1.grid(row=1,column=0)
#frame with listbox1
self.frame2 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
self.frame2.grid(row=1,column=1)
#scrollbar listbox1
self.scrollbar1 = Scrollbar(self.frame1)
self.scrollbar1.grid(row=0,column=1, sticky="NS")
self.scrollbar2 = Scrollbar(self.frame2)
self.scrollbar2.grid(row=0,column=3, sticky="NS")
self.scrollbar3 = Scrollbar(self.frame1, orient=HORIZONTAL)
self.scrollbar3.grid(row=1,column=0, sticky="WE")
self.scrollbar4 = Scrollbar(self.frame2, orient=HORIZONTAL)
self.scrollbar4.grid(row=1,column=2, sticky="WE")
#liste box
self.listeBox1 = Listbox(self.frame1, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar1.set, xscrollcommand=self.scrollbar3.set)
self.listeBox1.grid(row=0,column = 0)
self.scrollbar1.config(command=self.listeBox1.yview)
self.scrollbar3.config(command=self.listeBox1.xview)
#liste box2
self.listeBox2 = Listbox(self.frame2, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar2.set, xscrollcommand=self.scrollbar4.set)
self.listeBox2.grid(row=0,column = 2)
self.scrollbar2.config(command=self.listeBox2.yview)
self.scrollbar4.config(command=self.listeBox2.xview)
#radioboutton list box 1
self.var = IntVar()
for item in [1,2]:
if item == 1:
self.rb = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var)
self.rb.grid(row=2, column=0)
if item == 2:
self.rb = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var)
self.rb.grid(row=3, column=0)
#radioboutton list box 2
self.var2 = IntVar()
for item in [1,2]:
if item == 1:
self.rb2 = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var2)
self.rb2.grid(row=2, column=1)
if item == 2:
self.rb2 = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var2)
self.rb2.grid(row=3, column=1)
#variables
self.path1 = str()
self.path2 = str()
self.path3 = str()
#RUN Buttun
self.runbutton = Button(self.fen, text="RUN",command=self.start_foo_thread).grid(row=7,column=0,columnspan=2)
#FRAME CONSOLE
self.console = Frame(self.fen)
self.console.config(relief=SUNKEN, bg="black", height=200, width=400)
self.console.grid(row=8, columnspan=10)
self.console.grid_propagate(False) #to block the size of the frame
#QUIT BUTTON
self.quitButton = Button(self.fen)
self.quitButton.config(text="QUIT", command=self.fen.destroy)
self.quitButton.grid(row=100,column=0)
def folderPath(self):
path = askdirectory(title='Choose your set folder')
self.varLabel1.set(path)
self.listeBox1.delete(0, END)
for filename in sorted(glob.glob(path+'/*')):
if os.path.isfile(filename):
#stockage of path
self.path1 = os.path.split(filename)[0]
name = os.path.split(filename)[1]
self.listeBox1.insert(END, name)
def folderPath2(self):
path = askdirectory(title="Choose your library database folder")
self.varLabel2.set(path)
self.listeBox2.delete(0, END)
for filename in sorted(glob.glob(path+'/*')):
if os.path.isfile(filename):
#stockage of path
self.path2 = os.path.split(filename)[0]
name = os.path.split(filename)[1]
self.listeBox2.insert(END, name)
def run(self):
self.fen.mainloop()
def createJobName():
job = str(datetime.now())
job = job.replace(" ","-")
return job
def typeNP(self):
liste = []
#selection of query files
valListBox1 = [self.listeBox1.get(idx) for idx in self.listeBox1.curselection()]
#selection of database file
valListBox2 = [self.listeBox2.get(idx) for idx in self.listeBox2.curselection()]
#selection of sequence type
typ = (self.var.get(),self.var2.get())
# loop
for i in range(len(valListBox2)):
job = GraphicalUserInterface.createJobName()
path1 = self.path2
path2 = self.path1
DB = valListBox2[i]
path3 = os.getcwd()+"/"+DB+job
if os.path.isdir(DB+job) == True:
showwarning('Warning', "The folder already exist \n or they are no folder name !\nChange or get the folder name")
else:
os.mkdir(DB+job)
for filename in valListBox1:
seq = filename+job
seq2 = filename
#stock data for OneFile function
liste.append([path1,DB,path2,seq,seq2,typ,path3])
return liste
def start_foo_thread(self):
liste = self.typeNP()
for i in range(len(liste)):
global foo_thread
import threading
print('Fichier n°'+str(i+1)+' '+str(liste[i][4]))
stringLabel = Label(self.console,text='Fichier n°'+str(i+1)+' '+str(liste[i][4]),bg='black', fg='white')
stringLabel.grid(row=i,sticky="W")
foo_thread = threading.Thread(target=OneFile(liste[i][0],liste[i][1],liste[i][2],liste[i][3],liste[i][4],liste[i][5],liste[i][6]))
foo_thread.daemon = True
foo_thread.start()
#########
# AUTORUN #
#########
if __name__ == '__main__':
app = GraphicalUserInterface()
app.run()
The problem is when the loop began in:
def start_foo_thread(self):
liste = self.typeNP()
for i in range(len(liste)):
With the print function, I see the function run, but the label does not go in the frame when the iteration finishes. When the loops are completed, I see my label in the frame.
What is the correct code to have my label in my frame at the same time my function runs in my loop?
You sometimes have to manually update the widget. You have posted too much code to wade through, so this simple example should show the problem. Run as is, the labels don't show up until the function returns. Run with update_idletasks() uncommented does what I think you want. Also note that the program stops until the call to subprocess returns.
import sys
if sys.version_info[0] < 3:
import Tkinter as tk ## Python 2.x
else:
import tkinter as tk ## Python 3.x
class GraphicalUserInterface():
def __init__(self):
#constructor
self.fen = tk.Tk()
self.fen.title("Starch Enzyme Pipeline")
self.console=tk.Frame(self.fen)
self.console.grid()
self.liste=["one", "two", "three"]
tk.Button(self.fen, text="Exit", command=self.fen.quit).grid(row=1)
self.start_foo_thread()
self.fen.mainloop()
def start_foo_thread(self):
for ctr in range(len(self.liste)):
lit='Fichier n %s' % (ctr)
print(lit)
stringLabel = tk.Label(self.console, text=lit,
bg='black', fg='white')
stringLabel.grid(row=ctr,sticky="W")
##self.console.update_idletasks()
print("Waiting 2 seconds")
self.fen.after(2000) ## wait 2 seconds to show effect
print("Return from function")
if __name__ == '__main__':
app = GraphicalUserInterface()

How to update image in tkinter label?

I'm a beginner in python so this may be too simple question to ask but i need help..With this code i cannot update image in tkinter label. I can even resize window according to new loaded image's attributes but the new image is not displayed in tkinter label.
from Tkinter import Frame, Tk, Label, Text, Menu, END, BOTH, StringVar
from PIL import ImageTk, Image
import numpy
import tkFileDialog
class DIP(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("DIP Algorithms- Simple Photo Editor")
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
#Open Image Menu
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open", command=self.onOpen)
menubar.add_cascade(label="File", menu=fileMenu)
#menu for image ngative
basicMenu=Menu(menubar)
basicMenu.add_command(label="Negative", command=self.onNeg)
menubar.add_cascade(label="Basic", menu=basicMenu)
#Image Negative Menu callback
def onNeg(self):
I2=255-self.I;
im = Image.fromarray(numpy.uint8(I2))
photo2=ImageTk.PhotoImage(im)
self.label2= Label(self.parent,border=25,image=photo2)
self.label2.image = photo2 # keep a reference!
self.label2.grid(row=1, column=2)
def setImage(self):
self.img=Image.open(self.fn)
self.I = numpy.asarray(self.img)
l,h = self.img.size
text=str(2*l+100)+"x"+str(h+50)+"+0+0"
self.parent.geometry(text)
photo = ImageTk.PhotoImage(self.img)
self.label1 = Label(self.parent,border=25,image=photo)
self.label1.configure(image=photo)
self.label1.image = photo # keep a reference!
self.label1.grid(row=1, column=1)
#Open Callback
def onOpen(self):
ftypes = [('Image Files', '*.tif *.jpg *.png')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
filename = dlg.show()
self.fn=filename
#print self.fn #prints filename with path here
self.setImage()
#def onError(self):
#box.showerror("Error", "Could not open file")
def main():
root = Tk()
DIP(root)
root.geometry("320x240")
root.mainloop()
if __name__ == '__main__':
main()
When i run this code, and open an image , it is displayed in label1. But when i open another image again, i' expecting it to be displayed in same label1, but it's not happening. I know the 2nd image is loaded because the window size resized accordingly, the only problem is that it's not being displayed and i cannot figure out why!.
Instead of creating an new tk.Label each time setImage is called, just create it once outside of setImage -- for example, in initUI.
You can then change the image by calling self.label.configure:
import Tkinter as tk
import Image
import ImageTk
import numpy as np
import tkFileDialog
class DIP(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("DIP Algorithms- Simple Photo Editor")
self.pack(fill = tk.BOTH, expand = 1)
menubar = tk.Menu(self.parent)
self.parent.config(menu = menubar)
self.label1 = tk.Label(self, border = 25)
self.label2 = tk.Label(self, border = 25)
self.label1.grid(row = 1, column = 1)
self.label2.grid(row = 1, column = 2)
#Open Image Menu
fileMenu = tk.Menu(menubar)
fileMenu.add_command(label = "Open", command = self.onOpen)
menubar.add_cascade(label = "File", menu = fileMenu)
#menu for image ngative
basicMenu = tk.Menu(menubar)
basicMenu.add_command(label = "Negative", command = self.onNeg)
menubar.add_cascade(label = "Basic", menu = basicMenu)
def onNeg(self):
#Image Negative Menu callback
I2 = 255-self.I;
im = Image.fromarray(np.uint8(I2))
photo2 = ImageTk.PhotoImage(im)
self.label2.image = photo2 # keep a reference!
def setImage(self):
self.img = Image.open(self.fn)
self.I = np.asarray(self.img)
l, h = self.img.size
text = str(2*l+100)+"x"+str(h+50)+"+0+0"
self.parent.geometry(text)
photo = ImageTk.PhotoImage(self.img)
self.label1.configure(image = photo)
self.label1.image = photo # keep a reference!
def onOpen(self):
#Open Callback
ftypes = [('Image Files', '*.tif *.jpg *.png')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
filename = dlg.show()
self.fn = filename
#print self.fn #prints filename with path here
self.setImage()
#def onError(self):
#box.showerror("Error", "Could not open file")
def main():
root = tk.Tk()
DIP(root)
root.geometry("320x240")
root.mainloop()
if __name__ == '__main__':
main()

Categories

Resources