from tkinter import *
from tkinter.ttk import *
from tkinter.font import *
from tkinter.simpledialog import *
from tkinter.filedialog import *
from tkinter.messagebox import *
from tkinter.scrolledtext import ScrolledText
import tkinterDnD
from PIL import ImageTk, Image
#
# Libraries
#
class PilImage():
def __init__(self, image):
if type(image) == str: self.image = Image.open(image)
else:
self.image = Image.new('P', image)
newData = [(255, 255, 255, 0) for i in range(len(self.image.getdata()))]
self.image.putdata(newData)
def resize(self,size):
width = size[0]
radio = width / self.image.width
height = int(radio * self.image.height)
if height > size[1]:
height = size[1]
radio = height / self.image.height
width = int(radio * self.image.width)
self.image = self.image.resize((width,height), resample=0)
return self
#
# Controls
#
class ScrolledList(Frame):
def __init__(self,parent,events={}):
super().__init__(parent)
frame = self
self.listbox = Listbox(frame)
self.listbox.config(selectmode='extended')
self.listbox.config()#width=w,height=h)
self.listbox.pack(side=LEFT,fill=Y,expand=True)
if events.get('select'): self.listbox.bind('<<ListboxSelect>>', events['select'])
scroll = Scrollbar(frame,orient=VERTICAL,command=self.listbox.yview)
scroll.pack( side=RIGHT, fill=Y )
self.listbox.config( yscrollcommand = scroll.set)
def Count(self): return self.listbox.size()
def AddItem(self,value,index=END): self.listbox.insert(index,value)
def DeleteItem(self,index): self.listbox.delete(index)
def SelectedIndex(self): return self.listbox.curselection()
#def SelectedItem(self): return self.listbox.get(self.listbox.curselection())
class Text(ScrolledText):
def __init__(self,parent): super().__init__(parent)
def Clear(self): self.delete("1.0",END); return self
def AddText(self,value): self.insert(END,value); return self
def SetText(self,value): self.Clear(); self.AddText(value); return self
def GetText(self): return self.get("1.0",END)
class TextField(Entry):
def __init__(self,parent,events={}):
super().__init__(parent)
if events.get('enter'): self.bind("<Return>",events['enter'])
def Clear(self): self.delete(0,END); return self
def AddText(self,value): self.insert(END,value); return self
def SetText(self,value): self.Clear(); self.AddText(value); return self
def GetText(self): return self.get(0,END)
#
# Containers
#
def Splitter(parent,layout,panels,params={'orient' : HORIZONTAL }):
splitter = PanedWindow(parent,params)
for panel in panels: splitter.add(panel(splitter))
splitter.pack(layout)
return splitter
def Tab(parent,layout,labels,panels):
tab = Notebook(parent)
for index,panel in enumerate(panels): tab.add(panel(tab),text=labels[index])
tab.pack(layout)
return tab
def Box(parent,layout,panels):
frame = Frame(parent)
for panel in panels: panel(frame)
frame.pack(layout)
return frame
#
# Layouts
#
def Control(ctrl,layout,params={},events={}):
control = {}
control['ctrl'] = ctrl
control['layout'] = layout
control['params'] = params
control['events'] = events
return control
def Panel(parent,layout,controls):
def GetControl(parent,ctrl,handler=None):
params = ctrl['params']
events = ctrl['events']
if ctrl['ctrl'] == 'List': c = ScrolledList(parent,events)
elif ctrl['ctrl'] == 'Text': c = Text(parent)
elif ctrl['ctrl'] == 'TextField': c = TextField(parent,events)
elif ctrl['ctrl'] == 'Button': c = Button(parent) #,params)
elif ctrl['ctrl'] == 'Label': c = Label(parent) #,params)
else: return None
if events.get('drop'): c.register_drop_target("*"); c.bind("<<Drop>>",events['drop'])
c.config(params)
c.pack(ctrl.get('layout'))
return c
widgets = []
f = Frame(parent)
for ctrl in controls: widgets.append(GetControl(f,ctrl))
f.pack(layout)
return (f, widgets)
#
# Application
#
page_list = []
image_file = None
image_label = None
list_box = None
text_edit = None
output_edit = None
def MakeOutputFrame(parent):
global output_edit
ctrl_1 = Control('Label',
layout = { 'side' : LEFT, 'padx' : 10 },
params = { 'text' : 'Output', } )
ctrl_2 = Control('TextField',
layout = { 'side' : LEFT, 'expand' : True, 'fill' : X },
#params = { 'text' : 'Open', },
events = { 'enter' : make_handler2 } )
ctrl_3 = Control('Button',
layout = { 'side' : LEFT, 'padx' : 10},
params = { 'text' : 'Open', 'command' : open_handler })
(frame, widgets) = Panel(parent,
layout = { 'side' : TOP, 'fill' : X},
controls = (ctrl_1, ctrl_2, ctrl_3) )
output_edit = widgets[1]
return frame
def MakeTitleFrame(parent):
global output_edit
ctrl_1 = Control('Label',
layout = { 'side' : LEFT, 'padx' : 10 },
params = { 'text' : 'Title', } )
ctrl_2 = Control('TextField',
layout = { 'side' : LEFT, 'expand' : True, 'fill' : X, 'padx' : 10 },
events = { 'enter' : make_handler2 } )
(frame, widgets) = Panel(parent,
layout = { 'side' : TOP, 'fill' : X, 'pady' : 5},
controls = (ctrl_1, ctrl_2, ) )
output_edit = widgets[1]
return frame
def MakeSplitter(parent):
def MakeListFrame(parent):
def MakeListBox(parent):
global list_box
ctrl_1 = Control('List',
layout = { 'side' : TOP , 'expand' : True , 'fill' : BOTH},
events = {'select' : list_selected} )
(frame, widgets) = Panel(parent,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH},
controls = (ctrl_1, ))
list_box = widgets[0]
return frame
def MakeButtonBox(parent):
ctrl_2 = Control('Button',
layout = { 'side' : RIGHT, 'padx' : 5 },
params = { 'text' : 'Make', 'command' : make_handler })
ctrl_3 = Control('Button',
layout = { 'side' : RIGHT, },
params = { 'text' : 'Delete', 'command' : delete_handler })
(frame, widgets) = Panel(parent,
layout = { 'side' : BOTTOM, 'fill' : X, 'pady' : 5,'padx' : 5 },
controls = (ctrl_2, ctrl_3))
return frame
return Box( parent,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH, 'pady' : 5,'padx' : 10 },
panels = (MakeListBox, MakeButtonBox, ))
def MakeImageFrame(parent):
def MakePageBox(parent):
global image_label, text_edit
ctrl_1 = Control('Label',
layout = { 'expand' : True , 'fill' : BOTH},
params = {'bg' : 'white'},
events = {'drop' : image_drop})
ctrl_2 = Control('Text',
layout = { 'side' : BOTTOM, 'anchor' : S, 'fill' : BOTH,'pady' : 5},
params = { 'height' : 3 })
(frame, widgets) = Panel(parent,
layout = { 'side' : BOTTOM, 'expand' : True, 'fill' : BOTH },
controls = (ctrl_2, ctrl_1, ))
image_label = widgets[1]
text_edit = widgets[0]
return frame
def MakeButtonBox(parent):
ctrl_3 = Control('Button',
layout = { 'side' : RIGHT, 'padx' : 5 },
params = { 'text' : 'Add', 'command' : add_handler })
ctrl_4 = Control('Button',
layout = { 'side' : RIGHT },
params = { 'text' : 'Update', 'command' : update_handler })
ctrl_5 = Control('TextField',
layout = { 'side' : RIGHT, 'expand' : True, 'fill' : X, 'padx' : 10 },
#params = { 'text' : 'Open', },
)
ctrl_6 = Control('Label',
layout = { 'side' : RIGHT },
params = { 'text' : 'Outline', } )
(frame, widgets) = Panel(parent,
layout = { 'side' : BOTTOM, 'fill' : X, 'pady' : 5,'padx' : 5 },
controls = (ctrl_3, ctrl_4, ctrl_5, ctrl_6))
return frame
return Box( parent,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH, 'pady' : 10,'padx' : 10 },
panels = ( MakeButtonBox, MakePageBox, ))
return Splitter( parent,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH, 'pady' : 10,'padx' : 10 },
params = { 'orient' : HORIZONTAL },
panels = ( MakeListFrame, MakeImageFrame ) )
def open_handler():
#text = askdirectory()
text = asksaveasfilename(initialdir="/", title="Select file",
filetypes=(("PDF files", "*.pdf"),
("all files", "*.*")))
if len(text) > 0:
output_edit.SetText(text)
def list_selected(ev):
global text_edit, image_label, page_list, page_item, image_thumb, image_file
index = ev.widget.curselection()[0]
image_label.config(image = page_list[index][1])
text_edit.SetText(page_list[index][2])
image_thumb = page_list[index][1]
image_file = page_list[index][0]
def image_drop(ev):
global image_label, image_thumb, image_file, text_edit
im = PilImage(ev.data).resize((image_label.winfo_width(), image_label.winfo_height()))
image_thumb = ImageTk.PhotoImage(im.image) #Image.open("Lenna.png")
image_label.config(image = image_thumb); #image_label.image = image_thumb
image_file = ev.data
def add_handler():
global image_label, image_thumb, image_file, text_edit, list_box, page_list
page_item = [image_file, image_thumb, text_edit.GetText()]
page_list.append( page_item ); print(page_list)
list_box.AddItem("Page " + str(len(page_list)))
im = PilImage((image_label.winfo_width(), image_label.winfo_height()))
image_label.config( image = ImageTk.PhotoImage(im.image) )
text_edit.Clear()
def update_handler():
global image_label, image_thumb, image_file, text_edit, list_box, page_list
index = list_box.SelectedIndex()
if index[0] >= 0:
page_item = [image_file, image_thumb, text_edit.GetText()]
page_list[index[0]] = page_item; print(page_list)
im = PilImage((image_label.winfo_width(), image_label.winfo_height()))
image_label.config( image = ImageTk.PhotoImage(im.image) )
text_edit.Clear()
def delete_handler():
index = list_box.SelectedIndex()
if index[0] >= 0:
del page_list[index[0]]
list_box.DeleteItem(list_box.Count()-1)
def make_handler2(ev): make_handler()
def make_handler():
import pdf
import json
data = {}
data['title'] = 'Album'
data['pages'] = []
for page in page_list:
data['pages'].append( { \
'pictures' : [ page[0] ], \
'comment' : page[2] \
} )
pdf.make_pdf(json.dumps(data),'tkalbum.pdf')
showinfo( title="알림", message="생성되었습니다" )
if __name__ == "__main__":
root = tkinterDnD.Tk()
root.title("Album")
root.geometry("600x400")
root.resizable(False,False)
Box( root,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH, 'pady' : 10,'padx' : 10 },
panels = (MakeOutputFrame, MakeTitleFrame, MakeSplitter, ))
'''Tab( root,
layout = { 'side' : TOP, 'expand' : True, 'fill' : BOTH, 'pady' : 10,'padx' : 10 },
labels = ( 'Tab1', 'Tab2' ),
panels = ( MakeListFrame, MakeImageFrame ) )'''
root.mainloop()