PDFCropper/ui.py
2021-05-26 14:42:03 +08:00

213 lines
8.4 KiB
Python

import tkinter as tk
from tkinter import Text, ttk
from tkinter.constants import DISABLED, RIGHT, NORMAL, END
import tkinter.filedialog
import tkinter.font as tkFont
from PIL import Image, ImageTk, ImageFont, ImageDraw
from tkinter.colorchooser import askcolor
import sys
class StdSimulator():
def __init__(self, box) -> None:
self.box = box
self.stdout = sys.stdout
self.stderr = sys.stderr
def write(self, msg):
self.box.insert(END, msg)
self.box.see(END)
def flush(self):
pass
def text_on_image(img, text, pos, size=16, color='#000000'):
imgdraw = ImageDraw.Draw(img)
imgfont = ImageFont.truetype("msyh.ttc",size=size)
textw, texth = imgdraw.textsize(text, font=imgfont)
left_top = (pos[0]-int(textw/2), pos[1]-int(texth/2))
imgdraw.text(left_top, text, fill=color, font=imgfont)
return img
class Loader(tk.Frame):
def __init__(self, master=None, conf={}, execution=None, title=None):
super().__init__(master)
self.master = master
self.conf = conf
self.execution = execution
self.title = title
self.pack(fill='both', expand=1)
self.resources = {}
self.fontStyle = tkFont.Font(size=10, family='微软雅黑')
self.fontStyle_anchor = tkFont.Font(size=16)
self.create_widgets()
# self.font = tk.Font(family='', size=40,weight='',slant='',underline='',overstrike='')
if self.title is not None:
self.master.title(self.title)
def add_resource(self, obj, name):
if name in self.resources:
print('Name [{0}] Repeated.'.format(name))
print('Current used name:', list(self.resources.keys()))
raise ValueError
self.resources[name] = obj
def add_entry(self, default, width, layout, name, master=None):
if master is None:
master = self
resource = tk.Entry(master, width=width)
if type(default) is str:
resource.insert(0, default)
resource.grid(**layout)
self.add_resource(resource, name)
def add_label(self, text, layout, name, master=None):
if master is None:
master = self
resource = tk.Label(master, text=text, font=self.fontStyle)
resource.grid(**layout)
self.add_resource(resource, name)
def add_button(self, text, command, layout, size, name, image=None, master=None):
if master is None:
master = self
resource = {}
if image is not None:
width, height = size
image = image.resize((width,height))
if text is not None:
image = text_on_image(image, text, (int(width/2), int(height/2)), size=16, color='#000000')
img = ImageTk.PhotoImage(image)
resource['img'] = img
resource['button'] = tk.Button(master, text=text, command=command, borderwidth=0)
resource['button'].config(image=img)
else:
resource['button'] = tk.Button(master, text=text, command=command)
resource['button'].grid(**layout)
self.add_resource(resource, name)
def add_textbox(self, width, layout, name, master=None):
if master is None:
master = self
resource = tk.Text(master, width=width, state=NORMAL)
resource.grid(**layout)
# vsb = tk.Scrollbar(self, orient="vertical", command=resource.yview)
# resource.configure(yscrollcommand=vsb.set)
self.add_resource(resource, name)
# self.add_resource(vsb, name + '_scroll')
def choose_file(self, dst, choose_type='readfile', extension=None, initial_file=None):
default_extension = ("所有文件", '.*')
args = {"filetypes": []}
if extension is not None:
args['filetypes'].append(extension)
args['filetypes'].append(default_extension)
if initial_file is not None:
args['initialfile'] = initial_file
# print('args:', args)
filename = ''
if choose_type == 'readfile':
filename = tkinter.filedialog.askopenfilename(**args)
elif choose_type == 'savefile':
filename = tkinter.filedialog.asksaveasfilename(**args)
elif choose_type == 'directory':
args = {
'initialdir': initial_file
}
filename = tkinter.filedialog.askdirectory(**args)
if filename != '':
self.resources[dst].delete(0, 'end')
self.resources[dst].insert(0, filename)
def choose_color(self, dst):
color = askcolor()[0]
if color is not None:
color = [str(c) for c in color]
color = ','.join(color)
self.resources[dst].delete(0, 'end')
self.resources[dst].insert(0, color)
def execute(self):
conf = {}
for key in self.resources:
dtype, name = key.split('_', maxsplit=1)
if dtype == 'entry':
conf[name] = self.resources[key].get()
self.execution(conf)
def create_widgets(self):
self.rowcount = 0
for key, value in self.conf.items():
name = value['name']
dtype = value['type']
default = value.get('default', '')
self.add_label(name, {"row": self.rowcount, "column": 0, "padx": 10, "pady": 5}, name="label_" + key)
self.add_entry(
default=default,
width=None,
layout={"row": self.rowcount, "column": 1, "padx": 0, "sticky": "we"},
name='entry_' + key
)
destination = 'entry_' + key
if dtype in ['readfile', 'savefile', 'directory']:
extension = value.get('extension', None)
initialfile = default
args = {
"dst": destination,
"choose_type": dtype,
"extension": extension,
"initial_file": initialfile
}
self.add_button(
text="选择文件",
command=lambda args=args:self.choose_file(**args),
size=(16, 16),
layout={"row":self.rowcount, "column": 2, "padx": 5},
name='{0}_choose'.format(name),
image=None
)
self.conf[key]['type'] = 'str'
elif dtype == 'color':
self.add_button(
text="选择颜色",
command=lambda dst=destination:self.choose_color(dst),
size=(16, 16),
layout={"row":self.rowcount, "column": 2, "padx": 5},
name='{0}_choose'.format(name),
image=None
)
self.rowcount += 1
self.add_button(
text=" 裁剪 ",
command=self.execute,
size=(16, 16),
layout={"row":self.rowcount, "column": 0, "columnspan": 2, "pady": 5},
name='execute_final'
)
self.add_textbox(
width=40,
layout={"row":0, "column": 3, "rowspan": self.rowcount, "padx": 5, "pady": 0},
name="textbox_log"
)
sys.stdout = StdSimulator(self.resources['textbox_log'])
sys.stderr = StdSimulator(self.resources['textbox_log'])
if __name__ == '__main__':
conf = {
"input": {"name": "源文件", "type": "readfile", "extension": ("PDF & PPT", ".pdf .pptx")},
"output": {"name": "保存路径", "type": "savefile"},
"background_color": {"name": "背景颜色", "type": "color", "default": "255,255,255"},
"border": {"name": "留白", "type": "str", "default": "0.0"},
"zoom": {"name": "缩放等级", "type": "str", "default": "1.0"},
"thresh": {"name": "阈值", "type": "str", "default": "1.0"},
"split": {"name": "拆分", "type": "str", "default": "false"},
"names": {"name": "页名称", "type": "str"},
"visual": {"name": "显示裁切框", "type": "str", "default": "false"},
"mute": {"name": "显示保存文件", "type": "str", "default": "false"},
}
root = tk.Tk()
Loader(master=root, conf=conf)
root.mainloop()