I am trying to build a text editor with different tabs, and each one is a file, but the problem is that when I try to save the file, it doesn't read nothing, it creates a new file with no content. Before I didn't have the Tab class and it worked, but the problem was that it saved all the files with the same content.
Here is the code:
from tkinter import *
from tkinter import filedialog, ttk
import os
class App():
def __init__(self):
title = 'New document'
self.root = Tk()
self.root.geometry('300x200')
self.root.iconbitmap('icon.ico')
self.root.title(title)
self.tabs = {'ky': 0}
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(expand = True, fill= 'both')
menubar = Menu(self.root)
# create a pulldown menu, and add it to the menu bar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New...", command=self.generate_tab)
filemenu.add_command(label="Open", command = self.open_file)
filemenu.add_command(label="Save", command= self.save_file)
filemenu.add_separator()
filemenu.add_command(label="Exit", command= self.root.quit)
menubar.add_cascade(label="File", menu = filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo")
editmenu.add_command(label="Redo")
editmenu.add_separator()
menubar.add_cascade(label="Edit", menu=editmenu)
self.root.config(menu=menubar)
def open_file(self):
file = open(filedialog.askopenfilename(), 'r+')
text_value = file.read()
self.textWidget.delete(1.0, "end-1c")
self.textWidget.insert("end-1c", text_value)
title = os.path.basename(file.name)
self.root.title(title)
file.close()
def add_tab(self, name):
tab = Tab(self.notebook, name)
print(name)
self.notebook.add(tab, text=name)
def save_file(self):
self.get_tab().save_tab()
def get_tab(self):
tab = Tab(self.notebook, 'Document ' + str(self.notebook.index('current')))
return tab
def generate_tab(self):
if self.tabs['ky'] < 20:
self.tabs['ky'] += 1
self.add_tab('Document ' + str(self.tabs['ky']))
def run(self):
self.root.mainloop()
class Tab(Frame):
def __init__(self, root, name):
Frame.__init__(self, root)
self.root = root
self.name = name
self.textWidget = Text(self)
self.textWidget.pack(expand=True, fill='both')
def save_tab(self):
print(self.textWidget.get("1.0", 'end-1c'))
file = open(filedialog.asksaveasfilename() + '.txt', 'w+')
file.write(self.textWidget.get("1.0", 'end-1c'))
print(os.path.basename(file.name))
#title = os.path.basename(file.name)
file.close()
if __name__ == '__main__':
app1 = App()
app1.run()
Problem lies with your get_tab method. It doesn't actually return the object that represents the currently open tab. It returns a new tab that has no content.
In order to fix your problem you need to keep a record of the tabs you've created. I've created a 'workable' version that adds the object of each tab to a list when they are created. This way if you are currently in "Document 3" and press save, it will get the Tab object that relates to document 3.
from tkinter import *
from tkinter import filedialog, ttk
import os
class App():
def __init__(self):
title = 'New document'
self.root = Tk()
self.root.geometry('300x200')
#self.root.iconbitmap('icon.ico')
self.root.title(title)
self.tabs = {'ky': 0}
#Keep a record of the open tabs in a list.
self.tab_list = []
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(expand = True, fill= 'both')
menubar = Menu(self.root)
# create a pulldown menu, and add it to the menu bar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New...", command=self.generate_tab)
filemenu.add_command(label="Open", command = self.open_file)
filemenu.add_command(label="Save", command= self.save_file)
filemenu.add_separator()
filemenu.add_command(label="Exit", command= self.root.quit)
menubar.add_cascade(label="File", menu = filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo")
editmenu.add_command(label="Redo")
editmenu.add_separator()
menubar.add_cascade(label="Edit", menu=editmenu)
self.root.config(menu=menubar)
def open_file(self):
file = open(filedialog.askopenfilename(), 'r+')
text_value = file.read()
self.textWidget.delete(1.0, "end-1c")
self.textWidget.insert("end-1c", text_value)
title = os.path.basename(file.name)
self.root.title(title)
file.close()
def add_tab(self, name):
tab = Tab(self.notebook, name)
print(name)
self.notebook.add(tab, text=name)
self.tab_list.append(tab)
def save_file(self):
tab_to_save = self.get_tab()
print(tab_to_save)
tab_to_save.save_tab()
def get_tab(self):
print(self.notebook.index('current'))
#Get the tab object from the tab_list based on the index of the currently selected tab
tab = self.tab_list[self.notebook.index('current')]
return tab
def generate_tab(self):
if self.tabs['ky'] < 20:
self.tabs['ky'] += 1
self.add_tab('Document ' + str(self.tabs['ky']))
def run(self):
self.root.mainloop()
class Tab(Frame):
def __init__(self, root, name):
Frame.__init__(self, root)
self.root = root
self.name = name
self.textWidget = Text(self)
self.textWidget.pack(expand=True, fill='both')
def save_tab(self):
print(self.textWidget.get("1.0", 'end-1c'))
file = open(filedialog.asksaveasfilename() + '.txt', 'w+')
file.write(self.textWidget.get("1.0", 'end-1c'))
print(os.path.basename(file.name))
#title = os.path.basename(file.name)
file.close()
if __name__ == '__main__':
app1 = App()
app1.run()
Related
I am trying to call multiple definitions and have each print their results to the ScrolledText.
If I define ScrolledText in the class MainPage, then the button OpenFile works fine , but the Menus commands do not with the 'scroll' is not defined error.
If I define ScrolledText in the class SampleApp, then the Menu OpenFile works fine , but the button commands do not with the 'scroll' is not defined error.
If I define both, then I get two scrolls that both work only in their own class.
How do I pass the scroll object between the 2 classes to use the same scroll in both class SampleApp and class MainPage?
#!/usr/bin/env python
# Python3.7.0
# Tkinter
import tkinter as tk # python 3
#from tkinter import ttk, font as tkfont, messagebox as mb, filedialog # python 3
from tkinter import ttk
import tkinter.scrolledtext as tkst
from tkinter.ttk import *
# Global scope
FilePath = "C:\Myfiles"
ScrollMsg = ""
# window definitions ----------------------------------
# Menu definitions ----------------------------------
def OpenFile(scroll): # Add a filedialog (file & directory chooser)
global FilePath, ScrollMsg
FilePath = "C:\Myfiles\file.txt"
print("filedialog path & file :\n", FilePath)
ScrollMsg = "filedialog path & file : " + FilePath
print ("SCROLL MESSAGE")
print ( ScrollMsg +"\n")
scroll.insert(tk.INSERT,ScrollMsg )
# ------------------------------------------------------
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.replace_frame(MainPage)
# scrolledtext
scroll = tkst.ScrolledText(self,width=90,height=15)
scroll.grid(column=0,row=15, columnspan = 6, sticky='W')
scroll.insert(tk.INSERT," OK here" +"\n")
# Menu for all frames ----------------------------------
menubar = tk.Menu(self)
# File
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label='Open', command=lambda: OpenFile(scroll))
menubar.add_cascade(label='File', menu=filemenu)
self.config(menu=menubar)
def replace_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.grid()
# FRAME CLASSES --------------------------------------
class MainPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
lbl1 = tk.Label(self, text="File selection: ")
lbl1.grid(column=0, row=1)
lbl2 = tk.Label(self, text="File Path")
lbl2.grid(column=0, row=2)
_FP_ = Entry(self,width=30)
_FP_.insert(0,FilePath) #set the item
_FP_.grid(column=1, row=2)
btn = Button(self, text='OpenFile', command=lambda: OpenFile(scroll))
btn.grid(column=0, row=4)
# scrolledtext
'''
scroll = tkst.ScrolledText(self,width=90,height=15)
scroll.grid(column=0,row=15, columnspan = 6, sticky='W')
scroll.insert(tk.INSERT," OK here" +"\n")
'''
_FP_.focus() # Place cursor into File Name Entry
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I'm not sure I understand exactly what you're trying to accomplish, but think I can answer your question about having a ScrolledText that will work with both of the classes — SampleApp and MainPage — at the same time.
To do this I've added another class named SingleScroll which is what is known as a "singleton" class, because it restricts the number of instances of it that can be created to just a "single" one.
It's used by both SampleApp and MainPage just like a regular class, and the object returned from calling it is passed to the OpenFile() function as an argument for the Menu or Button commands in the respective classes.
import tkinter as tk # python 3
#from tkinter import ttk, font as tkfont, messagebox as mb, filedialog # python 3
from tkinter import ttk
import tkinter.scrolledtext as tkst
from tkinter.ttk import *
# Global scope
FilePath = r"C:\Myfiles"
ScrollMsg = ""
# window definitions ----------------------------------
# Menu definitions ----------------------------------
def OpenFile(scroll): # Add a filedialog (file & directory chooser)
global FilePath, ScrollMsg
FilePath = r"C:\Myfiles\file.txt"
print("filedialog path & file :\n", FilePath)
ScrollMsg = "filedialog path & file : " + FilePath
print("SCROLL MESSAGE")
print(ScrollMsg + "\n")
scroll.insert(tk.INSERT, ScrollMsg + "\n" )
# SHARED SCROLL CLASS (ADDED) --------------------------
class SingleScroll:
""" Singleton ScrolledText object. """
def __new__(cls, master):
if '_inst' not in vars(cls): # Create instance?
scroll = tkst.ScrolledText(master, width=90, height=15)
scroll.grid(column=0, row=15, columnspan=6, sticky='W')
scroll.insert(tk.INSERT, " OK here\n")
cls._inst = scroll
return cls._inst
# ------------------------------------------------------
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.replace_frame(MainPage)
scroll = SingleScroll(self) # ScrolledText
# Menu for all frames ----------------------------------
menubar = tk.Menu(self)
# File
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label='Open', command=lambda: OpenFile(scroll))
menubar.add_cascade(label='File', menu=filemenu)
self.config(menu=menubar)
def replace_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.grid()
# FRAME CLASSES --------------------------------------
class MainPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
lbl1 = tk.Label(self, text="File selection: ")
lbl1.grid(column=0, row=1)
lbl2 = tk.Label(self, text="File Path")
lbl2.grid(column=0, row=2)
_FP_ = Entry(self,width=30)
_FP_.insert(0,FilePath) #set the item
_FP_.grid(column=1, row=2)
scroll = SingleScroll(master) # ScrolledText
btn = Button(self, text='OpenFile', command=lambda: OpenFile(scroll))
btn.grid(column=0, row=4)
_FP_.focus() # Place cursor into File Name Entry
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I have a function inside a method of a class like this:
from tkinter import Frame, Tk, BOTH, Text, Menu, END
from tkinter import filedialog as tkFileDialog
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
self.path = None
print(self.path)
def initUI(self):
self.parent.title("File dialog")
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open_image", command=self.onOpen1)
menubar.add_cascade(label="File", menu=fileMenu)
def onOpen1(self):
ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
path = dlg.show()
if path != '':
self.path = path
print(self.path)
return self.path
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
When I run the code, the self.path variable inside the function changes. But the self.path global variable outside the function does not change.
I would like self.path to be updated outside of the function. In fact, I want to update the self.path variable with the onOpen1 function. This function opens a window which allows you to select an image. Then, I want to recover the path of this image to update self.path.
The button is just a way to help visualize what is happening. Here is the full code.
from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button
from tkinter import filedialog as tkFileDialog
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
self.path = None
print(self.path)
def initUI(self):
self.parent.title("File dialog")
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open_image", command=self.onOpen1)
menubar.add_cascade(label="File", menu=fileMenu)
button = Button(self.parent, text='test', command=self.test)
button.pack()
def test(self):
print(self.path)
def onOpen1(self):
ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
path = dlg.show()
if path != '':
self.path = path
print(self.path)
return self.path
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
Run it and watch your console where the print will happen.
Hit the button. Notice how self.path is None.
Now select an image with your file dialog box.
Hit the button again. Notice how self.path changed to reflect what the path to the image is?
You stated that you want to update self.path to reflect what you selected. Your code does in fact do that. The point of this visualization is to show you that the question you asked may not be the solution to the problem you're having.
Here is an example of what I think you want.
from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button, Label
from tkinter import filedialog as tkFileDialog
import cv2
from PIL import ImageTk, Image
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
self.path = None
print(self.path)
def initUI(self):
self.parent.title("File dialog")
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open_image", command=self.onOpen1)
menubar.add_cascade(label="File", menu=fileMenu)
def test(self):
print(self.path)
def onOpen1(self):
ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
path = dlg.show()
if path != '':
self.path = path
self.add_image()
def add_image(self):
img = cv2.imread(self.path)
img = cv2.resize(img,(224, 224), interpolation = cv2.INTER_AREA)
image1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
image1 = Image.fromarray(image1)
image1 = ImageTk.PhotoImage(image1)
panelA = Label(self, image=image1)
panelA.image = image1
panelA.grid(row=0, column=0, sticky='w')
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
Here's some sample code for 2 frames.
from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button, Label
from tkinter import filedialog as tkFileDialog
import cv2
from PIL import ImageTk, Image
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
self.current_window = 0
self.path = None
self.panelA = None
self.panelB = None
print(self.path)
def initUI(self):
self.parent.title("File dialog")
#self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open Image 1", command=lambda: self.onOpen1(1))
fileMenu.add_command(label="Open Image 2", command=lambda: self.onOpen1(2))
menubar.add_cascade(label="File", menu=fileMenu)
self.button_1 = Button(self.parent, text='Window 1', command=lambda: self.switch_window(1))
self.button_2 = Button(self.parent, text='Window 2', command=lambda: self.switch_window(2))
self.back_button = Button(self.parent, text='Back', command=lambda: self.switch_window(0))
self.button_1.grid(sticky='w')
self.button_2.grid(sticky='w')
def switch_window(self, window):
self.current_window = window
if window == 0:
self.back_button.grid_forget()
self.button_1.grid(sticky='w')
self.button_2.grid(sticky='w')
else:
self.button_1.grid_forget()
self.button_2.grid_forget()
self.back_button.grid(row=1, sticky='w')
self.repopulate_windows()
def onOpen1(self, image_selection):
ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
path = dlg.show()
if path != '':
self.path = path
self.add_image(image_selection)
def add_image(self, image_selection):
img = cv2.imread(self.path)
img = cv2.resize(img,(224, 224), interpolation = cv2.INTER_AREA)
image1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
image1 = Image.fromarray(image1)
image1 = ImageTk.PhotoImage(image1)
if image_selection == 1:
self.panelA = Label(self.parent, image=image1)
self.panelA.image = image1
else:
self.panelB = Label(self.parent, image=image1)
self.panelB.image = image1
if self.current_window != 0:
self.repopulate_windows()
def repopulate_windows(self):
if self.current_window == 1:
if self.panelB is not None:
self.panelB.grid_forget()
if self.panelA is not None:
self.panelA.grid(row=0, column=0, sticky='w')
elif self.current_window == 2:
if self.panelA is not None:
self.panelA.grid_forget()
if self.panelB is not None:
self.panelB.grid(row=0, column=0, sticky='w')
else:
if self.panelA is not None:
self.panelA.grid_forget()
if self.panelB is not None:
self.panelB.grid_forget()
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
Can anyone help me to understand the window code? Im trying to make all the objects run in a Toplevel() function instead of a new instance of Tkinter because that doesn't work launching it from another program. Theres no window = Tk() function anywhere just init and frame.
from tkinter import *
from tkinter.simpledialog import askstring
from tkinter.filedialog import asksaveasfilename
from tkinter.messagebox import askokcancel
def text_edit() :
class Quitter(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command=self.quit)
widget.pack(expand=YES, fill=BOTH, side=LEFT)
def quit(self):
ans = askokcancel('Verify exit', "Really quit?")
if ans: Frame.quit(self)
class ScrolledText(Frame):
def __init__(self, parent=None, text='', file=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.makewidgets()
self.settext(text, file)
def makewidgets(self):
sbar = Scrollbar(self)
text = Text(self, relief=SUNKEN)
sbar.config(command=text.yview)
text.config(yscrollcommand=sbar.set)
sbar.pack(side=RIGHT, fill=Y)
text.pack(side=LEFT, expand=YES, fill=BOTH)
self.text = text
def settext(self, text='', file=None):
if file:
text = open(file, 'r').read()
self.text.delete('1.0', END)
self.text.insert('1.0', text)
self.text.mark_set(INSERT, '1.0')
self.text.focus()
def gettext(self):
return self.text.get('1.0', END+'-1c')
class SimpleEditor(ScrolledText):
def __init__(self, parent=None, file=None):
frm = Frame(parent)
frm.pack(fill=X)
Button(frm, text='Save', command=self.onSave).pack(side=LEFT)
Button(frm, text='Cut', command=self.onCut).pack(side=LEFT)
Button(frm, text='Paste', command=self.onPaste).pack(side=LEFT)
Button(frm, text='Find', command=self.onFind).pack(side=LEFT)
Quitter(frm).pack(side=LEFT)
ScrolledText.__init__(self, parent, file=file)
self.text.config(font=('courier', 9, 'normal'))
def onSave(self):
filename = asksaveasfilename()
if filename:
alltext = self.gettext()
open(filename, 'w').write(alltext)
def onCut(self):
text = self.text.get(SEL_FIRST, SEL_LAST)
self.text.delete(SEL_FIRST, SEL_LAST)
self.clipboard_clear()
self.clipboard_append(text)
def onPaste(self):
try:
text = self.selection_get(selection='CLIPBOARD')
self.text.insert(INSERT, text)
except TclError:
pass
def onFind(self):
target = askstring('SimpleEditor', 'Search String?')
if target:
where = self.text.search(target, INSERT, END)
if where:
print (where)
pastit = where + ('+%dc' % len(target))
#self.text.tag_remove(SEL, '1.0', END)
self.text.tag_add(SEL, where, pastit)
self.text.mark_set(INSERT, pastit)
self.text.see(INSERT)
self.text.focus()
if __name__ == '__main__':
try:
SimpleEditor(file=sys.argv[1]).mainloop()
except IndexError:
SimpleEditor().mainloop()
You have to adapt to Tkinter as it was written to be used (or write your own which is beyond me), instead of trying to pound it into some preconceived form.
try:
import Tkinter as tk ## Python 2.x
except ImportError:
import tkinter as tk ## Python 3.x
from functools import partial
class OpenToplevels():
""" open and close additional Toplevels with a button
"""
def __init__(self):
self.root = tk.Tk()
self.button_ctr=0
but=tk.Button(self.root, text="Open a Toplevel",
command=self.open_another)
but.grid(row=0, column=0)
tk.Button(self.root, text="Exit Tkinter", bg="red",
command=self.root.quit).grid(row=1, column=0, sticky="we")
self.root.mainloop()
def close_it(self, id):
id.destroy()
def open_another(self):
self.button_ctr += 1
id = tk.Toplevel(self.root)
id.title("Toplevel #%d" % (self.button_ctr))
tk.Button(id, text="Close Toplevel #%d" % (self.button_ctr),
command=partial(self.close_it, id),
bg="orange").grid(row=1, column=0)
Ot=OpenToplevels()
I'm using this code to make a text editor and I'm trying to add menus and shortcuts I will implant that later as of now I don't know how to do that(thats another question another day though if you know the answer please share it. but anyway I'm getting this error and i don't know why.
Error:
Traceback (most recent call last):
File "C:\Python27\Completed Projects\editor.py", line 90, in <module>
Editor().mainloop()
File "C:\Python27\Completed Projects\editor.py", line 52, in __init__
filemenu.add_command(text='Save', command=self.onSave).pack(side=LEFT)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2683, in add_command
self.add('command', cnf or kw)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2674, in add
self._options(cnf, kw))
TclError: unknown option "-text"
and the code:
from Tkinter import *
from tkSimpleDialog import *
from tkFileDialog import *
from tkMessageBox import *
root = Tk()
menubar = Menu(root)
class QuitMe(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command=self.quit)
widget.pack(expand=YES, fill=BOTH, side=LEFT)
def quit(self):
ans = askokcancel('Confirm exit', "Sure you want to Quit?")
if ans: Frame.quit(self)
class ScrolledText(Frame):
def __init__(self, parent=None, text='', file=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.makewidgets()
self.settext(text, file)
def makewidgets(self):
sbar = Scrollbar(self)
text = Text(self, relief=SUNKEN)
sbar.config(command=text.yview)
text.config(yscrollcommand=sbar.set)
sbar.pack(side=RIGHT, fill=Y)
text.pack(side=LEFT, expand=YES, fill=BOTH)
self.text = text
def settext(self, text='', file=None):
if file:
text = open(file, 'r').read()
self.text.delete('1.0', END)
self.text.insert('1.0', text)
self.text.mark_set(INSERT, '1.0')
self.text.focus()
def gettext(self):
return self.text.get('1.0', END+'-1c')
class Editor(ScrolledText):
def __init__(self, parent=None, file=None):
frm = Frame(parent)
frm.pack(fill=X)
filemenu = Menu(menubar, tearoff=0)
editmenu = Menu(menubar, tearoff=0)
filemenu.add_command(text='Save', command=self.onSave).pack(side=LEFT)
editmenu.add_command(text='Cut', command=self.onCut).pack(side=LEFT)
editmenu.add_command(text='Paste', command=self.onPaste).pack(side=LEFT)
editmenu.add_command(text='Find', command=self.onFind).pack(side=LEFT)
QuitMe(frm).pack(side=LEFT)
ScrolledText.__init__(self, parent, file=file)
self.text.config(font=('courier', 9, 'normal'))
def onSave(self):
filename = asksaveasfilename()
if filename:
alltext = self.gettext()
open(filename, 'w').write(alltext)
def onCut(self):
text = self.text.get(SEL_FIRST, SEL_LAST)
self.text.delete(SEL_FIRST, SEL_LAST)
self.clipboard_clear()
self.clipboard_append(text)
def onPaste(self):
try:
text = self.selection_get(selection='CLIPBOARD')
self.text.insert(INSERT, text)
except TclError:
pass
def onFind(self):
target = askstring('SimpleEditor', 'Search String?')
if target:
where = self.text.search(target, INSERT, END)
if where:
print where
pastit = where + ('+%dc' % len(target))
self.text.tag_add(SEL, where, pastit)
self.text.mark_set(INSERT, pastit)
self.text.see(INSERT)
self.text.focus()
if len(sys.argv) > 1:
Editor(file=sys.argv[1]).mainloop()
else:
Editor().mainloop()
Your problem can be fixed by simply changing text to label. For example:
filemenu.add_command(text='Save', command=self.onSave)
should be
filemenu.add_command(label='Save', command=self.onSave)
I would like to have a Dropdown Menu in Tkinter, that includes the shortcut key associated with this command. Is this possible?
How would I also add the underline under a certain character, to allow for Alt-F-S (File->Save)?
import tkinter as tk
import sys
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
menubar = tk.Menu(self)
fileMenu = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label="File", underline=0, menu=fileMenu)
fileMenu.add_command(label="Exit", underline=1,
command=quit, accelerator="Ctrl+Q")
self.config(menu=menubar)
self.bind_all("<Control-q>", self.quit)
def quit(self, event):
print("quitting...")
sys.exit(0)
if __name__ == "__main__":
app = App()
app.mainloop()
Maybe
from tkinter import *
import tkinter.filedialog as filed
root = Tk()
root.title("My Python Tkinter Application")
root.minsize(800,600)
def openfile():
fn = filed.askopenfilename(filetypes=[("Text Files","*.txt")], title="Open File")
f = open(fn, "r").read()
print(f)
def init():
menu = Menu(root)
filemenu = Menu(menu)
filemenu.add_command(label="Open (⌘O)", command=openfile)
menu.add_cascade(label="File", menu=filemenu)
root.config(menu=menu)
def key():
print("Key Pressed: "+repr(event.char))
root.bind("<Key>", key)
In this code press ctrl+e to exit the programmme
from tkinter import *
class MainApp:
def __init__(self, root):
self.root = root
self.menubar = Menu(self.root)
self.fileMenu = Menu(self.menubar, tearoff=False)
self.menubar.add_cascade(label="File", menu=self.fileMenu)
self.fileMenu.add_command(label="Exit", accelerator="Ctrl+E")
self.root.config(menu=self.menubar)
self.root.bind_all("<Control-e>", lambda event: self.root.quit())
self.root.mainloop()
if __name__ == "__main__":
MainApp(Tk())