re-added all UI changes, removed global variable

This commit is contained in:
smethan 2018-11-01 09:27:59 -05:00
parent d2f0829b99
commit 3ab32da970
19 changed files with 132 additions and 8 deletions

88
framework.py Normal file
View File

@ -0,0 +1,88 @@
"""
Chapter 6: Paint Application
Developing a Tiny Framework
Tkinter GUI Application Development Blueprints
"""
import tkinter as tk
class Framework():
"""
GUIFramework is a class that provides a higher level of abstraction for
the development of Tkinter graphic user interfaces (GUIs).
Every class that uses this GUI framework must inherit from this class
and should pass the root window as an argument to this class by calling
the super method as follows:
super().__init__(root)
Building Menus:
To build a menu, call build_menu() method with one argument for
menu_definition, where menu_definition is a tuple where each item is a string of the
format:
'Top Level Menu Name - MenuItemName/Accelrator/Commandcallback/Underlinenumber'.
MenuSeparator is denoted by a string 'sep'.
For instance, passing this tuple as an argument to this method
menu_definition = (
'File - &New/Ctrl+N/new_file, &Open/Ctrl+O/openfile, &Save/Ctrl+S/save, Save&As//saveas, sep, Exit/Alt+F4/close',
'Edit - Cut/Ctrl+X/cut, Copy/Ctrl+C/copy, Paste/Ctrl+V/paste, Sep',
)
will generate a File and Edit Menu Buttons with listed menu items for each of the buttons.
"""
menu_items = None
def __init__(self, root):
self.root = root
def build_menu(self, menu_definitions):
menu_bar = tk.Menu(self.root)
for definition in menu_definitions:
menu = tk.Menu(menu_bar, tearoff=0)
top_level_menu, pull_down_menus = definition.split('-')
menu_items = map(str.strip, pull_down_menus.split(','))
for item in menu_items:
self._add_menu_command(menu, item)
menu_bar.add_cascade(label=top_level_menu, menu=menu)
self.root.config(menu=menu_bar)
def _add_menu_command(self, menu, item):
if item == 'sep':
menu.add_separator()
else:
menu_label, accelrator_key, command_callback = item.split('/')
try:
underline = menu_label.index('&')
menu_label = menu_label.replace('&', '', 1)
except ValueError:
underline = None
menu.add_command(label=menu_label, underline=underline,
accelerator=accelrator_key, command=eval(command_callback))
class TestThisFramework(Framework):
def new_file(self):
print('new tested OK')
def open_file(self):
print ('open tested OK')
def undo(self):
print ('undo tested OK')
def options(self):
print ('options tested OK')
def about(self):
print ('about tested OK')
if __name__ == '__main__':
root = tk.Tk()
menu_items = (
'File- &New/Ctrl+N/self.new_file, &Open/Ctrl+O/self.open_file',
'Edit- Undo/Ctrl+Z/self.undo, sep, Options/Ctrl+T/self.options',
'About- About//self.about'
)
app = TestThisFramework(root)
app.build_menu(menu_items)
root.mainloop()

BIN
icons/canvas_top_test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
icons/delete_item.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

BIN
icons/drag_item.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

BIN
icons/draw_arc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

BIN
icons/draw_line.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

BIN
icons/draw_oval.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

BIN
icons/draw_rectangle.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

BIN
icons/draw_star.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
icons/draw_super_shape.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

BIN
icons/draw_text.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

BIN
icons/draw_triangle.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

BIN
icons/duplicate_item.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

BIN
icons/enlarge_item_size.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
icons/fill_item.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
icons/move_to_top.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

BIN
icons/reduce_item_size.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

52
ui.py
View File

