Python Tkinter 哲学家问题可视化
发布日期:2021-05-08 20:30:48 浏览次数:18 分类:精选文章

本文共 7344 字,大约阅读时间需要 24 分钟。

Python Tkinter 哲学家问题可视化

学校的课设总算是告一段落,现在有时间分享一下代码和心得了。这次的文章是回应之前的雏形版代码的,这次的可是完全版哦。

我们先来看一下效果吧!
在这里插入图片描述
效果总归还行吧,代码也比较简短,只有170行。再此推荐你看我之前关于这个题目的文章,接下来我直接代码讲解了。

# -*- coding:utf-8 -*-#print('资源加载中,稍等片刻……')from tkinter import *from PIL import Image,ImageTk  from threading import Thread,Lockfrom time import sleepfrom random import randint"""哲学家类"""class Philosopher(Thread):    def __init__(self, index,forks,numForks,labels):        Thread.__init__(self)        self.index = index        self.forks=forks        self.numForks=numForks        self.rightFork = forks[self.index]        self.leftFork = forks[(self.index + 1) % numForks]        self.bm_thinking=ImageTk.PhotoImage(Image.open('img/thinking.png').resize((150,150),Image.ANTIALIAS))        self.bm_eating=ImageTk.PhotoImage(Image.open('img/eating.png').resize((150,150),Image.ANTIALIAS))        self.bm_waiting=ImageTk.PhotoImage(Image.open('img/waiting.png').resize((150,150),Image.ANTIALIAS))        self.bm_another=ImageTk.PhotoImage(Image.open('img/another.png').resize((150,150),Image.ANTIALIAS))    def run(self):        while True:            self.thinking()            self.hungry()            while True:                sleep(0.5)                if hobby.get()==True:#获取按钮的状态                    self.leftFork.pickup()                    labels[self.index].configure(image=self.bm_another)                    labels[self.index].image=self.bm_another                    text.insert(END,"Philosopher %s pick up left Fork.\n"%(self.index))                    sleep(0.5)                    self.rightFork.pickup()                    text.insert(END,"Philosopher %s pick up right Fork.\n"%(self.index))                    self.dining()                    self.leftFork.putdown()                    text.insert(END,"Philosopher %s put down left Fork.\n"%(self.index))                    self.rightFork.putdown()                    text.insert(END,"Philosopher %s put down right Fork.\n"%(self.index))                    break                else:                    if self.leftFork.use==False:                        if self.rightFork.use==False:                            self.leftFork.pickup()                            text.insert(END,"Philosopher %s pick up left Fork.\n"%(self.index))                            self.rightFork.pickup()                            text.insert(END,"Philosopher %s pick up right Fork.\n"%(self.index))                            self.dining()                            self.leftFork.putdown()                            text.insert(END,"Philosopher %s put down left Fork.\n"%(self.index))                            self.rightFork.putdown()                            text.insert(END,"Philosopher %s put down right Fork.\n"%(self.index))                            break                  def dining(self):        text.insert(END,"Philosopher %s starts to eat.\n"%(self.index))        labels[self.index].configure(image=self.bm_eating)        labels[self.index].image=self.bm_eating        sleep(randint(2,4))        text.insert(END,"Philosopher %s finishes eating.\n"%(self.index))    def thinking(self):        text.insert(END,"Philosopher %s is thinking.\n"%(self.index))        labels[self.index].configure(image=self.bm_thinking)        labels[self.index].image=self.bm_thinking        if not hobby2.get():#获取按钮的状态            sleep(randint(2,5))            def hungry(self):        text.insert(END,"Philosopher %s is hungry.\n"%(self.index))        labels[self.index].configure(image=self.bm_waiting)        labels[self.index].image=self.bm_waiting        sleep(1)

python图形化的特点,写代码的时候要和Tkinter里的组件结合,所以有时候会不知道类里的使用到的组件是哪来的,可以回到主程序里寻找。

