简体   繁体   English

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

[英]Embedd Buttons with images and scrollbar on a frame using Tkinter (Python)

I am trying to make a on-button click event in a Tkinter window. 我正在尝试在Tkinter窗口中进行按钮单击事件。 I have a Tkinter Window on which there are buttons. 我有一个Tkinter窗口,上面有按钮。 Pressing one of those buttons,opens up a new Tkinter Window using Toplevel. 按下其中一个按钮,使用Toplevel打开一个新的Tkinter窗口。 This window would have a Scrollbar and some other buttons with images on it which can be vertically scrolled down. 该窗口将具有滚动条和一些其他带有图像的按钮,这些按钮可以垂直向下滚动。 I could create the two functionalities separately,ie, I could embedd a button with an image on a Tkinter window and use the Scrollbar but was unable to call the same function with the previous Tkinter window. 我可以分别创建两个功能,即可以在Tkinter窗口中嵌入带有图像的按钮,并使用滚动条,但无法在以前的Tkinter窗口中调用相同的功能。

The code I am using is - 我正在使用的代码是-

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()

The above written function gives a pretty good result. 上面编写的函数给出了很好的结果。

在此处输入图片说明

But how do I call this function on a button click from another Tkinter window? 但是,如何在另一个Tkinter窗口中单击按钮时调用此函数? Changing the initial declaration of root to root = Tk() instead of root = Tk. 将root的初始声明更改为root = Tk()而不是root = Tk。 init (self, *args, **kwargs) throws a init (自身,* args,** kwargs)抛出一个

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

If I try to keep the function in some other file and import it into my original Tk file and create the object of that class on a button click, the second file gets automatically called during complilation of the original Tk file. 如果我尝试将函数保留在其他文件中,然后将其导入到我的原始Tk文件中,然后单击按钮创建该类的对象,则在原始Tk文件的编译过程中会自动调用第二个文件。 Can somebody please suggest a way out. 有人可以建议出路吗?

I really don't understand your question, even after asking for clarification. 即使要求澄清,我真的不明白您的问题。 You finally wrote in the comments of the question "I simply want to open a tkinter window with buttons and images, on a button click from another Tkinter window". 您最终在问题的注释中写道:“我只是想通过单击另一个Tkinter窗口中的按钮来打开包含按钮和图像的tkinter窗口”。

I don't see what's preventing you from doing that. 我看不出是什么阻止您这样做。 The only thing I see wrong with your code is that you're simply not creating an instance of Toplevel (well, except for a confusing set of imports). 我对代码的唯一错误是,您只是不创建Toplevel实例(嗯,除了令人困惑的导入集之外)。 Other than that, your code should work. 除此之外,您的代码应该可以工作。

For example, if you modify your sample app to look something like this, you can open as many windows as you want: 例如,如果您将示例应用程序修改为如下所示,则可以根据需要打开任意多个窗口:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM