eager2learn
eager2learn

Reputation: 1488

tkinter binding doesn't do anything and attribute error

I'm new to Tkinter and I'm trying to add event handling to a GUI. I have a list that contains sentences and words( the list contains a sublist consisting of the sent as a string as its first element and a list of its words as its second element), and I first want to display the sentences using a Label widget. What I'd like to do is switch between the sentences using the Up and Down keys.

My first problem, however is a different one. I want to store the sentence that is currently displayed in a variable called current_sent, so I try to assign 0 to self.current_sent in the constructor of the app. However, when I try to reference this variable in my code, I get an attribute error. When I initialize self.current_sent in the initialize() method of my app, I don't get the error. Can anybody tell me why this is?

Now if I set self.current_sent = 0 in the initialize method, the gui starts, but I don't get any changes when pushing the Down button. I also tried this using only '' as an event, but that also doesn't cause the second sentence to be displayed. If I try to call print statements from the next_sent method, nothing is displayed, so I never enter the event handling function. Can anybody tell me, what I'm doing wrong, please?

import nltk
import Tkinter as tk
import os

class Annotator(tk.Tk):
    def __init__(self, parent):
        tk.Tk.__init__(self, parent)
        self.sents = self.get_sents()
        self.initialize()
        self.current_sent = 0
        self.current_word = 0

    def sent_tokenize(self, textfile):
        f = open(textfile)
        s = f.readlines()
        text = " ".join(s)
        sents = nltk.sent_tokenize(text)
        tags = [[x,nltk.word_tokenize(x)] for x in sents]
        return tags

    def get_sents(self):
        article_files = self.get_articles()
        list_of_sents = [self.sent_tokenize(x) for x in article_files]
        sents = [sent for sublist in list_of_sents for sent in sublist]
        return sents

    def get_articles(self):
        directory = "/Users/------------/Documents/reuters/reuters/articles"
        list_of_articles = []
        for f in os.listdir(directory):
            if not f.startswith('.'):
                filename = directory + "/" + f
                list_of_articles.append(filename)
        return list_of_articles

    def next_sent(self,event):
        if (self.current_sent < len(self.sents) - 1):
            self.current_sent += 1
            self.label.config(text = self.sents[self.current_sent][0])

    def initialize(self):
        self.label = tk.Label(text = self.sents[self.current_sent][0])
        self.label.bind('<KeyPress-Down>', self.next_sent)
        self.label.grid(row = 0, column = 0, columnspan = 2)



if __name__ == "__main__":
        app = Annotator(None)
        app.mainloop()

Upvotes: 1

Views: 415

Answers (1)

Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21453

The AttributeError is coming up because __init__ calls initialize before defining self.current_sent so you just need to rearrange the __init__ a little bit:

def __init__(self, parent):
    tk.Tk.__init__(self, parent)
    self.current_sent = 0
    self.current_word = 0
    self.sents = self.get_sents()
    self.initialize()

As for the Binding issue, only the widget with keyboard focus will respond to events, either try clicking on the label before testing the events or set it up to respond regardless of what has focus like this:

self.bind_all('<KeyPress-Down>', self.next_sent)

Upvotes: 2

Related Questions