1

The scenario is that i want to:

  1. -Open a specific text file
  2. -Import text from text file to be shown in a text widget
  3. -Then the text from the text widget to then replace what was in the text file before, with what is currently in the text widget.

Currently i have worked out how to open the specific text file into the text widget and for it to be displayed however i can not figure out how to do the last step.

I have tried to define a 'Save' function however have not got anywhere, you can see this below.

Current code for step 1 and 2:

class PropertynewsA(Propertynews):

def __init__(self):
    Propertynews.__init__(self)

    def save():
        file.write(txt)
        file.close()
        messagebox.showinfo('Saved!','Your Message has been Saved')
        self.delete

    file = open('PropertynewsA.txt', 'r+') #Text file i am using
    with open('PropertynewsA.txt') as file: # Use file to refer to the file object
        data = file.read() #date=current text in text file

    #Text widget
    Time = strftime("%d %b %Y\n")#getting gmt time
    txt = Text(self.GenericGui,height=14, width=53,font=('TkDefaultFont',12)) #Creating text widget
    txt.insert('1.0',data) #showing text from text file in widget
    txt.tag_configure('format', background='lightblue', font='helvetica 14 bold', relief='raised')
    txt.focus()
    txt.place(x=8,y=40) #places text widget

If anyone can assist me here that would be great

Cheers guys

Ross
  • 19
  • 1
  • 9
  • Have you read the documentation for the text widget? Is the problem that you don't know how to get the text, or that you don' t know how to save the text to a file? What research have you done? – Bryan Oakley Feb 24 '16 at 17:18
  • @BryanOakley I have discovered how to open a text file within a text widget. I now want to be able to add further text in the text widget to what was opened and then for it all to be saved in the text file (replacing what was in there previously). I have attempted researching this which is how i found out about how to open the text file in the text widget in the first place:) – Ross Feb 24 '16 at 17:25

2 Answers2

1

Once you know how the Widget indices work and you know the insert and get methods on the Text widget:

starting_text = "THIS WOULD COME FROM A FILE"
...
textbox = TEXT_WIDGET_SETUP_ALREADY

textbox.insert("1.0",starting_text)
...

ending_text = textbox.get("1.0","end-1c")

The tricky part is accessing the text while the program is closing but not after the widget is destroyed (or you get a _tkinter.TclError: invalid command name ".4384096888" error):

import tkinter as tk

class Text(tk.Text):
    def destroy(self):
        global ending_text
        ending_text = self.get("1.0","end-1c")
        super(Text,self).destroy()

although if you use from tkinter import * notation you will need to call your class something other then Text as well as probably not using ending_text as a global variable, but that was the easiest way to show how to do it.


This is the full code I used for testing with IO, although if you don't understand how to work with files already there are references elsewhere.

import tkinter as tk


filename = "test.txt"

class Text(tk.Text):
    def destroy(self):
        global ending_text
        ending_text = self.get("1.0","end-1c")
        super(Text,self).destroy()
try:
    with open(filename) as f:
        text = f.read()
except IOError:
    text = ""

root = tk.Tk()

textbox = Text(root)
textbox.insert("1.0",text)
textbox.grid()

#this would probably just be put in the destroy method
def finish(event=None):
    with open(filename,"w") as f:
        f.write(ending_text)

textbox.bind("<Destroy>",finish) #this will happen after Text.destroy() so textbox.get() fails if used from this point
root.mainloop()
Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59
  • Big help, ill compare code and make the necessary changes, if i need to ask anything else i know who to ask, thanks man its appreciated and thank you for your time – Ross Feb 24 '16 at 23:59
  • 1
    The first index in a text widget is `"1.0"`, not `"0.0"`. Also, you should use `"end-1c"` rather than `"end"`. With `"end"` you will get an extra newline that was not part of the original data since tkinter always guarantees that the last character in the widget is a newline. – Bryan Oakley Feb 25 '16 at 04:00
  • @Bryan Oakley, I forgot tkinter starts lines at 1, haven't needed the reference I provided for a long time but I didn't know about `"end-1c"` and the newline, I will edit answer. – Tadhg McDonald-Jensen Feb 25 '16 at 14:14
0

I created a simple user interface that will allow you to open the text file of your choice from a file dialog. I prefer to set the options of this later apart for scalability reasons (in case you would love, in the future, to read document files instead, for instance):

        # Opening file options
        self.file_options={}
        self.file_options['defaultextension'] = '.txt'
        self.file_options['filetypes'] = [('text files', '.txt'), ('all files', '.*')]
        self.file_options['parent'] = self.parent
        self.file_options['title'] = 'Open a text file'
        self.file_options['initialdir']='/home/'

