How to accept user input using Tkinter? - python

I am currently trying to turn a Python script I use regularly into an application by using Platypus. However, my script prompts the user for input several times and uses that input to construct a URL that is being used to make API requests. Here is an example of how this is used in my script:
member_id = raw_input("What member id will you be using? ")
The data taken from the user (and stored as a variable) is then used like this:
url_member = "https://api.example.com/member?member_id="+str(member_id)
Since the application created using Platypus won't allow for user input (based on the way I am requesting it through my script) I was going to try and use Tkinter as well. However, I have read through the documentation and am confused when it comes to the syntax (I am still new to Python in general).
Can anyone help, or show an example of how I can change my request for user input (based on my example above) using Tkinter so the application will work?
I am also using Python 2.7.

You can use the Entry() widget to get the user input as a variable.
A user can type in there ID and then hit the submit button. This button can be tied to a function that will do anything you need it to form there.
import tkinter as tk # Python 3 import
# import Tkinter as tk # Python 2 import
root = tk.Tk()
def my_function():
current_id = my_entry.get()
url_member = "https://api.example.com/member?member_id="+str(current_id)
print(url_member)
#do stuff with url_member
my_label = tk.Label(root, text = "Member ID# ")
my_label.grid(row = 0, column = 0)
my_entry = tk.Entry(root)
my_entry.grid(row = 0, column = 1)
my_button = tk.Button(root, text = "Submit", command = my_function)
my_button.grid(row = 1, column = 1)
root.mainloop()

Related

Is there a config option for non-editable prefixes in entry field

I am trying to make my own console using Tkinter, and I want to be able to display a prefix in the entry field and also use console.prefix("prefix_goes_here") to set said prefix. But when I use entry.set("prefix_goes_here") the user has the ability to delete the prefix.
example of what I mean can be found in CMD
C:\Users\Nathan>command_goes_here
everything before the ">" is what I would class as the prefix (but I do not know if it has an official name so I am just clarifying).
I also would preferably like to still be able to grab this prefix using entry.get(), but I could store the prefix in a variable and just add it later on.
There is no configuration option.
One technique is to use the validation feature of an Entry widget. In the validation function, you can check that the entry contains the prefix and reject the edit if it does not.
For more example on entry validation see Interactively validating Entry widget content in tkinter
Example
import tkinter as tk
class Example():
def __init__(self):
root = tk.Tk()
self.prefix = r'C:\Users\Nathan> '
vcmd = (root.register(self.onValidate), '%P')
self.entry = tk.Entry(root, validate="key", validatecommand=vcmd)
self.entry.pack(padx=20, pady=20)
self.entry.insert(0, self.prefix)
def onValidate(self, P):
return P.startswith(self.prefix)
e = Example()
tk.mainloop()
Although i didnt find exactly what you are asking, i would suggest using 2 entry widgets one next to the other
without borders.
import tkinter as tk
root = tk.Tk()
e = tk.Entry(root)
e.configure(state="normal",borderwidth=0,highlightthickness=0)
e.insert(tk.END, "C:\\Users\\Nathan>")
e.configure(bg='white')
e.place(x=0,y=0)
e2 = tk.Entry(root)
e2.configure(bg='white',borderwidth=0,highlightthickness=0)
e2.place(x=97,y=0)
e2.config(state="normal")
root.mainloop()

Reset user input in tkinter

I'm trying to do a script in tkinter. Good to know: I'm kind of new to python.
The script takes user input to find the user input on a server. First time I run the script it works fine, but when trying to find something new the script gives me the error: AttributeError: 'str' object has no attribute 'get' So im guesseing that the user input/Button needs to be reset some how. And I don´t understand why it works the first time and not the second time.
I've tried to find a good way to do this, but I have failed. Please halp a newbie.
import requests, re, urllib.request
import tkinter as tk
from tkinter import *
from tkinter import ttk
window = Tk()
window.title("Find answer")
ttk.Label(window, text="What you wanna find: ").pack()
stuff = ttk.Entry(window)
stuff.pack()
frame = Frame(window, width=200, height=50)
frame.pack()
servers = ["192.168.8.3", "192.68.8.2"]
def find():
global stuff
stuff = stuff.get()
stuff = stuff.lower()
for server in servers:
f = urllib.request.urlopen("http://"+server+"/find")
result = f.read().decode('utf-8')
lab = tk.Label(frame,text="server")
lab.pack()
print(server)
def clicked_start():
find()
start_btn = ttk.Button(text="Find the stuff", command=clicked_start)
start_btn.pack(fill="none")
window.mainloop()
i guess the reason is that you redefine stuff
global stuff
stuff = stuff.get()
stuff = stuff.lower()
the variable is originally an Entry Object, you redefine it as a string
Try to use another variable, eg
global stuff
stuffcontent = stuff.get()
stuffcontent = stuffcontent.lower()

Copy Entry widget text and paste into another Entry widget in the same window

