使用Tkinter(Python)在框架上嵌入带图像和滚动条的按钮

时间:2015-01-03 08:48:12

标签: python python-2.7 tkinter

我正在尝试在Tkinter窗口中创建一个按钮单击事件。我有一个Tkinter窗口,上面有按钮。按下其中一个按钮,使用Toplevel打开一个新的Tkinter窗口。这个窗口有一个滚动条和一些其他按钮,上面有图像可以垂直向下滚动。我可以单独创建两个功能,即我可以在Tkinter窗口上嵌入一个带图像的按钮并使用滚动条,但无法使用之前的Tkinter窗口调用相同的功能。

我使用的代码是 -

from Tkinter import * 
from ttk import *

class VerticalScrolledFrame(Frame):
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0,
                        yscrollcommand=vscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior,
                                       anchor=NW)

        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


#if __name__ == "__main__":

class SampleApp(Tk):

    def __init__(self, *args, **kwargs):
        #from Tkinter import *
        print "in constructor"
        import Tkinter
        import ImageTk

        import Image
        import cv2
        import numpy as np
        import cv2.cv as cv
        import math
        import tkFileDialog
        import tkMessageBox
        import Tkinter as tk
        root = Tk.__init__(self, *args, **kwargs)

        def Print():
            print "print function"

        self.frame = VerticalScrolledFrame(root)
        self.frame.pack()
        self.label = Label(text="Shrink the window to activate the scrollbar.")
        self.label.pack()

        compare_button_path = "compare-button.jpg"
        image_compare = Image.open(compare_button_path)
        image_compare.thumbnail((70,45))
        photo_compare = ImageTk.PhotoImage(image_compare)
        button = tk.Button(self.frame, width=120, height=40, image=photo_compare,fg='black',bg='medium turquoise', activebackground='indian red',cursor="hand2",bd=6,relief=RAISED, compound=tk.LEFT, text="Compare",command = Print)
        button.image = photo_compare
        button.pack(side=LEFT)
        buttons = []
        for i in range(10):
            buttons.append(Button(self.frame.interior, text="Button " + str(i)))
            buttons[-1].pack()

app = SampleApp()
app.mainloop()

上面写的函数给出了相当不错的结果。

enter image description here

但是如何在另一个Tkinter窗口的按钮上调用此功能?将root的初始声明更改为root = Tk()而不是root = Tk。 init (self,* args,** kwargs)会抛出

RuntimeError: maximum recursion depth exceeded while calling a Python object. 

如果我尝试将该函数保存在其他文件中并将其导入我的原始Tk文件并在单击按钮时创建该类的对象,则在原始Tk文件的编译期间会自动调用第二个文件。 有人可以建议一个出路。

1 个答案:

答案 0 :(得分:0)

即使在要求澄清之后,我真的不明白你的问题。你最后在问题的评论中写道:“我只想打开一个带有按钮和图像的tkinter窗口,点击另一个Tkinter窗口的按钮”。

我不明白是什么阻止你这样做。我唯一看错你的代码就是你根本就没有创建Toplevel的实例(好吧,除了令人困惑的导入集)。除此之外,您的代码应该可以工作。

例如,如果您修改示例应用程序看起来像这样,您可以根据需要打开任意数量的窗口:

class SampleApp(Tk):

    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        b = Button(self, text="Open a new window", command=self.open_new)
        b.pack()

    def open_new(self):
        top = Toplevel()
        self.frame = VerticalScrolledFrame(top)
        self.frame.pack()

        def Print():
            print "print function"

        button = Button(self.frame, text="Compare",command = Print)
        button.pack(side=LEFT)
        buttons = []
        for i in range(10):
            buttons.append(Button(self.frame.interior, text="Button " + str(i)))
            buttons[-1].pack()