如何解决如何使用tkinter自动执行按钮的动作?
我想实现的是,当我单击“自动分页”按钮时,PDF中的每一页都会显示1秒。现在,当我单击它时,它会在页面列表中循环,跳到最后一页,并且不显示任何其他页面。
在auto_read函数中,我放置了print(pagenumber)以查看其在页面中的循环时间。
from PIL import ImageTk,Image
from pdf2image import convert_from_path
import time
class SuReader:
def __init__(self,root):
self.root = root
self.next_but = Button(root,text='>>',command=lambda: self.next_page())
self.prev_but = Button(root,text='<<',command=self.prev_page)
self.automate_but = Button(root,text='Autopaging',command=self.auto_read)
self.next_but.grid(row=1,column=2)
self.prev_but.grid(row=1,column=0)
self.automate_but.grid(row=1,column=1)
self.display_pages()
def get_pages(self):
self.pages = convert_from_path('book.pdf',size=(700,600))
self.photos = []
for i in range(len(self.pages)):
self.photos.append(ImageTk.PhotoImage(self.pages[i]))
def display_pages(self):
self.get_pages()
self.page_number = 0
self.content = Label(self.root,image=self.photos[self.page_number])
self.content.grid(column=0,row=0,sticky='NSEW',columnspan=3)
print(len(self.photos))
def next_page(self):
# self.page_number += 1
self.content.destroy()
self.content = Label(self.root,columnspan=3)
self.page_number += 1
def prev_page(self):
self.page_number -= 1
print(self.page_number)
self.content.destroy()
self.content = Label(self.root,columnspan=3)
def auto_read(self):
for i in range(len(self.photos)):
time.sleep(1)
print(self.page_number)
self.next_page()
root = Tk()
root.title('Book Reader')
program = SuReader(root)
root.mainloop()
在这里,我只是将其传递给next_page函数,但是即使我定义正确,它也不起作用。
解决方法
time.sleep
正在阻止mainloop
,我相信您也遇到了垃圾回收问题。我重写了您的代码并解决了您的问题。我也解决了您将要遇到的其他问题。更改将在脚本中注释。
import tkinter as tk
from PIL import ImageTk,Image
from pdf2image import convert_from_path
class App(tk.Tk):
WIDTH = 700
HEIGHT = 640
TITLE = 'Book Reader'
def __init__(self,**kwargs):
tk.Tk.__init__(self,**kwargs)
#get_pages and display_pages are useless just do it all in the constructor
self.pages = convert_from_path('book.pdf',size=(700,600))
self.photos = {}
for i in range(len(self.pages)):
#the image might get garbage collected if you don't do it this way
self.photos[f'photo_{i}'] = ImageTk.PhotoImage(self.pages[i])
self.auto = tk.IntVar()
self.was_auto = False
self.page_number = 0
self.content = tk.Label(self,image=self.photos[f'photo_{self.page_number}'])
self.content.grid(column=0,row=0,sticky='nsew',columnspan=3)
tk.Button(self,text='<<',command=self.prev_page).grid(row=1,column=0,sticky='w')
tk.Checkbutton(self,text='auto-paging',variable=self.auto,command=self.auto_page).grid(row=1,column=1)
tk.Button(self,text='>>',command=self.next_page).grid(row=1,column=2,sticky='e')
self.grid_columnconfigure(0,weight=1)
self.grid_rowconfigure(0,weight=1)
self.grid_columnconfigure(2,weight=1)
def next_page(self):
#stop a lingering `after` call from affecting anything if we unchecked auto-paging
if self.auto.get() == 0 and self.was_auto:
self.was_auto = False
return
self.page_number += 1
#never be out of range
self.page_number = self.page_number % len(self.pages)
#you don't have to remake the Label every time,just reassign it's image property
self.content['image'] = self.photos[f'photo_{self.page_number}']
#time.sleep(1) replacement ~ non-blocking
if self.auto.get() == 1:
self.after(1000,self.next_page)
def prev_page(self):
self.page_number -= 1
#never be out of range
if self.page_number < 0:
self.page_number += len(self.pages)
self.content['image'] = self.photos[f'photo_{self.page_number}']
def auto_page(self):
if self.auto.get() == 1:
#allows us to catch a lingering `after` call if auto-paging is unchecked
self.was_auto = True
self.next_page()
if __name__ == '__main__':
app = App()
app.title(App.TITLE)
app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
app.resizable(width=False,height=False)
app.mainloop()