Error when import a save file in Tkinter with Python - python

I have this problem in Tkinter. I wish to import a file (*.txt) with Open Button and save some values with Save Button. I wish to show a Error message when no file is open.
I am wrong becuse i get always this message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:/Users/samsung/PycharmProjects/test_FirstDensity/openANDread.py", line 30, in save
if not self.filename.name:
AttributeError: MainWindow instance has no attribute 'filename'
This is a very simplify example
from Tkinter import *
import tkMessageBox
import Tkinter, Tkconstants, tkFileDialog
class MainWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("input")
self.master.minsize(250, 150)
self.grid(sticky=E+W+N+S)
top=self.winfo_toplevel()
top.rowconfigure(0, weight=1)
top.columnconfigure(0, weight=1)
for i in range(2):self.rowconfigure(i, weight=1)
self.columnconfigure(1, weight=1)
self.button0 = Button(self, text="open", command=self.askopenfilename, activeforeground="red")
self.button0.grid(row=0, column=0, columnspan=2, pady=2, padx=2, sticky=E+W+N+S)
self.button1 = Button(self, text="save", command=self.save, activeforeground="red")
self.button1.grid(row=1, column=0, columnspan=2, pady=2, padx=2, sticky=E+W+N+S)
def askopenfilename(self):
self.filename = tkFileDialog.askopenfilename(filetypes=[("Text Files",'.txt')])
return self.filename.name
def save(self):
if not self.filename.name:
tkMessageBox.showerror("Error", message="None file to save")
return

It seems like you are calling the save() method before calling the askopenfilename() method. That's why, you get the AttributeError. Make sure the flow of your code reflects this change.
You might also want to include proper error handling in your askopenfilename() method itself to include situations where no file is opened.
You could do something on these lines. First initialize the self.filename = None in your constructor for the MainWindow class. Then you could modify your method as such:
def askopenfilename(self):
self.filename = tkFileDialog.askopenfilename(filetypes=[("Text Files",'.txt')])
if not self.filename: return None
return self.filename.name
However this is just to give you an idea, I have not myself worked with Tkinter much. All in all, it would depend on what exactly you are trying to achieve.

Related

Problem with open() function with tkinter in python