@ -38,12 +38,11 @@ from tkinter import filedialog
import framework
import decensor
class PaintApplication(framework.Framework):
def __init__(self, root):
super().__init__(root)
self.circle = 0
self.drawn_img = None
self.screen_width = root.winfo_screenwidth()
self.screen_height = root.winfo_screenheight()
@ -65,6 +64,19 @@ class PaintApplication(framework.Framework):
self.create_gui()
self.bind_mouse()
# Create blank image to avoid errors with irregular line drawing on blank canvas
# TODO: Optimize this, seems too inefficient
self.canvas.img = Image.new('RGB', (800,1280), (255, 255, 255))
self.canvas.img_width, self.canvas.img_height = self.canvas.img.size
# make reference to image to prevent garbage collection
# https://stackoverflow.com/questions/20061396/image-display-on-tkinter-canvas-not-working
self.canvas.tk_img = ImageTk.PhotoImage(self.canvas.img)
self.canvas.config(width=self.canvas.img_width, height=self.canvas.img_height)
self.canvas.create_image(self.canvas.img_width / 2.0, self.canvas.img_height / 2.0, image=self.canvas.tk_img)
self.drawn_img = Image.new("RGBA", self.canvas.img.size)
self.drawn_img_draw = ImageDraw.Draw(self.drawn_img)
def on_new_file_menu_clicked(self, event=None):
self.start_new_project()
@ -77,7 +89,7 @@ class PaintApplication(framework.Framework):
self.open_image()
def open_image(self):
self.file_name = filedialog.askopenfilename(master=self.root, filetypes = [("All Files","*.*")], title="Open...")
self.file_name = filedialog.askopenfilename(master=self.root, title="Open...")
print(self.file_name)
self.canvas.img = Image.open(self.file_name)
self.canvas.img_width, self.canvas.img_height = self.canvas.img.size
@ -118,7 +130,7 @@ class PaintApplication(framework.Framework):
def on_save_as_menu_clicked(self):
file_name = filedialog.asksaveasfilename(
master=self.root, filetypes=[('All Files', ('*.ps', '*.ps'))], title="Save...")
master=self.root, filetypes=[('All Files', ('*.png'))], title="Save...")
if not file_name:
return
self.file_name = file_name
@ -165,10 +177,11 @@ class PaintApplication(framework.Framework):
def on_decensor_menu_clicked(self, event=None):
combined_img = Image.alpha_composite(self.canvas.img.convert('RGBA'), self.drawn_img)
decensorer = decensor.Decensor()
decensorer.decensor_image(combined_img.convert('RGB'), self.file_name + ".png")
print(self.file_name)
decensorer.decensor_image(combined_img.convert('RGB'),combined_img.convert('RGB'), self.file_name + ".png")
save_path = self.file_name + ".png"
messagebox.showinfo(
"Decensoring", "Decensoring complete!")
"Decensoring", "Decensoring complete! image saved to {save_path}".format(save_path=save_path))
def on_about_menu_clicked(self, event=None):
# messagebox.showinfo(
# "Decensoring", "Decensoring in progress.")
@ -218,11 +231,30 @@ class PaintApplication(framework.Framework):
self.canvas.bind("<B1-Motion>", self.draw_irregular_line_update_x_y)
# Creates circular indicator for brush size, modified from https://stackoverflow.com/questions/42631060/draw-a-defined-size-circle-around-cursor-in-tkinter-python
def motion(self, event=None):
x, y = event.x, event.y
# the addition is just to center the oval around the center of the mouse
# remove the the +3 and +7 if you want to center it around the point of the mouse
self.canvas.delete(self.circle) # to refresh the circle each motion
radius = self.brush_width/2.0 # change this for the size of your circle
x_max = x + radius
x_min = x - radius
y_max = y + radius
y_min = y - radius
self.circle = self.canvas.create_oval(x_max, y_max, x_min, y_min, outline="black")
def draw_irregular_line_update_x_y(self, event=None):
self.start_x, self.start_y = self.end_x, self.end_y
self.end_x, self.end_y = self.adjust_canvas_coords(event.x, event.y)
# self.motion(event)
self.draw_irregular_line()
self.motion(event)
def draw_irregular_line_options(self):
self.create_fill_options_combobox()
self.create_width_options_combobox()
@ -414,19 +446,23 @@ class PaintApplication(framework.Framework):
self.start_x = self.end_x = self.canvas.canvasx(event.x)
self.start_y = self.end_y = self.canvas.canvasy(event.y)
self.execute_selected_method()
self.motion(event)
def on_mouse_button_pressed_motion(self, event):
self.end_x = self.canvas.canvasx(event.x)
self.end_y = self.canvas.canvasy(event.y)
self.canvas.delete(self.current_item)
self.motion(event)
self.execute_selected_method()
def on_mouse_button_released(self, event):
self.end_x = self.canvas.canvasx(event.x)
self.end_y = self.canvas.canvasy(event.y)
self.motion(event)
def on_mouse_unpressed_motion(self, event):
self.show_current_coordinates(event)
self.motion(event)
def create_gui(self):
self.create_menu()