如何使用Python 3 tkinter在画布中显示列表框项目的文本?

时间:2014-12-22 23:04:30

标签: python-3.x canvas listbox tkinter

我正在尝试将列表框中所选项目的文本显示在画布中。当我将列表框绑定到辅助事件处理程序时,它会抛出属性错误:CLASS对象没有属性“HELPER EVENT HANDLER”。

我想要的如下:

1)双击左侧列表框中的项目时,其文本应显示在画布上。这段特殊的代码给我带来了所有麻烦。

lstbox.bind("<Double-Button-1>", self.OnDouble) 

你能帮我修一下这个错误吗?

2)我认为必须有一种方法可以使列表框中的线条高度大于我在应用程序中显示的高度。但是,我不知道该怎么做。我尝试提供了几个选项,但tkinter无法识别这些选项。你能告诉我怎么做吗?

以下是代码:

import tkinter as tk
languages = ['Mandarin', 'English', 'French']
class LanguageFamilies(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        canv = tk.Canvas(self, width=675, height=530, bg="white", relief="sunken")
        canv.config(scrollregion=(0,0,300,650), highlightthickness=0)
        canv.pack(side="right", expand=True, fill="both")

        # Create scroll bar
        sbar = tk.Scrollbar(self)
        canv.config(yscrollcommand=sbar.set)
        sbar.config(command=canv.yview)
        sbar.pack(side="right", fill="both")

        # Create Scroll List
        lstbox = tk.Listbox(self, width=240, height=530, relief="sunken", font="Courier")
        lst_scrollbar = tk.Scrollbar(self)
        lstbox.config(yscrollcommand=lst_scrollbar.set)
        lst_scrollbar.config(command=lstbox.yview)
        lstbox.pack(side="left", expand=True, fill="both")
        lst_scrollbar.pack(side="right", fill="both")
        lstbox.bind("<Double-Button-1>", self.OnDouble) # THIS IS THE LINE CAUSING THE ERROR

        # Add items to the lstbox
        i = 0
        while i < len(languages):
            lstbox.insert(i, languages[i])
            i += 1

        # Create a text inside canvas
        canv_id = canv.create_text(50, 50, font="Times 14", anchor="nw")
        msg = "This is a text inside canvas."
        canv.insert(canv_id, "end", msg)

        #Binding Handler
        def OnDouble(self, event):
            self.widget = event.widget
            selection = self.widget.curselection()
            content = self.widget.get(selection[0])
            print("You selected", content)



if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("930x530")
    root.title("Language Families")
    LanguageFamilies(root).pack(fill="both", expand=True)
    root.mainloop()

这是错误消息:

Traceback (most recent call last):
File "C:/Python33/new_stack_overflow.py", line 43, in <module>
LanguageFamilies(root).pack(fill="both", expand=True)
File "C:/Python33/new_stack_overflow.py", line 23, in __init__
lstbox.bind("<Double-Button-1>", self.OnDouble)
AttributeError: 'LanguageFamilies' object has no attribute 'OnDouble'

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

问题是OnDouble的def是在 __init__内定义的,这使得它不是类方法,而是__init__范围内的方法。您需要为OnDouble删除一级缩进。

答案 1 :(得分:-1)

这里是完整而正确的答案!以下是解决问题的阶段。

  1. Bryan建议将OnDouble事件处理程序的缩进减少一级是该解决方案的第一步。

  2. 我从这次经历中学到的关键是,直接在画布上打印列表框的文本不是正确的选择。相反,最好的选择是在画布上放置一个文本小部件,以便操作文本更加容易。看完好的视频教程here后,我得出了这个结论。因此,在画布的顶部定义了文本小部件。 if条件用于控制在文本画布上打印的内容以及应该打印多少次 - (在这种情况下,只有一个与电子词典完全相同 - 这是我的应用程序)。

  3. 这是完整的工作代码:

    import tkinter as tk
    languages = ['Mandarin', 'English', 'French']
    global counter
    counter = 1
    class LanguageFamilies(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            global canv, canv_id # IN ORDER TO MAKE THEM ACCESSIBLE TO OnDouble EVENT HANDLER
            canv = tk.Canvas(self, width=675, height=530, bg="white", relief="sunken")
            canv.config(scrollregion=(0,0,300,650), highlightthickness=0)
            canv.pack(side="right", expand=True, fill="both")
    
            # Create scroll bar
            sbar = tk.Scrollbar(self)
            canv.config(yscrollcommand=sbar.set)
            sbar.config(command=canv.yview)
            sbar.pack(side="right", fill="both")
    
            # Create Scroll List
            lstbox = tk.Listbox(self, width=240, height=530, relief="sunken", font="Courier")
            lst_scrollbar = tk.Scrollbar(self)
            lstbox.config(yscrollcommand=lst_scrollbar.set)
            lst_scrollbar.config(command=lstbox.yview)
            lstbox.pack(side="left", expand=True, fill="both")
            lst_scrollbar.pack(side="right", fill="both")
            lstbox.bind("<Double-Button-1>", self.OnDouble) 
    
            # Add items to the lstbox
            i = 0
            while i < len(languages):
                lstbox.insert(i, languages[i])
                i += 1
    
            # Create a text inside canvas
            global textmatter
            textmatter = tk.Text(canv) # THE TEXT SHOULD BE PRINTED ON THE CANVAS
            textmatter.insert("end", "Double-click on a language on the left to view information.")
            textmatter.pack()
    
    
    
        #Binding Handler, ONE INDENTATION LEVEL IS REMOVED AS PER BRYAN'S SUGGESTION
        def OnDouble(self, event):
            global counter
            self.widget = event.widget
            selection = self.widget.curselection()
            content = self.widget.get(selection[0])
            if counter == 1:
                textmatter.delete(1.0, "end") # CLEAR THE TEXT WHICH IS DISPLAYED AT FIRST RUNNING
                textmatter.insert("end", content)
                counter += 1 #ONE ITEM HAS BEEN SELECTED AND PRINTED SUCCESSFULLY
            elif counter > 1: 
                textmatter.delete(1.0, "end")
                textmatter.insert("end", content)
                counter = 1 # RESET THE COUNTER SO THAT NEXT SELECTED ITEM DISPLAYS PROPERLY
    
    
    
    
    
    if __name__ == "__main__":
        root = tk.Tk()
        root.geometry("930x530")
        root.title("Language Families")
        LanguageFamilies(root).pack(fill="both", expand=True)
        root.mainloop()
    

    就是这样。我希望这篇文章对你有帮助!

    SALAM,

    <强>穆罕默德