Trying to make the program run while waiting for input - python

This is the error: NameError: name 'data' is not defined
I need the 'data' variable to remain undefined while waiting for user input without the program crashing.
from tkinter import *
import datetime as Dt
root = Tk()
user_input = Entry(root)
user_input.pack()
def get_input():
global assign
data = user_input.get
Dt.time(data)
myButton = Button(root, text="Enter data",command=get_input)
myButton.pack()
root.mainloop()

Since your question is how to use data after it is defined, here is the easiest way how:
def get_input():
global assign
data = user_input.get() # also you need to call this
Dt.time(data)

Related

Collecting variables from a GUI

I have a simple GUI where the user selects a file, which becomes a variable for my main code. Here, my variable output should be the database path (gui_db_path) which the user inputs. When I run this code, called gui_test.py, the variable is printable, and prints to the console.
class GUI:
def __init__(self, window):
# 'StringVar()' is used to get the instance of input field
self.input_db_text = StringVar()
window.title("HyPep 1.0")
window.geometry("700x700")
ttk.Label(window, text='Database sequences .csv:').grid(row=1,column=0)
ttk.Button(window, text = "Browse", command = lambda: self.set_path_database_field()).grid(row = 1,column=2, ipadx=5, ipady=0)
ttk.Entry(window, textvariable = self.input_db_text, width = 70).grid( row = 1, column = 1, ipadx=1, ipady=1)
ttk.Button(window, text = "Analyze").grid(row = 10,column=1, ipadx=5, ipady=15)
def set_path_database_field(self):
self.path_db = askopenfilename()
self.input_db_text.set(self.path_db)
def get_database_path(self):
""" Function provides the database full file path."""
return self.path_db
if __name__ == '__main__':
window = tkinter.Tk()
gui = GUI(window)
window.mainloop()
print(gui.path_db, '\n', gui.path_qu)
gui_db_path = gui.path_db
print(gui_db_path)
My issue is that I need to retrieve this variable for use in another file, user_input.py, but is no longer callable. My code for user_input.py is:
from gui_test import gui_db_path
print(gui_db_path)
Instead of printing to the console in this instance, I get:
ImportError: cannot import name 'gui_db_path' from 'gui_test'
I'm sure there is a simple solution that I am missing, can anyone shed some light?
...
Update: much closer, need to expand the solution:
How would I go about expanding this to retrieve multiple paths? I have been trying this:
gui_test.py:
...
def get_db_path():
window = tkinter.Tk()
gui = GUI(window)
window.mainloop()
return gui.get_database_path()
def get_qu_path():
window = tkinter.Tk()
gui = GUI(window)
window.mainloop()
return gui.get_query_path()
user_input.py:
from gui_test import get_db_path
from gui_test import get_qu_path
gui_db_path = get_db_path()
gui_qu_path = get_qu_path()
Note that the code inside if __name__ == '__main__' block will not be executed when the file is imported. You need to put those code inside a function instead and returns the path at the end of the function:
gui_test.py
...
def get_db_path():
window = tkinter.Tk()
gui = GUI(window)
window.mainloop()
return gui.get_database_path()
Then import this function inside user_input.py:
from gui_test import get_db_path
gui_db_path = get_db_path()
print(gui_db_path)

Cant break loop using button

I wanted make window which will reappear if closed but will only close if user presses a button. I tried so many times but cant make. Plz help.
from Tkinter import *
x='y'
while x!='break':
def something(x):
x='break'
root=tkinter.Tk()
button=tkinter.Button(root, text='Break', command=lambda:something(x))
button.pack()
root.mainloop()
print('done')
When you set x using x = "break", you set the local variable which means that the global variable x is still "y". So to solve your problem just make sure that you use the global variable for x. This is a simple example:
import tkinter as tk
def something():
# Use the global variable for `loop_running`
global loop_running
loop_running = False
# You might also want to add: root.destroy()
loop_running = True
while loop_running:
root = tk.Tk()
button = tk.Button(root, text="Break", command=something)
button.pack()
root.mainloop()
print("Done")

Allow user to change default text in tkinter entry widget.

