Commit 75eca498 authored by Alessandro dos Santos Ferreira's avatar Alessandro dos Santos Ferreira
Browse files

Pynovisao - Classes Tk

parent 1b74267e
...@@ -33,17 +33,17 @@ def open_image(tk): ...@@ -33,17 +33,17 @@ def open_image(tk):
if event.xdata != None and event.ydata != None and int(event.ydata) != 0: if event.xdata != None and event.ydata != None and int(event.ydata) != 0:
x = int(event.xdata) x = int(event.xdata)
y = int(event.ydata) y = int(event.ydata)
tk.write_logger("Coordinates: x = %d y = %d ", x, y) tk.write_log("Coordinates: x = %d y = %d ", x, y)
if segments is not None: if segments is not None:
tk.append_logger("Segment = %d", segments[y, x]) tk.append_log("Segment = %d", segments[y, x])
imagename = tk.utils.ask_image_name() imagename = tk.utils.ask_image_name()
if imagename: if imagename:
image = f.open_image(imagename) image = f.open_image(imagename)
name = f.get_filename(imagename) name = f.get_filename(imagename)
tk.write_logger("Opening %s...", name) tk.write_log("Opening %s...", name)
tk.add_image(image, name, onclick) tk.add_image(image, name, onclick)
const_image = image const_image = image
...@@ -56,11 +56,22 @@ def rotate_image(tk): ...@@ -56,11 +56,22 @@ def rotate_image(tk):
image = f.rotate_image(const_image) image = f.rotate_image(const_image)
tk.write_logger("Rotating image 90 degrees") tk.write_log("Rotating image 90 degrees")
tk.refresh_image(image) tk.refresh_image(image)
const_image = image const_image = image
def rotate_image(tk):
global image, const_image
if const_image is None:
raise IException("Image not found")
image = f.rotate_image(const_image)
tk.write_log("Rotating image 90 degrees")
tk.refresh_image(image)
const_image = image
def close_image(tk): def close_image(tk):
global const_image global const_image
...@@ -68,7 +79,7 @@ def close_image(tk): ...@@ -68,7 +79,7 @@ def close_image(tk):
raise IException("Image not found") raise IException("Image not found")
if tk.close_image(): if tk.close_image():
tk.write_logger("Closing image...") tk.write_log("Closing image...")
const_image = None const_image = None
segments = None segments = None
...@@ -79,11 +90,11 @@ def run_segmentation(tk): ...@@ -79,11 +90,11 @@ def run_segmentation(tk):
if const_image is None: if const_image is None:
raise IException("Image not found") raise IException("Image not found")
tk.write_logger("Running %s,,,", segmenter.get_name()) tk.write_log("Running %s,,,", segmenter.get_name())
tk.append_logger("\nConfig: %s", str(segmenter.get_summary_config())) tk.append_log("\nConfig: %s", str(segmenter.get_summary_config()))
segments, image, run_time = segmenter.run(const_image) segments, image, run_time = segmenter.run(const_image)
tk.append_logger("\nTime elapsed: %0.3f seconds", run_time) tk.append_log("\nTime elapsed: %0.3f seconds", run_time)
tk.refresh_image(image) tk.refresh_image(image)
...@@ -91,7 +102,7 @@ def config_segmentation(tk): ...@@ -91,7 +102,7 @@ def config_segmentation(tk):
global segmenter global segmenter
title = "Configuring %s" % segmenter.get_name() title = "Configuring %s" % segmenter.get_name()
tk.write_logger(title) tk.write_log(title)
current_config = segmenter.get_config() current_config = segmenter.get_config()
...@@ -99,10 +110,15 @@ def config_segmentation(tk): ...@@ -99,10 +110,15 @@ def config_segmentation(tk):
new_config = tk.get_config_and_destroy() new_config = tk.get_config_and_destroy()
segmenter.set_config(new_config) segmenter.set_config(new_config)
tk.append_logger("\nConfig updated: %s", str(segmenter.get_summary_config())) tk.append_log("\nConfig updated: %s", str(segmenter.get_summary_config()))
tk.dialogue_config(title, current_config, process_config) tk.dialogue_config(title, current_config, process_config)
def refresh_classes(tk):
tk.write_log("Refreshing classes...")
tk.add_panel_classes()
def func_not_available(tk): def func_not_available(tk):
tk.write_logger("This functionality is not available right now.") tk.write_log("This functionality is not available right now.")
...@@ -14,31 +14,19 @@ else: ...@@ -14,31 +14,19 @@ else:
import tkinter as Tk import tkinter as Tk
import tkMessageBox import tkMessageBox
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import pylab as plt
from Interface import Interface, InterfaceException as IException from Interface import Interface, InterfaceException as IException
from tk_interface import * from tk import *
class TkInterface(Interface): class TkInterface(Interface):
utils = TkUtils.TkUtils utils = TkUtils.Utils
title = None title = None
__root = None __root = None
__menus = None __menus = None
__configs = None __image = None
__grid = None
__im = None
__canvas = None
__logger = None
__dialog = None
def __init__(self, title): def __init__(self, title):
...@@ -56,7 +44,7 @@ class TkInterface(Interface): ...@@ -56,7 +44,7 @@ class TkInterface(Interface):
def add_menu(self, label): def add_menu(self, label):
self.__menus.append( Menu.Menu(label) ) self.__menus.append( TkMenu.Menu(self.__root, label) )
def add_command(self, label, action, shortcut = None): def add_command(self, label, action, shortcut = None):
self.__menus[-1].add_command( label = label, action = lambda *_: self.__apply( action ), shortcut = shortcut ) self.__menus[-1].add_command( label = label, action = lambda *_: self.__apply( action ), shortcut = shortcut )
...@@ -66,165 +54,137 @@ class TkInterface(Interface): ...@@ -66,165 +54,137 @@ class TkInterface(Interface):
def render_menu(self): def render_menu(self):
menubar = Tk.Menu(self.__root) menubar = Tk.Menu(self.__root)
shortcuts = []
for menu in self.__menus: for menu in self.__menus:
menubar = menu.render(menubar) menu.render(menubar)
shortcuts += menu.get_shorcuts()
self.__root.config(menu=menubar) self.__root.config(menu=menubar)
for sh in shortcuts:
self.__root.bind("<Control-Key-" + sh["shortcut"] + ">", sh["action"])
self.__root.bind("<Control-Key-" + sh["shortcut"].lower() + ">", sh["action"])
def show(self):
self.__root.protocol("WM_DELETE_WINDOW", self.quit)
self.__root.mainloop()
def add_image(self, image, title = None, onclick = None): def add_image(self, image, title = None, onclick = None):
if self.__canvas is None: if self.__image is None:
self.__root.image = image self.__image = TkCanvas.Image(self.__root, image, lambda event, *_: self.__apply( onclick, event ))
else:
fig = plt.figure(facecolor='white') self.__image.refresh(image)
self.__im = plt.imshow(self.__root.image) # later use a.set_data(new_data)
#ax = plt.gca()
#ax.set_xticklabels([])
#ax.set_yticklabels([])
# a tk.DrawingArea
self.__canvas = FigureCanvasTkAgg(fig, master=self.__root)
self.__canvas.show()
self.__canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
if onclick is not None: if title is not None:
fig.canvas.mpl_connect('button_press_event', func = lambda event, *_: self.__apply( onclick, event )) self.set_subtitle(title)
def refresh_image(self, image, title = None):
if self.__image is not None:
self.__image.refresh(image)
if title is not None: if title is not None:
self.set_subtitle(title) self.set_subtitle(title)
else:
self.refresh_image(image, title)
def refresh_image(self, image, title = 'None'):
if self.__canvas is not None:
self.__root.image = image
self.__im.set_data(self.__root.image)
self.__canvas.draw()
def close_image(self): def close_image(self):
if self.__canvas is not None: if self.__image is not None:
if tkMessageBox.askokcancel("Quit", "Do you want to close the image?"): if tkMessageBox.askokcancel("Quit", "Do you want to close the image?"):
self.__root.image = None self.__image.close()
#self.__im.set_data(np.zeros((0,0,3), float))
#self.__canvas.draw()
self.__canvas.get_tk_widget().pack_forget();
self.__canvas.get_tk_widget().destroy();
self.__im = None self.__image = None
self.__canvas = None
return True return True
return False return False
def open_log(self):
def create_logger(self): self.__logger = TkLogger.Logger(self.__root)
self.__logger = Tk.Text(self.__root, width=0, height=10, bg="white", fg="black", padx=5, pady=5)
self.__logger.insert(Tk.INSERT, "$ Pynovisao is ready!\n")
self.__logger.config(state=Tk.DISABLED)
self.__logger.pack(side=Tk.BOTTOM, fill=Tk.X, expand=False)
def write_logger(self, fmt, *args):
self.clean_logger()
self.append_logger(fmt % args)
def append_logger(self, fmt, *args): def write_log(self, fmt, *args):
self.__logger.config(state=Tk.NORMAL) if self.__logger:
self.__logger.insert(Tk.END, fmt % args) self.__logger.write_logger(fmt, *args)
self.__logger.insert(Tk.END, '\n')
self.__logger.config(state=Tk.DISABLED)
def clean_logger(self): def append_log(self, fmt, *args):
self.__logger.config(state=Tk.NORMAL) if self.__logger:
self.__logger.delete('1.0', Tk.END) self.__logger.append_logger(fmt, *args)
self.__logger.insert('1.0', '$ ')
self.__logger.config(state=Tk.DISABLED)
def destroy_logger(self): def clear_log(self):
self.__logger.pack_forget(); if self.__logger:
self.__logger.destroy(); self.__logger.clear_logger()
def close_log(self):
if self.__logger:
self.__logger.destroy_logger()
def popup(self):
pass
def log_and_popup(self, message): def add_panel(self, left = True):
pass self.__grid = TkCustomFrame.CustomGrid(self.__root, 175)
side = Tk.LEFT if left == True else Tk.RIGHT
def show_error(self, fmt, *args): self.__grid.pack(side=side, fill=Tk.Y, expand=False)
tkMessageBox.showerror("Error", fmt % args)
def show_info(self, fmt, *args): def add_panel_classes(self, classes = None):
tkMessageBox.showinfo("Info", fmt % args) if self.__grid is None:
self.__grid = TkCustomFrame.CustomGrid(self.__root)
else:
self.clear_panel_classes()
def show_warning(self, fmt, *args): from random import randint as r
tkMessageBox.showwarning("Warning", fmt % args) length = r(2, 16)
self.__grid.add_cell_label("Classes ", 0, 0, 12, 4)
def dialogue_config(self, title, configs, callback):
n_configs = len(configs)
self.__dialog = Tk.Toplevel(self.__root, padx=10, pady=10) for i in range(1, length):
self.__dialog.title(title) self.__grid.add_cell_radio_button("Classe " + str(i), i, i, 0, 12, selected=False if i > 1 else True)
self.__grid.add_cell_button_color("", i, 1, 2, bg='#%02X%02X%02X' % (r(23, 212), r(50, 214), r(0, 255)))
self.__grid.add_cell_label("", i, 2, 2)
row = 0 self.__grid.pack(side=Tk.LEFT, fill=Tk.Y, expand=False)
self.__configs = []
for config in configs:
Tk.Label(self.__dialog, text=config.title()).grid(row=row, padx=4, pady=4, sticky=Tk.W)
entry = Tk.Entry(self.__dialog)
entry.insert(0, str(configs[config].value))
entry.grid(row=row, column=1, padx=4, pady=4, sticky=Tk.W)
if row == 0:
entry.focus_set()
self.__configs.append( TkConfig.TkConfig(config, configs[config].value, c_type=configs[config].c_type, tk_entry=entry) )
row += 1
B1 = Tk.Button(self.__dialog, text="Ok", width=5, command = lambda *_: self.__apply( callback ))
B1.grid(row=row, padx=6, pady=6, sticky=Tk.W)
self.__dialog.bind("<Return>", lambda *_: self.__apply( callback )) def clear_panel_classes(self):
for i in range(1, 20):
self.__grid.add_cell_label("", i, 0, 12)
self.__grid.add_cell_label("", i, 1, 2)
def close_panel(self):
if self.__grid is not None:
self.__grid.pack_forget();
self.__grid.destroy();
B2 = Tk.Button(self.__dialog, text="Cancel", width=5, command = self.__dialog.destroy)
B2.grid(row=row, column=1, padx=6, pady=6, sticky=Tk.W)
self.__dialog.bind("<Escape>", lambda *_: self.__dialog.destroy()) def popup(self):
pass
self.__dialog.grab_set() def log_and_popup(self, message):
pass
self.__dialog.protocol("WM_DELETE_WINDOW", self.__dialog.destroy)
self.__dialog.geometry("+%d+%d" % (self.__root.winfo_width()/3,
self.__root.winfo_height()/3))
def dialogue_config(self, title, configs, callback):
self.__conf_dialog = TkCustomDialog.ConfigDialog(self.__root, title, configs, command_ok = lambda *_: self.__apply( callback ))
def get_config_and_destroy(self): def get_config_and_destroy(self):
if self.__conf_dialog is None:
return None
try: try:
configs = {} configs = {}
for config in self.__configs: for config in self.__conf_dialog.get_configs():
config.value = config.get_entry_val() config.value = config.get_entry_val()
configs[config.label] = config configs[config.label] = config
except: except:
self.__dialog.destroy() self.__conf_dialog.destroy()
raise IException("Illegal values, please try again") raise IException("Illegal values, please try again")
self.__dialog.destroy() self.__conf_dialog.destroy()
self.__conf_dialog = None
return configs return configs
def show_error(self, fmt, *args):
tkMessageBox.showerror("Error", fmt % args)
def show_info(self, fmt, *args):
tkMessageBox.showinfo("Info", fmt % args)
def show_warning(self, fmt, *args):
tkMessageBox.showwarning("Warning", fmt % args)
def show(self):
self.__root.protocol("WM_DELETE_WINDOW", self.quit)
self.__root.mainloop()
def quit(self): def quit(self):
if tkMessageBox.askokcancel("Quit", "Do you want to quit?"): if tkMessageBox.askokcancel("Quit", "Do you want to quit?"):
...@@ -249,6 +209,6 @@ class TkInterface(Interface): ...@@ -249,6 +209,6 @@ class TkInterface(Interface):
if warning == True: if warning == True:
self.show_warning( message ) self.show_warning( message )
elif IException.DEBUG == True: elif IException.DEBUG == True:
self.append_logger( message ) self.append_log( message )
else: else:
self.show_error( message ) self.show_error( message )
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: TkCanvas.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: TODO
"""
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import pylab as plt
class Image(object):
parent = None
__im = None
__canvas = None
def __init__(self, parent, image, onclick = None):
self.parent = parent
self.parent.image = image
fig = plt.figure(facecolor='white')
self.__im = plt.imshow(self.parent.image) # later use a.set_data(new_data)
#ax = plt.gca()
#ax.set_xticklabels([])
#ax.set_yticklabels([])
# a tk.DrawingArea
self.__canvas = FigureCanvasTkAgg(fig, master=self.parent)
self.__canvas.show()
self.__canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
if onclick is not None:
fig.canvas.mpl_connect('button_press_event', func = onclick)
def refresh(self, image):
if self.__canvas is not None:
self.parent.image = image
self.__im.set_data(self.parent.image)
self.__canvas.draw()
def close(self):
if self.__canvas is not None:
self.parent.image = None
#self.__im.set_data(np.zeros((0,0,3), float))
#self.__canvas.draw()
self.__canvas.get_tk_widget().pack_forget();
self.__canvas.get_tk_widget().destroy();
self.__im = None
self.__canvas = None
return True
return False
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: TkCustomDialog.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: Classe que customiza as janelas de dialogo da biblioteca TkInter.
"""
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
from TkConfig import TkConfig
class ConfigDialog(Tk.Toplevel):
parent = None
__configs = None
def __init__(self, parent, title = None, configs = None, command_ok = None):
self.parent = parent
Tk.Toplevel.__init__(self, self.parent, padx=10, pady=10)
self.transient(self.parent)
if title is not None:
self.title(title)
self.grab_set()
if configs is not None:
self.add_configs(configs, command_ok)
self.geometry("+%d+%d" % (parent.winfo_width()/3,
parent.winfo_height()/3))
self.protocol("WM_DELETE_WINDOW", self.destroy)
def add_configs(self, configs, command_ok):
row = 0
self.__configs = []
for config in configs:
Tk.Label(self, text=config.title()).grid(row=row, padx=4, pady=4, sticky=Tk.W)