How do I copy Entry widget text and paste into another Entry widget in the same window.
i.e. Let's imagine you are completing a joint credit application but you and the co-applicant have the same mailing address. Instead of re-typing the same address over again, there should be a checkbutton on the application that when it's checked it will auto-populate the co-applicant's mailing address with the main applicant's address. How do I get this done in tkinter? (I'm a tkinter and python rookie)
thanks in advance DP​
There can probably a couple more ways of achieving the behavior you want. I think using the textvariable option and Variable Classes fits well here. Together, they let a widget's text to be the same as another at all times. With the Checkbutton the user decides whether or not to do that:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def on_selection(copy_widget, paste_widget, condition_widget):
if condition_widget.var.get():
paste_widget['textvariable'] = copy_widget['textvariable']
else:
paste_widget['textvariable'] = ''
def create_entry_widgets(master):
entries = list()
for i in range(2):
entries.append(tk.Entry(master))
entries[-1].pack()
entries[0].var = tk.StringVar()
entries[0]['textvariable'] = entries[0].var
return entries
def create_checkbutton(master, entries):
checkbutton = tk.Checkbutton(master, text="Copy?")
checkbutton.var = tk.BooleanVar(value=False)
checkbutton.config(variable=checkbutton.var, onvalue=True, offvalue=False)
checkbutton['command'] = lambda cw=entries[0], pw=entries[1], \
cdw=checkbutton: on_selection(cw, pw, cdw)
checkbutton.pack()
return checkbutton
def main():
root = tk.Tk()
entries = create_entry_widgets(root)
checkbutton = create_checkbutton(root, entries)
tk.mainloop()
if __name__ == '__main__':
main()

Changing source file while program is running

I am trying to change a program's behaviour on the fly by editing its source file (under Python 3.4.2, Windows 8.1). My program is a tkinter GUI with a button that sums two values, but I want to be able to change the button's behaviour. I am currently trying to do this by editing the source file (changing, say, the addition to subtraction), saving it, and then clicking a button whose callback function imports the source file. I want my code changes to be reflected in the running GUI without having to exit and restart the program. I also want this import to only recompile the lines that I changed, rather than the entire file.
The program, reload0.py:
import time
import serial
import sys
import os
import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
try:
import Tkinter # Python 2
import ttk
except ImportError:
import tkinter as Tkinter # Python 3
import tkinter.ttk as ttk
mGui = Tk()
mGui.title("GUI")
mGui.geometry('400x200+100+100')
def mOp():
num1 = value1.get()
num2 = value2.get()
Op=num1+num2
name1.set('Sum')
name2.set(Op)
def mReLoad():
import reload0.py
mGui.update()
def mCheck():
if len(name1.get()) == 0:
name1.set('name1')
mGui.update()
if (len(name2.get()) == 0):
name2.set('name2')
mGui.update()
try:
print(value1.get())
except ValueError:
value1.set(0)
mGui.update()
try:
print(value2.get())
except ValueError as ValE:
value2.set(0)
mGui.update()
print(ValE)
value1 = DoubleVar()
value2 = DoubleVar()
name1 = StringVar()
name2 = StringVar()
mButtonSave = Button(mGui, text = "Operation", command = mOp, fg = 'Red').place(x=150,y=80)
mButtonLoad = Button(mGui, text = "ReLoad Operation", command = mReLoad, fg = 'Red').place(x=150,y=110)
mButtonLoad = Button(mGui, text = "Check", command = mCheck, fg = 'Red').place(x=150,y=140)
tText1 = Entry(mGui, textvariable = name1).place(x=10,y=80)
tText2 = Entry(mGui, textvariable = name2).place(x=10,y=100)
vText1 = Entry(mGui, textvariable = value1).place(x=10,y=120)
vText2 = Entry(mGui, textvariable = value2).place(x=10,y=140)
For your purpose of changing button functionality there are easy ways than changing source code, and as commented it's not possible.
judging from another question i saw of yours you are quite new to python programming. I would recommend spending some time on some basic tutorials getting to know python and some programming concepts first.
for instance
import reload.py
should simply be
import reload
https://wiki.python.org/moin/BeginnersGuide/NonProgrammers
read a book, do some examples, and so enough you will be the one answering the questions here, good luck!

How do I make a timer run in a Tkinter widget while a process, started by the widget, is running?

So, I used Tkinter to create a widget that allows the user to input some information and click the run button, which will begin running a test that is defined elsewhere. Here is the code. It is far from perfected, this is just a prototype:
from tkinter import*
import controller
root = Tk()
#create labels
label = Label(text = "text you don't need to know")
label.pack()
remind = Label(text = "more text you don't need to know")
remind.pack()
#create text fields
name = Entry(root)
name.pack()
name.insert(0, "Name")
name.focus_set()
testName = Entry(root)
testName.pack()
testName.insert(0, "Test name")
duration = Entry(root)
duration.pack()
duration.insert(0, "Duration in minutes")
def runTest():
controller.main(testName.get(), name.get(), float(duration.get()))
#create run button
run = Button(root, text = "Run", fg = "red", width = 10, command = runTest)
run.pack()
root.mainloop()
So, here is my issue. Once this project is implemented, the duration will likely be set for something like 1-4 hours. So, what I would like to do is have a countdown appear on the widget, so the users can reference that timer at any time to see how long until their data is produced. The problem is that as soon as my test is running, the widget locks up until it is complete. Everything I've tried is put on hold until it finishes running the test, then it does what I wanted. It doesn't help very much at that point.
Anybody have some experience at implementing something like this?
Thanks.
You'll need to fork off your work in runTest. The threading module will be your friend (e.g. from threading import Thread).
Then rewrite your runTest method:
def runTest():
# pack your arguments in a tuple
mainArgs = (testName.get(), name.get(), float(duration.get()))
# create a thread object armed with your function and the args to call it with
thread = Thread(target=controller.main, args=mainArgs)
# launch it
thread.start()
#and remember, never set state (directly or indirectly) from separate threads without taking appropriate precautions!

Categories