学习python日记

"""
        myTk008.py
        为指定文件夹中图片加注释文字,相关信息保存到json数据文件中。
        2022年8月 在python3.7下调试通过。
"""
import os
from tkinter import *
import tkinter as ttk
from PIL import Image,ImageTk
from mylx2 import myfiles,mysystem,myfile_list
import tkinter.filedialog as tkf
from time import sleep
import json
import codecs

def call_back(event):
    print(event.keysym)

class MyTk_001(ttk.Frame):

    def __init__(self, master: Tk,title,width, height,path='D:/2022/image', **kw):

        # 变量X和Y用来记录鼠标左键按下的位置
        self.X = ttk.IntVar(value=0)
        self.Y = ttk.IntVar(value=0)
        self.selectPosition = None

        super().__init__(master, **kw)


        self.mroot = master
        self.mainframe = ttk.Frame(master,bg='black')
        self.mainframe.pack()
        #self.mainframe.grid(column=0, row=0, sticky=NSEW)


        self.width = width
        self.height = height

        self.canvas = Canvas(self.mainframe, width=self.width, height=self.height, background='gray55')
        self.canvas.pack()

        # set window's title.
        self.master.title(title + '         鼠标:左键定位,中键换页,右键选标注')

        # set window's geometry size
        ss='%sx%s+%s+%s' % (width,160+height,50,50)

        self.master.geometry(ss)




        self.canvas.bind(sequence='<Button-1>', func=self._onLeftButtonDown)
        self.canvas.bind(sequence='<B1-Motion>', func=self._onLeftButtonMove)

        self.canvas.bind(sequence='<ButtonRelease-1>',func=self._onLeftButtonUp)

        self.canvas.bind(sequence='<Button-2>', func=self._PriNext)

        self.canvas.bind(sequence='<Button-3>', func=self._select)

        self.canvas.pack(fill=ttk.BOTH, expand=ttk.YES)

        h = self.height
        h1 = 100

        # 标注
        label_Biaozhu = ttk.Label(self.mroot,text='标注:')
        label_Biaozhu.place(x=50, y=h+50)

        #global input_valueText
        self.inputText = ttk.Entry(self.mroot, width=12)
        self.inputText.place(x=100, y=h+40, width=180, height=30, anchor=NW)
        self.inputText.bind('<Return>',func=self._mytext)

        App = ttk.Button(self.mroot, text='追加', command=self._save)
        App.place(x=350, y=h+40, w=100, h=40)

        Exit = ttk.Button(self.mroot, text='退出', command=(ttk._exit))
        Exit.place(x=50, y=h+h1, w=100, h=40)



        Lood = ttk.Button(self.mroot, text='加载', command=self._get_files)
        Lood.place(x=200, y=h+h1, w=100, h=40)


        #save_jsonfile
        Save_json = ttk.Button(self.mroot, text='Save_json', command=self._save_jsonfile)
        Save_json.place(x=350, y=h + h1, w=100, h=40)

        # open_jsonfile
        Open_json = ttk.Button(self.mroot, text='Open_json', command=self._open_jsonfile)
        Open_json.place(x=500, y=h + h1, w=100, h=40)

        # 系统提示
        #  self.stateValue.set('系统提示:')
        self.stateValue = ttk.Label(self.mroot)
        self.stateValue.place(x=10, y=h+10)



        self._init_selectPosition()
        self.id = 0
        self.bz_id = 0
        self.mydict = {}
        self.Factor_Dict = {}
        self._get_files0(path)
        self._resizes()
        self._show0()
        self._show_state()


    def _show_state(self):
        k = str(self.id)
        if k in self.mydict.keys():
            self.bz_list = self.mydict[k]
        else:
            self.bz_list = []
        bzlen = len(self.bz_list)
        mstate = '目录名:%s   文件名:%s %s/%s       标注:%s/%s' % (self.path,
                                                      self.file_list[self.id],
                                                      self.id + 1,
                                                      len(self.file_list),
                                                      self.bz_id + 1,
                                                      bzlen)

        self.stateValue['text'] = mstate
        

    # 鼠标左键按下的位置
    def _onLeftButtonDown(self,event):
        self.X.set(event.x)
        self.Y.set(event.y)
        # 开始截图
        self.sel = True

    # 鼠标左键移动,显示选取的区域
    def _onLeftButtonMove(self,event):
        if not self.sel:
            return
        global lastDraw
        try:
            # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形
            self.canvas.delete(lastDraw)
        except Exception as e:
            pass
        lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red')

    # 获取鼠标左键抬起的位置,保存区域截图
    def _onLeftButtonUp(self,event):
        self.sel = False
        try:
            self.canvas.delete(lastDraw)
        except Exception as e:
            pass
        sleep(0.1)


        # 考虑鼠标左键从右下方按下而从左上方抬起的截图
        myleft, myright = sorted([self.X.get(), event.x])
        mytop, mybottom = sorted([self.Y.get(), event.y])
        print(myleft,mytop,myright,mybottom)
        # Position : x , y, w, h
        self.selectPosition = (myleft,mytop,myright,mybottom)
        self._show_BzOne()

    def _PriNext(self,event):
        self._Delete_Bz()
        self.inputText.delete(0, END)
        if event.x < self.width // 2:           #private
            self.id -= 1
            if self.id < 0:
                self.id = len(self.file_list) -1
        else:       #Next
            self.id += 1
            if self.id == len(self.file_list):
                self.id = 0

        self._show0()
        self._show_Bz0()
        self._show_state()

    def _select(self,event):
        self._show_BzId(self.bz_id)
        x = event.x
        y = event.y
        find = False
        i = 0
        k = str(self.id)
        if k in self.mydict.keys():
            self.bz_list = self.mydict[k]
            for bz in self.bz_list:
                box = bz[1]
                if (x >= box[0]) and  (x <= box[2]) and  (y >= box[1]) and (y <= box[3]):
                    self.bz_id = i
                    find = True
                    break
                i += 1
        if find == True:
            self._show_BzId(self.bz_id)
            self.bz_id = i
            bz = self.bz_list[self.bz_id]
            mtext = bz[0]
            self.selectPosition = bz[1]
            self.inputText.delete(0, END)
            self.inputText.insert(0, mtext)
            self._show_BzOne()
        else:
            self.bz_id = i
            self._show_BzOne()
            self.inputText.delete(0, END)
        self._show_state()





    def _mytext(self,event):
        k = str(self.id)
        if k in self.mydict.keys():
            self.bz_list = self.mydict[k]
        else:
            self.bz_list = []
        self._show_BzOne()
        if self.bz_id == len(self.bz_list):
            pass
        else:
            self._save()

    def _save(self):
        mtext = self.inputText.get()
        if len(mtext) == 0:
            print('标注不能为空!')
            return

        item = (mtext, self.selectPosition)
        k = str(self.id)
        if k not in self.mydict.keys():
            self.bz_list = []
        else:
            self.bz_list = self.mydict[k]

        if self.bz_id == len(self.bz_list):
            self.bz_list.append((mtext,self.selectPosition))
            print(self.bz_list)
            self.mydict[k] = self.bz_list
            self._show_BzId(self.bz_id)
            self.bz_id += 1

            self.inputText.delete(0, END)
            self._init_selectPosition()
            self._show_BzOne()

        else:
            self.bz_list[self.bz_id] = (mtext,self.selectPosition)
            self.mydict[k] = self.bz_list
        self._show_state()







    def _show_BzOne(self):
        bzname = 'bzname%d' % self.bz_id
        try:
            self.canvas.delete(bzname)
        except:
            pass

        mtext = self.inputText.get()
        print(self.selectPosition)
        x = (self.selectPosition[0] + self.selectPosition[2]) // 2
        y = (self.selectPosition[1] + self.selectPosition[3]) // 2
        h = (self.selectPosition[3] - self.selectPosition[1])
        w = (self.selectPosition[2] - self.selectPosition[0])
        #underline
        #self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal'))

        self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'underline'))


    def _show_BzId(self,bzid):
        bzname = 'bzname%d' % bzid
        try:
            self.canvas.delete(bzname)
        except:
            pass

        if bzid == len(self.bz_list):
            mtext = self.inputText.get()
            box = self.selectPosition
        else:
            bz = self.bz_list[bzid]
            mtext = bz[0]
            box = bz[1]

        x = (box[0] + box[2]) // 2
        y = (box[1] + box[3]) // 2
        h = (box[3] - box[1])
        w = (box[2] - box[0])
        self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal'))


    def _Delete_Bz(self):
        self.bz_id = 0
        k = str(self.id)
        if k in self.mydict.keys():
            self.bz_list = self.mydict[k]
        else:
            self.bz_list = []
        for bz in self.bz_list:
            bzname = 'bzname%s' % self.bz_id
            self.canvas.delete(bzname)
            self.bz_id += 1
        bzname = 'bzname%s' % self.bz_id
        self.canvas.delete(bzname)


    def _init_selectPosition(self):
        x = self.width // 2
        y = self.height // 2
        h = 10
        self.selectPosition = (x - 5 * h, y - h, x + 5 * h, y + h)


    def _show_Bz0(self):

        self.bz_id = 0
        k = str(self.id)
        if k in self.mydict.keys():
            self.bz_list = self.mydict[k]
            for bz in self.bz_list:
                bzname = 'bzname%s' % self.bz_id
                mtext = bz[0]
                box = bz[1]

                x = (box[0] + box[2]) // 2
                y = (box[1] + box[3]) // 2
                h = (box[3] - box[1])
                self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal'))
                self.bz_id += 1

        self._init_selectPosition()
        self._show_BzOne()


    def _show0(self):
        global image
        global im
        global out

        filen = self._getfilen(self.id)
        if filen == None:
            return

        image = Image.open(filen)

        if self.id in self.Factor_Dict.keys():
            out = self._resize1(image)
        else :
            out = self._resize(self.width, self.height, image)
        im = ImageTk.PhotoImage(out)

        w = (self.width - im.width()) // 2
        h = (self.height - im.height()) // 2

        self.canvas.delete('image')
        self.canvas.create_image(self.width // 2, self.height // 2, image=im, tag='image')

    def _Load_image(self):
        self._Delete_Bz()
        self.inputText.delete(0, END)
        self.id += 1
        if self.id == len(self.file_list):
            self.id = 0

        self._show0()
        self._show_Bz0()


    def _private(self):
        if self.bz_id>0 :
            self._show_BzId(self.bz_id)
            self.bz_id -= 1
            bz = self.bz_list[self.bz_id]
            mtext = bz[0]
            self.selectPosition = bz[1]
            self.inputText.delete(0,END)
            self.inputText.insert(0,mtext)
            self._show_BzOne()
        else:
            k = str(self.id)
            if k in self.mydict.keys():
                self.bz_list = self.mydict[k]
                self.bz_id = len(self.bz_list)
            else:
                self.bz_id = 0
                self.bz_list = []
            self._init_selectPosition()
            self.inputText.delete(0, END)



    def _resize(self,w_box, h_box, pil_image):
        # get the size of the image
        # 获取图像的原始大小
        w, h = pil_image.size
        print(w,h,w_box, h_box)
        '''
        resize a pil_image object so it will fit into
        a box of size w_box times h_box, but retain aspect ratio
        对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例
        '''
        f1 = 1.0 * w_box / w  # 1.0 forces float division in Python2
        f2 = 1.0 * h_box / h
        factor = min([f1, f2])
        # print(f1, f2, factor) # test
        # use best down-sizing filter
        width = int(w * factor)
        height = int(h * factor)
        #print('_resize')
        temp = (factor,(w_box-width) // 2,(h_box-height) // 2)
        self.Factor_Dict[self.id] = temp
        return pil_image.resize((width, height), Image.DEFAULT_STRATEGY)  #Image.ANTIALIAS

    def _resize1(self,pil_image):
        temp = self.Factor_Dict[self.id]
        width = self.width - temp[1] * 2
        height = self.height - temp[2] * 2
        #print('_resize1')
        return pil_image.resize((width, height), Image.DEFAULT_STRATEGY)

    def _resizes(self):
        self.Factor_Dict.clear()
        for i in range(0,len(self.file_list)-1):
            #print(i)
            filen = self._getfilen(i)
            #print(i,filen)
            pil_image = Image.open(filen)
            w, h = pil_image.size
            f1 = 1.0 * self.width / w
            f2 = 1.0 * self.height / h
            factor = min([f1, f2])
            print("factor:",type(factor))
            width = int(w * factor)
            height = int(h * factor)
            temp = (factor, (self.width - width) // 2, (self.height - height) // 2)
            self.Factor_Dict[i] = temp

    def _getfilen(self,i):
        #print(id)
        if (i >= 0) and (i < len(self.file_list) - 1):
            filen = os.path.join(self.path, self.file_list[i])
            return filen

    # 打开图片文件并显示
    def _get_files(self):
        path = tkf.askdirectory()
        if path:
            self._get_files0(path)


    def _get_files0(self,path):
        mclass = myfile_list(path, "jpg|png")
        self.path = path
        self.file_list = mclass.file_list
        self.Factor_Dict.clear()
        self.mydict.clear()
        self.id = 0
        self.id = 0
        self.bz_id = 0
        if len(mclass.file_list) > 0:
            self._resizes()
            self._Load_image()
        self._show_state()

    def _save_jsonfile(self):
        json_content = {}

        json_content['path'] = self.path
        json_content['files'] = self.file_list
        json_content['Factor_Dict'] = self.Factor_Dict
        json_content['mydict'] = self.mydict

        # 存入json文件
        final_json = json.dumps(json_content, ensure_ascii=False)
        jsonfileName = "d:\\2022\\data\\data_json.json"
        with codecs.open(jsonfileName, 'a', 'utf-8') as file:
            file.write(final_json)
            file.close()
        print('save_jsonfile:%s' % jsonfileName)

    def _open_jsonfile(self):
        jsonfileName = "d:\\2022\\data\\data_json.json"
        with codecs.open(jsonfileName, 'r','utf-8') as file:
            data = json.load(file)
            file.close()
        print('open_jsonfile:%s' % jsonfileName)
        print(data['path'])
        print(data['files'])
        print(data['Factor_Dict'])
        print(data['mydict'])
        self._get_files1(data)
    def _get_files1(self,data):
        self.path = data['path']
        self.file_list = data['files']
        self.Factor_Dict.clear()
        self.Factor_Dict = data['Factor_Dict']
        self.mydict.clear()
        self.mydict = data['mydict']
        print('mydict-len=',len(self.mydict))
        self.id = 0
        self.id = 0
        self.bz_id = 0
        if len(self.file_list) > 0:
            self._Load_image()
        self._show_state()

    def _call_back(event):
        print(event.keysym)


root = Tk()

# 不允许改变窗口大小
root.resizable(False, False)
root.focusmodel()


mytk = MyTk_001(root,"窗口程序__图片标注",800,600)
root.mainloop()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值