I'm writing a python script that requires the user to enter the name of a folder. For most cases, the default will suffice, but I want an entry box to appear that allows the user to over-ride the default. Here's what I have:
from Tkinter import *
import time
def main():
#some stuff
def getFolderName():
master = Tk()
folderName = Entry(master)
folderName.pack()
folderName.insert(END, 'dat' + time.strftime('%m%d%Y'))
folderName.focus_set()
createDirectoryName = folderName.get()
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
return
b = Button(master, text="OK and Close", width=10, command=callback)
b.pack()
mainloop()
return createDirectoryName
getFolderName()
#other stuff happens....
return
if __name__ == '__main__':
main()
I know next to nothing about tkInter and have 2 questions.
Is over-riding the default entry using global createDirectoryName within the callback function the best way to do this?
How can I make the button close the window when you press it.
I've tried
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
master.destroy
but that simply destroys the window upon running the script.
I don't know how experienced are you in Tkinter, but I suggest you use classes.
try:
from tkinter import * #3.x
except:
from Tkinter import * #2.x
class anynamehere(Tk): #you can make the class inherit from Tk directly,
def __init__(self): #__init__ is a special methoed that gets called anytime the class does
Tk.__init__(self) #it has to be called __init__
#further code here e.g.
self.frame = Frame()
self.frame.pack()
self.makeUI()
self.number = 0 # this will work in the class anywhere so you don't need global all the time
def makeUI(self):
#code to make the UI
self.number = 1 # no need for global
#answer to question No.2
Button(frame, command = self.destroy).pack()
anyname = anynamehere() #remember it alredy has Tk
anyname.mainloop()
Also why do you want to override the deafult Entry behavior ?
The solution would be to make another button and bind a command to it like this
self.enteredtext = StringVar()
self.entry = Entry(frame, textvariable = self.enteredtext)
self.entry.pack()
self.button = Button(frame, text = "Submit", command = self.getfolder, #someother options, check tkitner documentation for full list)
self.button.pack()
def getfolder(self): #make the UI in one method, command in other I suggest
text = self.enteredtext.get()
#text now has whats been entered to the entry, do what you need to with it

How do I create a button in Python Tkinter to increase integer variable by 1 and display that variable?

I am trying to create a Tkinter program that will store an int variable, and increase that int variable by 1 each time I click a button, and then display the variable so I can see that it starts out as 0, and then each time I click the button it goes up by 1. I am using python 3.4.
import sys
import math
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("My Button Increaser")
counter = 0
def nClick():
counter + 1
def main_click():
mLabel = Label(root, text = nClick).pack()
mButton1 = Button(text = "Increase", command = main_click, fg = "dark green", bg = "white").pack()
root.mainloop()
Ok so there are a few things wrong with your code so far. My answer basically changes what you have already into the easiest way for it to do what you want.
Firstly you import libraries that you don't need/use (you may need them in your whole code, but for this question include a minimal example only). Next you must deifne the counter variable as a global variable, so that it will be the same in the function (do this inside the function as well). Also you must change counter + 1 to counter += 1 so it increments the variable
Now the code will be able to count, but you have set variables as Buttons, but then made them None type objects, to change this .pack() the variable on the next line. You can get rid of the second function as you only need one, then you change the command of the button and its text to counter. Now to update the text in the button, you use .config(text = counter) which configures the button.
Here is the final solution (changes button value and has no label, but this is easily changed):
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("My Button Increaser")
global counter
counter = 0
def nClick():
global counter
counter += 1
mButton1.config(text = counter)
mButton1 = Button(text = counter, command = nClick, fg = "darkgreen", bg = "white")
mButton1.pack()
root.mainloop()
hope that helps!
You could use Tkinter variables. They are specially useful when you need to modify a data that other widgets might interact with. Here is a look alike code to the one in the question, but instead of defining counter as a normal variable, it is a variable from Tkinter.
import tkinter
import sys
root = tkinter.Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = tkinter.IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
tkinter.Label(root, textvariable=counter).pack()
tkinter.Button(root, text="Increase", command=onClick, fg="dark green", bg = "white").pack()
root.mainloop()
Instead of passing the value this variable holds to the text attribute of the Label, we assign the variable to textvariable attribute, so when the value of the variable gets updated, Label would update the displayed text accordingly.
When you want to change the value of the variable, you'd need to call the set() method of the variable object (see onClick) instead of assigning the value directly to it.

issue with python Tkinter drop down menu

The following code is a program to append buttons onto an existing program so selection can occur on a more friendly interface rather than inside the code. I am trying to use drop down menu's but the setEthAnt1 function seems to have an error: TypeError: setEthAnt1() takes no arguments (1 given). I do not know what arg i am failing to pass in. Does anyone have any ideas?
from Tkinter import *
import ThreegroupsGraphics as three
def run():
three.main()
def setEthAnt1():
name = var.get()
print name
three.OneTo2Ant = name
print three.OneTo2Ant
root = Tk()
var = StringVar()
var.set("Group 1 Ethnic Antagonism")
OptionMenu(root, var, "1","2","3","4","5","6","7","8","9","10", command = setEthAnt1).pack()
butn = Button(root, text = 'run', command = run)
butn.pack()
root.mainloop()
When you specify a command for an OptionMenu, the value of the selected item will be sent into the command, which essentially makes your var.get() unneeded. See below:
from Tkinter import *
import ThreegroupsGraphics as three
def run():
three.main()
def setEthAnt1(name):
print name
three.OneTo2Ant = name
print three.OneTo2Ant
root = Tk()
var = StringVar()
var.set("Group 1 Ethnic Antagonism")
OptionMenu(root, var, "1","2","3","4","5","6","7","8","9","10", command = setEthAnt1).pack()
butn = Button(root, text = 'run', command = run)
butn.pack()
root.mainloop()
If you don't want setEthAnt1 to have any parameters and still use var.get(), you can make the command for the OptionMenu a lamda function like so:
OptionMenu(root, var, "1","2","3","4","5","6","7","8","9","10", command = lambda _: setEthAnt1).pack()

Categories

Resources