N is not defined (Global Present) - python-3.x

So I'm currently doing a project that is a random generator that reads on an excel file and select a data randomly but as I develop my code I get the following error:
line 19, in RandomG
L2 = Label(r2, text=edata).grid(row=3, column=1).grid(rowspawn=3, sticky=S)
NameError: name 'edata' is not defined
I have been told once to use "global" so the variables applies to all functions
but it still gives me the error.
Here is my code:
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
import xlrd
import random
import os
creds = 'Python file.txt' # This just sets the variable creds to 'tempfile.temp'
def RandomG():
global r2
r.destroy()
rootA.destroy()
r2 = Tk()
r2.title('Random Generator')
r2.geometry('350x300')
r2.resizable(False, False)
L1 = Label(r2, text='Welcome to My Random Generator!!').grid(row=1, column=1)
L2 = Label(r2, text= edata).grid(row=3, column=1).grid(rowspawn=3, sticky=S)
L2.config(width=200)
B1 = Button(r2, text="Browse", command=Directory)
B1.grid(rowspan=3, sticky=S)
B2 = Button(r2, text="Randomize", command=Generator)
B2.grid(rowspan=3, sticky=S)
r2.mainloop
def Directory():
global filename
filename = askopenfilename(filetypes=(("Excel Files", ".xlsx"),("All files","*.*")))
pathlabel = Label(r2)
pathlabel.config(text=(filename))
pathlabel.grid(columnspan=2)
pathlabel.pack()
def Generator():
global edata
global sheet
global workbook
with open(filename)as a:
filelocation = (filename)
workbook = xlrd.open_workbook(filelocation)
sheet = workbook.sheet_by_index(0)
for col in range(sheet.nrows):
edata = print[sheet.pop(sheet.random.cell.value(0, col))]

this is not how the global keyword works... global just tells your function to look up the variable in the global namespace (instead of the local namespace of your function).
this would work:
N = None
def f():
global N
print(N)
without defining N first (or setting it inside your function) it will not.
this would also work:
def f():
global N
N = 5
print(N)
(and it would spill N to your global namespace).
in any case: you have to set N (or edata in your case) before you try to read its value.

This means that edata doesn't have a value. It needs to be defined before calling it.

Related

How do I get the value from an option in tkinter after it has passed through a function?

I'm using tkinter to create an option menu for a user to interact with, when the selection has been made it will pass through a function to return an integer based on the input. I want to be able to return the integer back to a variable outside of the function so it can be received by another file. My problem is that python will keep returning the button as the command has not yet been processed.
from tkinter import *
Final = [] ##List containing options
master = Tk()
variable = StringVar(master)
variable.set(Final[0]) # default value
w = OptionMenu(master, variable, *Final)
w.pack()
def ok():
global choice
choice = variable.get()
global x
x = 0
for i in Final:
if str(i) == str(choice):
break
x += 1
button = Button(master, text="Choose", command=ok)
button.pack()
values = x

Unable to bind function after pickling - tkinter

I have simple code which creates two fields by the press of a button. There are two other buttons to save and load back the entry fields created. I have used the bind function to bind field A and field B. Pressing the Enter button on field A after entering a number will print out its value multiplied by 5 in field B. At this point the bind function works perfectly.
When I create three entry fields and save the progress without entering any inputs and compile the program, then load the file, the bind function does not seem to work. It seems to work only for the last field created. My code is as follows. I tried my best to simplify the code.
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfile
from tkinter import messagebox
import pickle
class Test(Frame):
def Widgets(self):
self.button_add = Button(self, text = "Add", command = self.add)
self.button_add.grid(row=0, column =2)
self.button_save = Button(self, text = "save", command = self.save)
self.button_save.grid(row=0, column =3)
self.button_load = Button(self, text = "load", command = self.load)
self.button_load.grid(row=0, column =4)
def add(self):
def test(event):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
self.field_A.append({})
n = len(self.field_A)-1
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
n = len(self.field_B)-1
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
def save(self):
for n in range(len(self.field_A)):
self.entry_A.append(self.field_A[n].get())
self.entry_B.append(self.field_B[n].get())
fname = asksaveasfile(mode = "w", defaultextension = ".est")
data = {"fields": len(self.field_A), "entries_A": (self.entry_A),"entries_B": (self.entry_B)}
with open(fname.name, "wb") as file:
pickle.dump(data, file)
def load(self):
def test(event):
print("Why is the value of n always equal to", n, "?")
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
fname = askopenfilename(filetypes = (("Estimation Files (est)", "*.est"),))
location = fname.replace("/", "\\")
if location:
with open(location, "rb") as file:
data = pickle.load(file)
for n in range(data["fields"]):
self.field_A.append({})
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].insert(0, data["entries_A"][n])
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
self.field_B[n].insert(0, data["entries_B"][n])
def __init__(self,master = None):
Frame.__init__(self, master)
self.field_A = []
self.field_B = []
self.entry_A = []
self.entry_B = []
self.grid()
self.Widgets()
root = Tk()
app = Test(master = None)
app.mainloop()
You need a "closure". You can make a closure in python with the functools.partial function.
from functools import partial
def test(n, event=None):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
#other code ...
self.field_A[n].bind("<Return>", partial(test, n))
Both of your test() functions are accessing a variable n from the enclosing function. In the case of add(), there is no loop; n has a single value. Each Entry's test() gets its own n, because they were bound by a distinct call to add(). In load(), however, you are looping over n values; each test() is referring to the same n, which will have its final value by the time that any binding can possibly be invoked. The other answer gives a reasonable way to give each instance of test() its own personal n, so I'm not going to repeat that here.

integrate tkinter whit Sqlite3

