I am currently working on a simple Oregon Trail clone for a school project. I want to use Tkinter for this game, since the current version for pygame only goes up to Python 2 and I am used to using Python 3. I separated the different parts of the game into separate py files (main.py, names.py, occupations.py, store.py, game.py) and put them all into a folder so it is more organized. I already typed out the code for the welcome screen and the code for main.py, names.py, and a little for occupations.py. When I run my code, I am presented with an error that that the name 'names' is not defined. In the names file, I created a function called names() and a ran it in the main file. What is wrong with my code?
# main.py
from tkinter import *
from names import *
from occupations import *
from store import *
from game import *
root = Tk()
root.resizable(width=True, height=True)
root.wm_title('Oregon Trail')
root.geometry("200x75")
canvas = Canvas(root,width=400,height=200)
canvas.pack()
welcome = Label(canvas,
font = ('System',14,'bold'),
text = 'Oregon Trail')
welcome.grid(row=0,sticky=(N,S,E,W))
play = None
def playbuttoncommands():
canvas.pack_forget()
play.grid_forget()
welcome.grid_forget()
names()
play = Button(canvas,
font = 'System',
text = 'Travel the Trail',
command = playbuttoncommands)
play.grid(row=1,sticky=(N,S,E,W))
root.mainloop()
# names.py
from tkinter import *
from occupations import *
from store import *
from game import *
from main import *
def names():
canvas2 = Canvas(root,width=400,height=200)
canvas.pack()
root.geometry("400x200")
namelabel = Label(root,
font = 'System',
text = 'Please enter the names of your travel group:')
namelabel.grid(row=1,sticky=N)
name1 = ''
name1entry = Entry(root,textvariable=name1)
name1entry.grid(row=2,sticky=N)
name2 = ''
name2entry = Entry(root,textvariable=name2)
name2entry.grid(row=3, sticky=N)
name3 = ''
name3entry = Entry(root,textvariable=name3)
name3entry.grid(row=4,sticky=N)
name4 = ''
name4entry = Entry(root,textvariable=name4)
name4entry.grid(row=5,sticky=N)
name5 = ''
name5entry = Entry(root,textvariable=name5)
name5entry.grid(row=6,sticky=N)
enternames = Button(text = 'Continue', command = submitnames)
enternames.grid(row=7,sticky=N)
# occupations.py
from tkinter import *
from names import *
from store import *
from game import *
from main import *
def submitnames():
name1 = name1entry.get()
name2 = name2entry.get()
name3 = name3entry.get()
name4 = name4entry.get()
name5 = name5entry.get()
# Full Error Report
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1550, in __call__
return self.func(*args)
File ***************/main.py", line 33, in playbuttoncommands
names()
NameError: name 'names' is not defined
The problem is that you have a circular import, because main.py imports names.py, which then imports main.py. You should avoid these, as they cause problems like you are seeing. (The error report doesn't show all those layers, did you leave some out?)
Organize your code so that if moduleA imports moduleB, then moduleB doesn't need to import moduleA.
BTW: "from xyz import *" is discouraged, because it makes it hard to see where names were defined.
Related
I'm new to Python and I have the following code . When executed I get a GUI which allows me to check in /Out a checkbox . I have created an if statment to record the status of the clicking , however I don't understand how to bind the checkbox to a specific object within a dataframe (Pandas).The dataframe includes a list of objects that can user choose from ,so when the application save the data to csv file only the selected data will be saved . Right now I can't make it work . All the fields are saved to the csv file ,always .
Can you help me to understand what to do to make to be selectable ?
Thx .
from tkinter import *
from tkinter import Scale
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import ttkbootstrap
from termcolor import cprint ,colored
import pydicom
import pandas as pd
import os
print('Welcome to DTETool v1.1')
#Asking the user to choose input location
def filelocainput():
filelocationinput = filedialog.askopenfilename()
Data = pydicom.dcmread(filelocationinput , force = True )
print('PatientID -',Data.PatientID)
print('StudyID -',Data.StudyID)
print('StudyDescription-',Data.StudyDescription)
print('StudyDate -',Data.StudyDate)
print('PatientName -' ,Data.PatientName)
print('ScanOptions -' ,Data.ScanOptions)
print('TotalCollimationWidth -',Data.TotalCollimationWidth)
print('SeriesDescription',Data.SeriesDescription)
print('SeriesNumber -',Data.SeriesNumber)
print('PatientSex -' ,Data.PatientSex)
print('SliceThickness -' ,Data.SliceThickness)
print('ProtocolName -',Data.ProtocolName)
print('BodyPartExamined -' ,Data.BodyPartExamined)
print('Exposure -' ,Data.Exposure)
print('FilterType - ' ,Data.FilterType)
print('InstitutionAddress -',Data.InstitutionAddress)
print('KVP -' ,Data.KVP)
print('ManufacturerModelName -' ,Data.ManufacturerModelName)
DFdictionary = {}
if cPID.get()==1:
print('PatientID ON')
DFdictionary['PatientID'] = [Data.PatientID]
df = pd.DataFrame ({'PatientID ': [Data.PatientID], })
#Asking the user to choose output location
class filelocaoutput:
def SaveDatatoxlsx():
pass
filelocaloutput = filedialog.asksaveasfilename(defaultextension = 'xlsx')
df.to_excel (filelocaloutput)
root = Tk()
root.geometry("600x500")
Scallbtn = ttk.Button(root , text = 'Select All')
Scallbtn.place(y=450 , x=430)
Run_btn = ttk.Button(root, text='Run',command = filelocainput)
Run_btn.place(y=450, x=520)
# MainWindowbg = PhotoImage(file="BG.png")
# MainWindowbg_label = Label(root , image=MainWindowbg)
# MainWindowbg_label.place(y=0,x=0 , relwidth =1 , relheight=1)
cPID = IntVar()
CheckBoxPID = Checkbutton(root ,
text = 'PatientID',variable = cPID,
onvalue = 1 , offvalue = 0 , command=cPID,
)
CheckBoxPID.place(y=20 , x=20)
root.mainloop()
I am trying to build a Tkinter UI with a button where the user chooses a main file and based on information in that file, the script would get some information about some secondary files. Upon choosing the main file, I am trying to use the file path of the main file to get the file path of the secondary files. However, because I am calling a function "open_main_file()" twice, I get two dialog boxes where the user will have to choose the main file twice instead of once. How can I circumvent that?
My code looks like this:
import pandas as pd
from tkinter import *
from os.path import dirname
from tkinter import filedialog
root = Tk()
def open_main_file():
return filedialog.askopenfilename()
def parse_main_file():
return pd.read_parquet(open_main_file(), engine='pyarrow')
def get_some_ids():
return parse_main_file()['some_ids'].iloc[0]
def get_list_of_other_files():
other_files_path = dirname(dirname(dirname(open_main_file())))
list_of_other_files = []
for f in get_some_ids():
list_of_other_files.append(glob.glob(other_files_path + '/identifier=' + str(f) + '/*'))
return map(''.join, list_of_other_files)
myButton = Button(root, text='Open File...', command=get_list_of_other_files).pack()
root.mainloop()
try not to use a function in other functions. In this case, you are calling a function one time in another one, and one time in the main code. That is why you get file dialog 2 times. Use the returned item and give it to the next function. You can code like this:
import pandas as pd
from tkinter import *
from os.path import dirname
from tkinter import filedialog
root = Tk()
def open_main_file(): # This function is not necessary
return filedialog.askopenfilename()
def parse_main_file(main_file_path):
return pd.read_parquet(main_file_path, engine='pyarrow')
def get_some_ids(main_file_path):
return parse_main_file(main_file_path)['some_ids'].iloc[0]
def get_list_of_other_files():
main_file_path = filedialog.askopenfilename()
other_files_path = dirname(dirname(dirname(main_file_path)))
list_of_other_files = []
for f in get_some_ids(main_file_path):
list_of_other_files.append(glob.glob(other_files_path + '/identifier=' + str(f) + '/*'))
return map(''.join, list_of_constituent_files)
myButton = Button(root, text='Open File...', command=get_list_of_other_files).pack()
root.mainloop()
I'm currently working on a program that displays variables line by line as code executes from a file (think trace tables). I'm able to get it working fine when the code is encased within a function inside the program itself but when I import the same code, it tracks new variables that I don't want to track (as they don't appear in the actual script). Is there any way I can isolate the variables specific to the program? (it'll also be useful for when I'm ignoring variables from pulled libraries in Python).
Here's my program so far:
import sys
import dis
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
line_record = [] #where data on variables will be stored line by line
def trace(frame, event, arg_unused): #tracing function
global line_record
relevant_locals = {}
temp_vars = frame.f_locals.copy()
for k,v in temp_vars.items():
if not k.startswith("__"):
relevant_locals[k] = v
line_record.append([frame.f_lineno, relevant_locals])
return trace
def print_results(v_list):
print_record="" #variable which holds the formatting of the data
for item in v_list: #iterating for data in each recorded line
print_record += "Line " + str(item[0]) + "= "
if item[1]=={}: #catching lines with no variables
print_record += "no variables"
else:
for key in item[1]: #iterating through each variable to fetch associated data
print_record += str(key)+"="+str(item[1].get(key,"error"))+"|"
print_record += "\n"
return print_record
root = Tk() #creating the main window
root.title("frame")
root.iconbitmap("c:/Users/hamza/Documents/Other/Python/GUI/6 images/apple.ico")
root.filename = filedialog.askopenfilename(initialdir="/", title="select file",filetypes=[("python files","*.py")]) #import python files through tkinter dialog box
user_code = compile(open(root.filename, "rb").read(), root.filename, 'exec') #compiling imported code in order to use later in project
sys.settrace(trace)
exec(user_code)
sys.settrace(None)
print(print_results(line_record))
root.mainloop()
And for reference (if needed), my test code is:
a = 1
b = 2
a = a + b
If you need any more information please don't hesitate to ask, I'm happy to clarify, thanks.
Error Message
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Patrick\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "<string>", line 20, in set_training_data_directory
File "<string>", line 252, in printer
AttributeError: 'Navigate' object has no attribute 'Listbox1'
In this code, If I call the function set_training_data_directory, it should also call printer from the Toplevel1 which it does. However, as the method printer is expecting self as an argument, any instance from the Navigate class that I pass as an object says "object has no attribute 'Listbox1". I've passed self and self.main_g as an argument and so far the error I get is "object has no attribute 'Listbox1"
Module Name: All_Classes
import import_ipynb
import Navigator
import Listings
import Main_GUI
Module name: Main
from tkinter import *
import import_ipynb
import Main_GUI
root = Tk()
top = Main_GUI.Toplevel1(root)
root.mainloop()
Module name: Listings
import import_ipynb
from tkinter import filedialog
import sys
import tkinter as tk
import os
import All_Classes
class Lists:
#Making a Navigator Object
#List of the training data
def get_list_of_training_data(self):
training_data_names = []
directory = self.get_training_dir()
for classes in os.listdir(directory):
for data in os.listdir(os.path.join(directory,classes)):
print(data)
training_data_names.append(data)
return training_data_names
Module name: Navigator
import import_ipynb
from tkinter import filedialog
import tkinter as tk
import All_Classes
class Navigate:
def __init__(self):
#Global Navigation variables
#Training data directory
self.TRAINING_DIR = ''
#Model directory for loading
self.MODEL_DIR = ''
#Sound file path for loading
self.SOUND_FILE = ''
self.listings = All_Classes.Listings.Lists
#self.g = GUI.Toplevel1()
self.main_g = All_Classes.Main_GUI.Toplevel1
#Function for Data directory
def set_training_data_directory(self):
self.TRAINING_DIR = filedialog.askdirectory()
p = self.listings.get_list_of_training_data(self)
print(p)
self.main_g.printer(self)
def get_training_dir(self):
return self.TRAINING_DIR
Module Name: Main_GUI
import import_ipynb
import All_Classes
import sys
import tkinter as tk
import tkinter.ttk as ttk
py3 = True
class Toplevel1:
def __init__(self, top=None):
self.nav = All_Classes.Navigator.Navigate()
#'''This class configures and populates the toplevel window.
# top is the, toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
self.style = ttk.Style()
top.geometry("832x674+650+150")
self.style.configure('TNotebook.Tab', background=_bgcolor)
self.style.configure('TNotebook.Tab', foreground=_fgcolor)
self.style.map('TNotebook.Tab', background=
[('selected', _compcolor), ('active',_ana2color)])
self.TNotebook1 = ttk.Notebook(top)
self.TNotebook1.place(relx=0.012, rely=0.0, relheight=0.895
, relwidth=0.978)
self.TNotebook1.configure(width=814)
self.TNotebook1.configure(takefocus="")
self.TNotebook1_t0 = tk.Frame(self.TNotebook1)
self.TNotebook1.add(self.TNotebook1_t0, padding=3)
self.TNotebook2 = ttk.Notebook(self.TNotebook1_t0)
self.TNotebook2.place(relx=0.037, rely=0.113, relheight=0.461
, relwidth=0.412)
self.TNotebook2.configure(width=334)
self.TNotebook2.configure(takefocus="")
self.TNotebook2_t0 = tk.Frame(self.TNotebook2)
self.TNotebook2.add(self.TNotebook2_t0, padding=3)
self.TNotebook2.tab(0, text="Audio Files", compound="left", underline="-1"
,)
self.TNotebook2_t0.configure(background="#d9d9d9")
self.TNotebook2_t0.configure(highlightbackground="#d9d9d9")
self.TNotebook2_t0.configure(highlightcolor="black")
self.Button2 = tk.Button(self.TNotebook1_t0)
self.Button2.place(relx=0.123, rely=0.78, height=40, width=190)
self.Button2.configure(activebackground="#ececec")
self.Button2.configure(activeforeground="#000000")
self.Button2.configure(background="#d9d9d9")
self.Button2.configure(disabledforeground="#a3a3a3")
self.Button2.configure(foreground="#000000")
self.Button2.configure(highlightbackground="#d9d9d9")
self.Button2.configure(highlightcolor="black")
self.Button2.configure(pady="0")
self.Button2.configure(text='''Load Training Data''')
self.Button2.configure(command= self.nav.set_training_data_directory)
self.Listbox1 = tk.Listbox(self.TNotebook2_t0)
self.Listbox1.place(relx=0.0, rely=0.0, relheight=1.008, relwidth=1.012)
self.Listbox1.configure(background="white")
self.Listbox1.configure(disabledforeground="#a3a3a3")
self.Listbox1.configure(font="TkFixedFont")
self.Listbox1.configure(foreground="#000000")
self.Listbox1.configure(width=334)
#Init Scrollbar object
self.scroll1 = tk.Scrollbar(self.Listbox1)
self.scroll1.configure(command=self.Listbox1.yview)
self.Listbox1.configure(yscrollcommand = self.scroll1.set)
def printer(self):
print("printer Reached")
self.Listbox1.pack()
self.scroll1.pack(side = "right",fill = 'y')
for i in range(20):
self.Listbox1.insert(tk.END,i)
I am pretty new with object in python. If you happen to have an answer, I would appreciate it. Also could this be a bad way of designing?
Well. I had a look, and it definitely seems to be a issue with how you write and use classes. In Navigator you call the Lists class, but you don't instanciate it:
self.listings = All_Classes.Listings.Lists
To make an instance you must end the class name with parenthesis. Thus when you run the method get_list_of_training_data(self) there is no self to pass as self is the name of the instance.
Same thing with self.main_g = All_Classes.Main_GUI.Toplevel1.
From my perspective it looks like you build a complicated structure of classes when you really don't need them. To quote Jack Diederich: "The signature of this is not a class is that it has two methods, one of which is init". YouTube clip: Stop Writing Classes
On my end I'm having trouble to get it running without errors because my os.path.join() delivers dysfunctional paths, don't know why.
But: have look and see if you can make the code not so fractured and I think it will be easier to spot problems.
I've been trying to run this simple test just to get the feel of how to import methods from another script, but I have two problems:
the whole program runs instead of just importing and calling, the methods, when I need them too.
I'm getting this error:
Traceback (most recent call last):
File "C:\Users\devilboy 4\Documents\Visual Studio 2013\Projects\classvariablesOnANewScript\classvariablesOnANewScript\classvariablesOnANewScript.py", line 1, in <module>
from logInScreen import getUser, getPass
ImportError: cannot import name getUser
This is the script I'm importing to:
from logInScreen import getUser, getPass
class hello:
def show(self):
usr = getUser()
ps = getPass()
str(usr)
str(ps)
h = hello()
h.show()
This is what's on logInScreen.py :
from tkinter import *
import os
import tkinter.messagebox
#check si lo entrado es correcto
class checkValidation:
fail = 0
user = "hi user"
password = "nice pass"
#valida el user y el pass
def fullVali(self, name, passwd):
if name == "" or name == " ":
tkinter.messagebox.showinfo( "Error","Dejo el usuario en blanco")
self.fail+= 1
elif name != "UmetSeg":
tkinter.messagebox.showinfo( "Error","Usuario incorrecto")
self.fail+= 1
else :
self.user = name
tkinter.messagebox.showinfo( "ok","dude" + name)
if passwd == "" or passwd == " ":
tkinter.messagebox.showinfo( "Error","Dejo la password en blanco")
self.fail+= 1
elif passwd != "SegUmet":
tkinter.messagebox.showinfo( "Error","Password incorrecto")
self.fail+= 1
else:
self.password = passwd
tkinter.messagebox.showinfo( "ok","dude" + passwd)
form.destroy()
#open another py script
#os.system("mainPage3.py 1")
return
# no deja pasar parametros por command en el boton a menos que se por lambda, so corre #este metodo para
#correr el metodo de validar
def callVali(self):
user = usrIn.get()
self.fullVali(usrIn.get(), passIn.get())
return
def getUser(self):
return self.user
def getPass(self):
return self.password
vali = checkValidation()
form = Tk()
form.title("LogIn")
form.geometry("300x320+300+200")
#User txtBox
usrIn = Entry(form, textvariable = None, width = 30)
usrIn.place(x = 60, y = 140)
user = usrIn.get()
#Passwd txtBox
passIn = Entry(form, textvariable = None, width = 30)
passIn.place(x = 60, y = 200)
#Username Label
usrLblVal = StringVar()
usrLblVal.set("User name")
usrLbl = Label(form, textvariable = usrLblVal )
usrLbl.place(x = 120, y = 115)
#Passwrd label
passLblVal = StringVar()
passLblVal.set("Password")
passLbl = Label(form, textvariable = passLblVal )
passLbl.place(x = 120, y = 175)
#Login btn
btn = Button(form, text = "Entrar", width = 10, command = vali.callVali)
btn.place(x = 110, y = 250)
form.mainloop()
I hope I got the indentation right, kinda off a pain going through every line and spacing 4 times till it's right. I apologize for the Spanish, just ignore all the comments lol
You are attempting to import methods from within a class in your LogInScreen.py file. The methods getUser and getPass are bound methods that belong to the class checkValidation, You need to instead import the class and make the call on your class instead
from LogInScreen import checkValidation
validation = checkValidation()
validation.getUser()
validation.getPass()
As a simple illustration consider the following example involving two files:
file_to_import_from.py (Analogous to your logInScreen.py)
class MyClass:
def my_class_bound_method(self):
print "hello I a method belonging to MyClass"
def my_method_not_belonging_to_a_class():
print "Hello, I am a method that does not belong to a class"
file_to_import_to.py (Analogous to the script you are importing to)
from file_to_import_from import my_method_not_belonging_to_a_class
my_method_not_belonging_to_a_class()
from file_to_import_from import MyClass
x = MyClass()
x.my_class_bound_method()
from file_to_import_from import my_class_bound_method
my_class_bound_method()
And see Output
Hello, I am a method that does not belong to a class
hello I a method belonging to MyClass
Traceback (most recent call last):
File "C:\Users\Joe\Desktop\Python\import_test2.py", line 10, in <module>
from file_to_import_from import my_class_bound_method
ImportError: cannot import name my_class_bound_method
As you can see, the first two calls worked, but the second time the error you are facing arose, this is because the method my_class_bound_method exists as a method within the class MyClass.
EDIT:
In response to your comment, to avoid running the whole file, surround the code in your 'LogInScreen.py' in an if statement which checks if the file being evaluated by the interpreter is the main file being run.
from tkinter import *
import os
import tkinter.messagebox
#check si lo entrado es correcto
class checkValidation:
# CODE FROM YOUR CLASS OMITTED FOR BREVITY SAKE
# NOTHING BEYOUND THIS IF STATEMENT WILL RUN WHEN THE FILE IS IMPORTED
if __name__ == "__main__":
vali = checkValidation()
# MORE CODE OMITTED FOR BREVITY
form.mainloop()
The if statement I added here checks a special environment variable that python creates when it interprets a file, which is __name__, when the file is the file that you are directly running: python file_i_am_running.py the variable __name__ is set the the string "__main__" to indicate it is the main method, when it is not the file being run, and maybe one being imported as in your case, the variable is set to the module name, i.e. file_to_import.
Change to this:
from logInScreen import checkValidation
And then, use:
check = checkValidation()
usr = check.getUser()
ps = check.getPass()