Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
193 views
in Technique[技术] by (71.8m points)

python 3.x - Diary in Tkinter

Hi everybody have assignment diary, i had been created my diary but my concern is that, my Professor want us to make 4 Diaries in this file. Kindly help me to add additional diaries inside. i dont have really idea for it. Hope to this site got what I'm looking for

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you want to expand your diary items, it should be better to put the diary items in external file and read them in your backend library. Also you should put the bounding checking in the backend library as well. Then you main application will not need to be changed due to change of the diary items.

I have modified your backend (PhotoDiaryLib.py) code using class as below:

from PIL import ImageTk, Image
import json

class PhotoDiary:
    def __init__(self, width=500, height=500):
        self.imageWidth = width
        self.imageHeight = height
        self.current = -1
        self.diary = None
        self.loadDiaries()

    def loadDiaries(self):
        with open('diaries.json') as f:
            self.diaries = json.load(f)

    def getDiaryList(self):
        return self.diaries.keys()

    def getDiaryImage(self, diary):
        return self.diaries[diary]['image']

    def setDiary(self, diary):
        self.diary = diary
        self.diaryDetails = self.diaries[diary]['items']
        self.current = -1

    def getImage(self, imageName):
        originalImage = Image.open(imageName)
        imageRatio = float(originalImage.size[0]) / float(originalImage.size[1])
        if imageRatio > 1:
            targetSize=(self.imageWidth, int(self.imageHeight/imageRatio))
        else:
            targetSize=(int(self.imageWidth*imageRatio), self.imageHeight)
        resizedImage = originalImage.resize(targetSize, Image.ANTIALIAS)
        return ImageTk.PhotoImage(resizedImage)

    def get(self, index):
        ''' get the diary item at given index '''
        if 0 <= index < len(self.diaryDetails):
            self.current = index
            details, imageName = self.diaryDetails[index]
            return details, self.getImage(imageName)
        return None, None

    # navigation functions
    next = lambda self: self.get(self.current+1)
    previous = lambda self: self.get(self.current-1)

And diaries.json contains something like below:

{
  "Fish": {
    "image": "images/fish.jpg",
    "items": [
      ["Test1", "images/1.jpg"],
      ["Test2", "images/2.jpg"],
      ["Test3", "images/3.jpg"],
      ["Test4", "images/4.png"]
    ]
  },
  "Birds": {
    "image": "images/birds.jpg",
    "items": [
      ...
    ]
  },
  "Mammals": {
    "image": "images/mammals.jpg",
    "items": [
      ...
    ]
  },
  "Snakes": {
    "image": "images/snakes.jpg",
    "items": [
      ...
    ]
  }
}

You can add more items into the JSON file.

Then modify your main application to cater the change of the backend library:

from tkinter import *
from PIL import ImageTk,Image
from PhotoDiaryLib import PhotoDiary

class PhotoDiaryApp:
    def __init__(self):
        self.mainWindow = Tk()
        self.mainWindow.title("Diary")

        self.pd = PhotoDiary(500, 500)
        self.current = StringVar()

        # diary list
        diaryFrame = Frame(self.mainWindow, bg='blue')
        for i, item in enumerate(self.pd.getDiaryList()):
            imgtk = ImageTk.PhotoImage(file=self.pd.getDiaryImage(item))
            btn = Radiobutton(diaryFrame, text=item, image=imgtk, compound=TOP, indicatoron=0, variable=self.current, value=item)
            btn.config(command=lambda d=item:self.changeDiary(d))
            btn.grid(row=0, column=i, sticky='ew', ipadx=10)
            btn.image = imgtk
            if i == 0: self.current.set(item)
        diaryFrame.pack(fill=X)

        # diary detail frame
        detailFrame = Frame(self.mainWindow)
        detailFrame.pack(fill=BOTH, expand=1)

        self.photoFrame = Frame(detailFrame)
        self.labelFrame = Frame(detailFrame)
        self.controlFrame = Frame(detailFrame)

        self.canvasImage = Canvas(self.photoFrame, width=500, height=500)
        self.canvasImage.pack()
        self.photo = self.canvasImage.create_image(250, 250, image=None)

        self.photoDetails = StringVar()
        self.photoLabel = Label(self.labelFrame, textvariable=self.photoDetails)
        self.photoLabel.pack()

        self.previousButton = Button(self.controlFrame, command=self.previousEntry, text="Previous", width=10)
        self.previousButton.pack(side='left')
        self.previousNext = Button(self.controlFrame, command=self.nextEntry, text="Next", width=10)
        self.previousNext.pack(side='left')

        self.photoFrame.pack()
        self.labelFrame.pack()
        self.controlFrame.pack(pady=10)

        # show first diary
        self.changeDiary(self.current.get())

        self.mainWindow.mainloop()

    def changeDiary(self, diary):
        #print(self.pd.diary, diary)
        if self.pd.diary != diary:
            print('Changed to diary:', diary)
            self.pd.setDiary(diary)
            self.nextEntry()

    def updateDiary(self, details, image):
        ''' update photo details and image '''
        if details and image:
            self.photoDetails.set(details)
            self.photoImage = image
            self.canvasImage.itemconfig(self.photo, image=image)

    def previousEntry(self):
        self.updateDiary(*self.pd.previous())

    def nextEntry(self):
        self.updateDiary(*self.pd.next())

executeWindow = PhotoDiaryApp()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...