I'm looking for a suggestion: I have a Module called main.py where I write all GUI code.In order to avoid repeating all the sqlite queries, I have written all those queries un other Module called admin.py.
So there is this code in main.py:
B = tk.Entry()
B1= B.get()
In admin.py, I have the method validate.That is supposed take the B variable to make the query.Something like:
//Here the function will query the db to see if the value in B1.get() exist//
class myclass()
def validate(a):
....SELECT FROM table WHERE col_val = (a)
And here is the trouble: I don't know how to pass the value of B1 to the validate method. Could be something like this:
s= myclass()
s.validate(B1)
maybe?
I've done but i think could be better.Here is the way i did. Sorry for question i wasn't in the computer.
There is the module main.py
import tkinter as tk
import ingreso
from tkinter import messagebox
from ingreso import myclass
import sqlite3
def __init__(self):
tk.Tk.__init__(self)
frame = tk.Frame(self,width=380, height=420, bg="white", colormap="new")
self.fi = tk.Entry(frame)
self.fi.pack()
self.dni = tk.Entry(frame)
self.dni.pack()
frame.pack()
self.hi = tk.Button(self,text="guardar", command= self.validate)
self.hi.pack()
def validate(self):
messagebox.showwarning(title="validador",message="Se procedera a validar los campos")
fi= self.fi.get() #That is that i pass as class argument
dni= self.dni.get()
if len(fi)== 0 or len(dni)==0:
tk.messagebox.showwarning(message="campos requeridos")
else:
query = myclass(fi, dni) #Create the objet at instance of class
val = query.validar() #Determine if the object exist or not
There is the module ingreso.py:
class myclass():
def __init__(self, a= " ", b= " "): #There is the attributes of the class
self.db = db
self.a = a
self.b = b
def validar(self): # here i determine if the objet exist or not
fi = self.a
dni = self.b
conn = sqlite3.connect('ecina.db')
c = conn.cursor()
c.execute('''SELECT COUNT(*) FROM admision WHERE fi = (?) AND dni =(?)''', (fi, dni))
r = c.fetchone()
number_of_rows=r[0]
return number_of_rows
It's works but any suggestion or correction will be very appreciate.Thanks Alot.

how do you open two tkinter Windows one after the other.?

I am fairly new to python programming with its concept of class which is very different of languages like java, c++, c# ... and also the Tkinter library. I am trying to do something basic. First creating a frame that will allow the user to enter a string value; store that string value in memory then exit that frame. Creating a new file browser that will allow you to select a specific file then rename the chosen file with the string stored in memory earlier. I do not have any specific snippet of code to do that but I have two pieces of codes that could be combined to give me the result I want.
enter code here
# This is the snippet for the input user
def printtext():
global e
string = e.get()
return string
from Tkinter import *
root = Tk()
root.title('Name')
e = Entry(root)
e.pack()
e.focus_set()
b = Button(root,text='okay',command=printtext)
b.pack(side='bottom')
root.mainloop()
# This is for the file browser
import Tkinter,tkFileDialog
root = Tkinter.Tk()
file = tkFileDialog.askopenfile(parent=root,mode='rb',title='Choose a file')
Why don't you try with asksaveasfilename like in this example.But if you want to use file_path=askopenfilename with entry, than you would have to use OS library, with function os.rename (i think) .This code is written in python 3 so if you are using python2 than just change names of libraries.
from tkinter import *
import tkinter.filedialog as fd
def main():
root = Tk()
root.title('Name')
#e = Entry(root)
#e.pack()
#e.focus_set()
b = Button(root,text='okay',command= lambda:printtext(e))
b.pack(side='bottom')
root.mainloop()
def printtext(e):
#string = e.get()
#print(string)
file = fd.asksaveasfile(title='Choose a file')
#print(file)
main()

Making a basic user interface with tkinter-python

I've just been trying to practice some code by making a simple dice game
and using tkinter for the user interface of the starting menu for the game
For the starting menu, I'm trying to just see how it will come out if I used the code below,
BUT before making the Button widget and the Label Widgets, the commands come up first.
How would I fix this up?
thanks in advance
import tkinter as tk
from main import main
from written import showInstructions, showCredits
from generate_no import generate_no
class DiceGameUI(tk.Frame):
def __init__(self, master = None):
tk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def createWidgets(self):
self.titleLabel = tk.Label(self, fg = "red") #The Title of the Game
self.titleLabel["text"] = "Dice Game"
self.startButton = tk.Button(self) #Start Button
self.startButton["text"] = "Roll On!"
self.startButton["command"] = main() <<----- This plays out first before
self.startButton.grid() making any widgets
self.instrButton = tk.Button(self) #Instructions Button
self.instrButton["text"] = "Instructions"
self.instrButton["command"] = showInstructions()
self.instrButton.grid()
self.credits = tk.Button(self) #Credits Button
self.credits["text"] = "Credits"
self.credits["command"] = showCredits()
self.credits.grid()
root = tk.Tk() #Run code using tkinter
app = DiceGameUI(master = root)
app.mainloop()
'
You have to assign only name of function without () and arguments
self.startButton["command"] = main
If you use () than you run that function and result is assigned to command. It is good to create dynamicly function for command.
If you will need assign function which require arguments you have to use lambda function.
self.startButton["command"] = lambda:main()
self.startButton["command"] = lambda:main("abc", 123)
a = "abc"
b = 123
self.startButton["command"] = lambda arg1=a,arg2=b:main(arg1,arg2)
self.startButton["command"] = lambda title=a,count=b:main(title,count)
# this may not work - especially if a or b changes value (for example in loop)
self.startButton["command"] = lambda:main(a, b)
example how to use function name in own code
def plus(a, b):
return a + b
def minus(a, b):
return a - b
def result(a, b, func_name):
return func_name(a,b)
print result(10, 7, plus) # 17
print result(10, 7, minus) # 3

Resources