I'm doing a python course and I'm learning to use tkinter here, and as part of the course they send me to make a text editor (a notepad), and I'm defining the functions of the menubar, but in the open one at the time of opening a file (obviously txt) gives me this error, could someone please help me, anyway... Thanks in advance.
from tkinter import *
from tkinter import filedialog as FileDialog
from io import open
rute = ""
def new():
global rute
message.set("New File")
rute = ""
text.delete(1.0, "end")
root.tittle(rute + " - MEditor")
def open():
global rute
message.set("Open File")
rute = FileDialog.askopenfilename(
initialdir='.',
filetype=( ("Text Files", "*.txt"), ),
title="Open a text file" )
if rute != "":
file = open(rute,'r')
content = file.read()
text.delete(1.0,'end')
text.insert('insert', content)
file.close()
root.tittle(rute + " - MEditor")
def save():
message.set("Save File")
def save_as():
message.set("Save File As...")
root = Tk()
root.title("MEditor")
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New",command=new)
filemenu.add_command(label="Open",command=open)
filemenu.add_command(label="Save",command=save)
filemenu.add_command(label="Save As",command=save_as)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(menu=filemenu, label="File")
text = Text(root)
text.pack(fill='both', expand=1)
text.config(bd=0, padx=6, pady=4, font=("Consolas",12))
message = StringVar()
message.set("Welcome to MEditor!")
monitor = Label(root, textvar=message, justify='left')
monitor.pack(side='left')
root.config(menu=menubar)
root.mainloop()
throws me this error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\anaconda3\envs\spyder-cf\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\luisc\Desktop\CursoPython\Fase 4 - Temas avanzados\Tema 13 - Interfaces graficas con tkinter\editor.py", line 24, in open
file = open(rute,'r')
TypeError: open() takes 0 positional arguments but 2 were given
It should be said that I used anaconda for the jupyter notebook but to write scripts I am now using VSCode.
You named your own function open, shadowing the definition of the built-in open with a global scope definition (global scope names are always found before built-in names, you only find the latter if the former doesn't exist). Don't name-shadow built-ins, it only leads to pain.
Change:
def open():
to some other name and change all the places that call it to match.
A list of the built-ins can be found in the docs here:
https://docs.python.org/3/library/functions.html

Errror: _tkinter.TclError: bad window path name ".!button"

So today I tried to use python classes for the first time, to remove the excessive use of global keyword. I am trying to create a tkinter window in which, when we click one button it removes the clicked button and replaces it with a new button. And when we click it again, it removes this button and replaces the old (first) button and this should cycle through out...
This is my code which I made:
# ================= Importing Modules ===================
from tkinter import *
import tkinter as tk
# ====================================================
class Test():
# ============= Play Button Click =============
def fun1(self):
self.hi.destroy()
self.he.place(x=350,y=340)
# ============ Pause Button Click =============
def fun2(self):
self.he.destroy()
self.hi.place(x=350,y=340)
# ============ Player Window ================
def __init__(self):
self.root = Tk()
self.root.geometry('700x400')
self.root.resizable(0,0)
self.root["bg"] = "black"
self.hi = tk.Button(self.root, text="button 1", bg="white", bd=0, command=lambda: self.fun1() , relief=RIDGE)
self.hi.place(x=350,y=340)
self.he = tk.Button(self.root, text="button 2", bg="white", bd=0, command=lambda: self.fun2() , relief=RIDGE)
self.root.mainloop()
# ============== Calling ===========
if __name__ == '__main__':
Test()
But Instead of the desired output, sadly, I got this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:/XXX/XXX/Desktop/test.py", line 29, in <lambda>
self.he = tk.Button(self.root, text="button 2", bg="white", bd=0, command=lambda: self.fun2() , relief=RIDGE)
File "C:/XXX/XXX/Desktop/test.py", line 16, in fun2
self.hi.place(x=350,y=340)
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 2477, in place_configure
self.tk.call(
_tkinter.TclError: bad window path name ".!button"
SO MY QUESTION IS:
doubt1 = Any idea what I am doing wrong?
doubt2 = Or isn't this possible?
if doubt1 or doubt2:
Please explain it...
elif:
Please tell me a better alternative or idea, how to do this efficiently.
else:
Note: I have researched so many questions. Nothing helped me out. Especially ---|
↓
ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤthis one.
You're destroying self.hi and then later trying to call place on the destroyed button. Once a widget has been destroyed you can no longer use it.
If you want to keep cycling the buttons, don't destroy them. Since you are using place, you can use self.hi.place_forget() and self.he.place_forget() to remove the buttons from view without destroying them.

Tkinter - Linking buttons to different scripts

I am exploring GUI's at the moment. What I want is to have a GUI with a 2 buttons and I want each of the buttons to run a separate python script when clicked.
I have outlined my code below (the first button runs just fine but I am having issues with the second button.
Error Message when I choose the second button:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
Code:
from tkinter import *
import tkinter as tk
master = Tk()
def First_Scriptcallback():
exec(open(r'Desktop\Automation\First_Script.py').read())
def second_Scriptcallback():
exec(open(r'Desktop\Automation\Second_Script.py').read())
#master.title("Test GUI")
#canvas = tk.Canvas(master, height=300, width = 400)
#canvas.pack()
firstButton = Button(master, text="Run first script", command=First_Scriptcallback)
firstButton.pack()
secondButton = Button(master, text="Run second script", command=second_Scriptcallback)
secondButton.pack()
mainloop()
Thanks
As #matiiss suggested importing the other scripts into your program can help and it can be done like this,
import First_Script as first
import Second_Script as second
from tkinter import *
import tkinter as tk
master = Tk()
def First_Scriptcallback():
first.function_name()#here you must create functions in first_script to call in this main script
def second_Scriptcallback():
second.function_name()
#master.title("Test GUI")
#canvas = tk.Canvas(master, height=300, width = 400)
#canvas.pack()
firstButton = Button(master, text="Run first script", command=First_Scriptcallback)
#command=first.function_name
#we can also directly call an function using above command,but sometimes there are problems related to this approch
firstButton.pack()
secondButton = Button(master, text="Run second script", command=second_Scriptcallback)
#command=second.function_name
secondButton.pack()
mainloop()
here for this example the scripts and the program must be in same directory.

How to put tkinter Message widget on tkinter Canvas

I was trying to make a window with tkinter. On the home screen, I would have a label, a few buttons, and then a Message, all on the tkinter.Canvas. I created them in different functions, but even then, the label and buttons went on the canvas. The Message didn't, returning an error:
File "C:\Users\bobby\AppData\Local\Programs\Python\Python35-32\NFL Model\nflScreen.py", line 54, in homeScreen
self.homeText = tk.Message(master=self.canvas, text=self.getText(0), width=550)
File "C:\Users\bobby\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 2816, in __init__
Widget.__init__(self, master, 'message', cnf, kw)
File "C:\Users\bobby\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 2139, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: bad window path name ".59508144.59508176"
Here is my code to make the window:
import tkinter as tk
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.makeScroll(); self.showMenu(); self.homeScreen();
def makeScroll(self):
self.canvas = tk.Canvas(self, bg='#F0F0F0', width=1000, height=600)
self.canvas.grid(row=0, column=0) ###Makes the Canvas. This part works well
def showMenu(self):
self.home = tk.Button(self.canvas, text="Home", command=self.homeScreen, width=10)
self.home.grid(column=0, row=1) ###Make some buttons, this part works well.
self.rank = tk.Button(self.canvas, text="Rankings", command=self.rankingScreen, width=10)
self.rank.grid(column=1, row=1)
###I tried adding a Message here to the canvas, and it worked, but I need the message to be made in another function
def homeScreen(self):
###This part doesn't work. I know that self.canvas is still a variable.
self.homeText = tk.Message(master=self.canvas, text=self.getText(0), width=550)
self.homeText.grid(column=0, row=3, columnspan=7)
Basically, I create the tkinter.Canvas in makeScroll(). When I add widgets to it in showMenu(), that works. But when I try to add widgets in homeScreen(), it doesn't. Does anyone know why, and how to fix it?
I found out after a while that this was just a logic error. In my real code, I called a function that would delete the canvas object at the start of the homeScreen() function.

Tkinter Module Error erroe creating login page in calss pageone

I have try to write program for library Management system I am using tkinter module for it. I have writen the below code but when I am trying to create multiple Text box i am getting below error.
File "Hope_work.py", line 22, in __init__
frame = F(container, self)
File "Hope_work.py", line 62, in __init__
pwd_lable.pack()
UnboundLocalError: local variable 'pwd_lable' referenced before assignment
Below is the complete program I am getting error in PageOne class
import tkinter as tk
import os
LARGE_FONT= ("Verdana", 12)
class Myprogramapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Library Managment System", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = tk.Button(self, text="Admin Login",
command=lambda: controller.show_frame(PageOne))
button.pack()
button1 = tk.Button(self, text="Lib Login")
button1.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
name_label = tk.Label(self, text="User ID : ")
pwd_label = tk.Label(self.name_lable, text="Password:")
name_label.pack(pady=10,padx=10)
pwd_lable.pack(pady=10,padx=10)
name_lable = tk.Entry(self)
pwd_lable = tk.Entry(self, show="*")
name_lable.pack()
pwd_lable.pack()
button1 = tk.Button(self, text="Login")
button1.pack()
if __name__ == "__main__":
app = Myprogramapp()
app.mainloop()
**
It would appear that you are trying to bite off more than you can chew so to speak with this example of code. You are miss using parts of tkinter that should be understood before moving onto something more complicated like this.
Before you try to use multiple classes like this try to focus more on understanding how tkinter works and how to implement all its widgets properly in a single class or even outside of a class first.
You do not assign widgets to another widget like you are attempting to do here:
pwd_label = tk.Label(self.name_lable, text="Password:")
This is the problem refereed to in your trackback. You need to assign the Label widget to either a root window, a frame or a toplevel.
Your indention is not clean and if the way you have it pasted in your question is accurate then you code will not work as the def show_frame() method is not inside the Myprogramapp class.
You are importing os for no reason here and it is not good practice to import libraries you are not currently using.
You should make some important parts of your program into a class attribute, like your entry fields. If you are going to put in a password to that field and try and get() the string from the entry field inside a method you wont be able to as its not a class attribute. You can fix this by adding self. prefix to the widget name.
All and all after making those changes you will get a tkinter window with 2 buttons. The Admin Login button will display a login screen. That being said I think you should either step away from classes all together while learning tkinter or work in a single class for now until you have a solid understanding of how classes, methods, and attributes work and are used.

Categories

Resources