I am runing Linux, so in case you're on MS Windows OS, you may change self.file_options['initialdir']='/home/' to whatever directory path you want. Note that you can also remove it, in which case the file dialog window will prompt you to the directory where you are running the application, by default.

The method initialize_user_interface() does what its name reflects. Mainly, it offers a comfortable way to exit the application on a click and choose the file to read:

       self.filemenu.add_command(label="Open",command=self.text_replacement)
       self.filemenu.add_command(label="Exit",command=self.parent.quit)

You can then add a Text widget. Preferably, it is better to have a scrollable text zone in case you stumble on a large content file.

For this, you need to create the scrollbar, and attach it to the Text widget because the Text widget do not maintain its own scrollbars.

Here is the complete program:

'''
Created on Feb 25, 2016

@author: begueradj
'''
import Tkinter  # Tkinter -> tkinter in Python3
import Tkconstants
import tkFileDialog

class Begueradj(Tkinter.Frame):
    """ Get text file content and past it into a scrollable Text widget.
    Replace the content of the file with the pre-existing Text widget content.
    """

    def __init__(self,parent):
        """ Set some class variables:
         mainly the file dialog interface options.
        """
        Tkinter.Frame.__init__(self,parent)
        self.parent=parent

        # Opening file options
        self.file_options={}
        self.file_options['defaultextension'] = '.txt'
        self.file_options['filetypes'] = [('text files', '.txt'), ('all files', '.*')]
        self.file_options['parent'] = self.parent
        self.file_options['title'] = 'Open a text file'
        self.file_options['initialdir']='/home/'

        self.initialize_user_interface()

    def initialize_user_interface(self):
        """ Design of the user interface.
        It mainly consists of a bar menu and a horizontally & vertically 
        scrollable Text widget in case the text file to read is large.
        """

        self.parent.title("Text replacement")

        # Set the bar menu and its items
        self.menubar=Tkinter.Menu(self.parent)
        self.filemenu=Tkinter.Menu(self.menubar,tearoff=0)
        self.filemenu.add_command(label="Open",command=self.text_replacement)
        self.filemenu.add_command(label="Exit",command=self.parent.quit)
        self.menubar.add_cascade(label="File",menu=self.filemenu)
        self.parent.config(menu=self.menubar)        

        self.parent.grid_rowconfigure(0,weight=1)
        self.parent.grid_columnconfigure(0,weight=1)
        # Set the horizontal and vertical scrollbars              
        self.hscrollbar=Tkinter.Scrollbar(self.parent,orient=Tkconstants.HORIZONTAL)
        self.hscrollbar.grid(row=1,column=0,sticky=Tkinter.E+Tkinter.W)

        self.vscrollbar=Tkinter.Scrollbar(self.parent)
        self.vscrollbar.grid(row=0,column=1,sticky=Tkinter.N+Tkinter.S)

        # Set the Text widget and make it scrollable
        self.text=Tkinter.Text(self.parent,wrap=Tkinter.NONE,bd=0,
                               xscrollcommand=self.hscrollbar.set,
                               yscrollcommand=self.vscrollbar.set)
        self.text.grid(row=0,column=0,sticky=Tkinter.E+Tkinter.W+Tkinter.S+Tkinter.N)

        self.text.insert("1.0","Original text here")
        self.hscrollbar.config(command=self.text.xview)
        self.vscrollbar.config(command=self.text.yview)

    def text_replacement(self):
        """ Return the name of a file
        opened in read mode
        """
        self.filename = tkFileDialog.askopenfilename(**self.file_options) 
        if self.filename:
            self.original=self.text.get("0.0","end-1c")
            print self.original
            with open(self.filename) as self.filetoread:
                self.txtfilecontent=self.filetoread.read()
            self.filetoread.close()

            self.text.delete("1.0", Tkinter.END) # Erase the previous Text widget content
            self.text.insert("1.0", self.txtfilecontent)

            with open(self.filename,'w') as self.filetowrite:
                self.filetowrite.write(self.original)
            self.filetowrite.close()


def main():
    """ Main method to be executed.
    Instantiate Begueradj class
    """
    root=Tkinter.Tk()
    b=Begueradj(root)
    root.geometry("300x250+300+300")
    root.mainloop()

if __name__=="__main__":
    """ Run the application
    """ 
    main()

Application demo:

The demo consists of 3 screenshots showing:

  1. Original text set into the Text widget and a file dialog window to pick up the file to read.
  2. Loading the content of file1.txt into Tkinter.Text widget
  3. Check if the original file of the Text widget is saved (replaces) in file1.txt

    • Choosing the file to read
    • Text replacement
    • enter image description here
Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130