如何使用tkinter GUI在python中依次显示图像

时间:2017-06-19 11:23:14

标签: python user-interface tkinter

我在代码中主要有两个问题:
1)它显示错误"没有这样的目录或文件存在"虽然我已经将图像的相同路径用于另一个程序(虽然我只指定了一个图像的常量路径)和图像文件,这个程序和另一个程序,都在同一个工作目录中 2)它不等待等待功能,它只执行到16然后打开GUI。我希望它能够逐个显示所有图像,并且只有在我按下“下一步”时才会更改。按钮
请提供代码中可能需要的任何更改,以满足上述要求 我在Windows 10系统中使用Python 3.5.2 提前致谢

import sys
import tkinter as tk
from PIL import Image,ImageTk,ImageFilter,ImageOps
from msvcrt import getch

def wait():
    getch()
    return

def classify_obj():
    print("In Development")
    return

src = "ímages/"

root = tk.Tk()
root.wm_title("Classify Image")

for i in range(1,17):
    frame1 = tk.Frame(root, width=500, height=400, bd=2)
    frame1.grid(row=1, column=0)
    cv1 = tk.Canvas(frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
    cv1.grid(row=1,column=0)
    im = Image.open(src+str(i)+".jpg")
    if (490-im.size[0])<(390-im.size[1]):
        width = 490
        height = width*im.size[1]/im.size[0]
    else:
        height = 390
        width = height*im.size[0]/im.size[1]
    im.thumbnail((width, height), Image.ANTIALIAS)
    photo = ImageTk.PhotoImage(im)
    cv1.create_image(0, 0, image=photo, anchor='nw')
    claButton = tk.Button(master=root, text='Classify', height=2, width=10, command=classify_obj)
    claButton.grid(row=0, column=1, padx=2, pady=2)
    frame2 = tk.Frame(root, width=500, height=400, bd=1)
    frame2.grid(row=1, column=1)
    cv2 = tk.Canvas(frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
    cv2.grid(row=1,column=1)
    broButton = tk.Button(master=root, text='Next', height=2, width=8, command=wait)
    broButton.grid(row=0, column=0, padx=2, pady=2)
    print(i)

tk.mainloop()

2 个答案:

答案 0 :(得分:1)

因此,在尝试使用下一个图像时遇到的大问题是for loop。发生的事情是你告诉python检查那个循环中的所有内容并执行这些功能。

我认为更好的方法是首先将此程序创建为class。这样我们就可以避免在程序中的任何地方调用全局变量。然后在__init__上的所述课程内,我们创建了一个包含图像文件夹内每张照片图像的列表。 (注意:我只用.jpg图片测试了这个。现在我们有了所有文件名的列表,然后我们可以使用该列表来计算我们正在使用的图像文件的数量。通过这个计数,我们可以创建一个计数器,让我们选择列表中的下一个索引,从而选择所述列表中的下一个图像。

通过将所有变量创建为类的属性,我们可以与这些属性进行交互,而无需将它们声明为全局。

采用以下示例。只需将src变量更改为您的文件路径即可。 如果您的文件夹位于主python工作区内,请记住在文件路径中使用.。示例:我在与TestImages相同的目录中有一个名为main.py的文件夹,因此我可以创建此变量:src = "./TestImages/"

看看下面的代码:

import tkinter as tk
from PIL import Image,ImageTk
import os


class ImageClassifyer(tk.Frame):


    def __init__(self, parent, *args, **kwargs):

        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.root = parent
        self.root.wm_title("Classify Image")   
        src = "./TestImages/"

        self.list_images = []
        for d in os.listdir(src):
            self.list_images.append(d)

        self.frame1 = tk.Frame(self.root, width=500, height=400, bd=2)
        self.frame1.grid(row=1, column=0)
        self.frame2 = tk.Frame(self.root, width=500, height=400, bd=1)
        self.frame2.grid(row=1, column=1)

        self.cv1 = tk.Canvas(self.frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
        self.cv1.grid(row=1,column=0)
        self.cv2 = tk.Canvas(self.frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
        self.cv2.grid(row=1,column=0)

        claButton = tk.Button(self.root, text='Classify', height=2, width=10, command=self.classify_obj)
        claButton.grid(row=0, column=1, padx=2, pady=2)
        broButton = tk.Button(self.root, text='Next', height=2, width=8, command = self.next_image)
        broButton.grid(row=0, column=0, padx=2, pady=2)

        self.counter = 0
        self.max_count = len(self.list_images)-1
        self.next_image()

    def classify_obj(self):
        print("In Development")

    def next_image(self):

        if self.counter > self.max_count:
            print("No more images")
        else:
            im = Image.open("{}{}".format("./TestImages/", self.list_images[self.counter]))
            if (490-im.size[0])<(390-im.size[1]):
                width = 490
                height = width*im.size[1]/im.size[0]
                self.next_step(height, width)
            else:
                height = 390
                width = height*im.size[0]/im.size[1]
                self.next_step(height, width)

    def next_step(self, height, width):
        self.im = Image.open("{}{}".format("./TestImages/", self.list_images[self.counter]))
        self.im.thumbnail((width, height), Image.ANTIALIAS)
        self.root.photo = ImageTk.PhotoImage(self.im)
        self.photo = ImageTk.PhotoImage(self.im)

        if self.counter == 0:
            self.cv1.create_image(0, 0, anchor = 'nw', image = self.photo)

        else:
            self.im.thumbnail((width, height), Image.ANTIALIAS)
            self.cv1.delete("all")
            self.cv1.create_image(0, 0, anchor = 'nw', image = self.photo)
        self.counter += 1


if __name__ == "__main__":
    root = tk.Tk() 
    MyApp = ImageClassifyer(root)
    tk.mainloop()

答案 1 :(得分:0)

当前代码存在很多问题。我尝试尽可能少地改变它。根本问题是绑定到wait()的按钮违​​反了具有GUI的原则。简而言之,这是一个从中开始的框架......

import tkinter as tk
from PIL import Image,ImageTk,ImageFilter,ImageOps
from msvcrt import getch

src = 'images/'
i = 1

def showImage():
    global i
    # You need to do file exists error checking here.
    try:
        im = Image.open(src+str(i)+".jpg")
    except:
        print("No image file named", src+str(i)+".jpg")
        return
    if (490-im.size[0])<(390-im.size[1]):
        width = 490
        height = width*im.size[1]/im.size[0]
    else:
        height = 390
        width = height*im.size[0]/im.size[1]
    im.thumbnail((width, height), Image.ANTIALIAS)
    photo = ImageTk.PhotoImage(im)
    label.configure(image=photo)
    label.image = photo
    i += 1
    return

def classify_obj():
    print("In Development")
    return

root = tk.Tk()
root.wm_title("Classify Image")

frame1 = tk.Frame(root, width=500, height=400, bd=2)
frame1.grid(row=1, column=0)
cv1 = tk.Canvas(frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
label = tk.Label(cv1)
cv1.create_window(0, 0, anchor='nw', window=label)
cv1.grid(row=1,column=0)
claButton = tk.Button(master=root, text='Classify', height=2, width=10, command=classify_obj)
claButton.grid(row=0, column=1, padx=2, pady=2)
frame2 = tk.Frame(root, width=500, height=400, bd=1)
frame2.grid(row=1, column=1)
cv2 = tk.Canvas(frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
cv2.grid(row=1,column=1)
broButton = tk.Button(master=root, text='Next', height=2, width=8, command=showImage)
broButton.grid(row=0, column=0, padx=2, pady=2)

showImage()
tk.mainloop()