"""叉子类"""class Fork:    def __init__(self, index,label_forks):        self.index = index        self.forks=label_forks        self._lock = Lock()        self.bm_fork=ImageTk.PhotoImage(Image.open('img/fork.png').resize((70,130),Image.ANTIALIAS))        self.bm_nothing=ImageTk.PhotoImage(Image.open('img/nothing.png').resize((70,130),Image.ANTIALIAS))        self.use=False        for i in self.forks:            i.configure(image=self.bm_fork)    def pickup(self):    """叉子的消失其实就是拿一张和背景色相同的图片来遮挡叉子的图片"""        self._lock.acquire()        self.use=True        self.forks[self.index].configure(image=self.bm_nothing)        self.forks[self.index].image=self.bm_nothing    def putdown(self):        self._lock.release()        self.use=False        self.forks[self.index].configure(image=self.bm_fork)        self.forks[self.index].image=self.bm_fork
def main():    text.delete('0.0','end')#清除文本框中的所有内容    numPhilosophers = numForks = 5    # 创建叉子与哲学家实例    forks = [Fork(idx,label_forks) for idx in range(numForks)]    philosophers = [Philosopher(idx,forks,numForks,labels)for idx in range(numPhilosophers)]        # 开启所有的哲学家线程    for philosopher in philosophers:        philosopher.start()
def author():#关于作者的说明,我没有用文本形式而是图片呈现"""必要一提的就是Tkinter不支持二级窗口呈现图片,所以要用Toplevel"""    newroot=Toplevel()    bm_about = ImageTk.PhotoImage(Image.open('img/about.png'))    aboutme=Label(newroot,image=bm_about)    aboutme.pack()    newroot.mainloop()def detail_show():#“说明”的内容    newroot2=Toplevel()    bm_details = ImageTk.PhotoImage(Image.open('img/details.png'))    details_label=Label(newroot2,image=bm_details)    details_label.pack()    newroot2.mainloop()
if __name__ == '__main__':    root = Tk()    root.title('哲学家问题')    root.geometry('1000x750')    start=Button(root,text='开始',font=('Arial',12),command=main,relief='raised')    start.place(x=100,y=0)    tip=Button(root,text='关于',font=('Arial',12),command=author,relief='raised')    tip.place(x=180,y=0)    hobby=BooleanVar()    isDeathLock=Checkbutton(root,text='允许死锁',font=('Arial',12),variable=hobby,relief='raised')    isDeathLock.place(x=260,y=0)    hobby2=BooleanVar()    death=Checkbutton(root,text='饥饿模式',font=('Arial',12),variable=hobby2,relief='raised')    death.place(x=400,y=0)    details=Button(root,text='说明',font=('Arial',12),command=detail_show,relief='raised')    details.place(x=550,y=0)    scroll = Scrollbar()    text=Text(root,width=35,height=50)    scroll.pack(side=RIGHT,fill=Y)    text.pack(side=RIGHT)    scroll.config(command=text.yview)    text.config(yscrollcommand=scroll.set)    img_init = Image.open('img/init.png').resize((150,150),Image.BILINEAR)    bm_init=ImageTk.PhotoImage(img_init)    labels=[]    for i in range(5):        temp=Label(root,image=bm_init)        labels.append(temp)    labels[0].place(x=400,y=100)    labels[1].place(x=520,y=350)    labels[2].place(x=250,y=570)    labels[3].place(x=50,y=350)    labels[4].place(x=150,y=100)    #加载餐桌图像    img_table = Image.open('img/table.png').resize((250,200),Image.BILINEAR)    bm_table = ImageTk.PhotoImage(img_table)    label_table=Label(root,image=bm_table)    label_table.image=bm_table    label_table.place(x=240,y=300)    #加载叉子类    img_fork = Image.open('img/fork.png').resize((70,130),Image.BILINEAR)    bm_fork = ImageTk.PhotoImage(img_fork)    label_forks=[]    for i in range(5):        temp=Label(root,image=bm_fork)        label_forks.append(temp)    label_forks[0].place(x=320,y=100)    label_forks[1].place(x=600,y=150)    label_forks[2].place(x=500,y=550)    label_forks[3].place(x=150,y=550)    label_forks[4].place(x=75,y=175)    print('加载完毕')    root.mainloop()

大功告成,代码自取,图片自己挑选设计,死锁的解决换种算法,我使用的是简单的”左右手都有叉子才进餐“的算法。关于使用pyinstaller对py文件打包可以参考我的另外一篇文章。喜欢就点个赞再走吧!

上一篇:新冠病毒疫情的数据爬取和简单分析
下一篇:Pyinstaller打包的exe文件过大的解决方法

发表评论

最新留言

关注你微信了!
[***.104.42.241]2025年04月10日 22时08分40秒