I am not allowed to add images yet to question posts.
Question below:
My app currently uses a window that is coded in a class.
My ultimate goal is to press enter while entering letters and numbers into an entry widget and press enter, then the function would update text that correlates to a label in my main window.
Detailed description below:
I cannot figure out how to create and entry and then bind the enter key so that when I run my app, I can click in the entry, type a value and press enter.
I see plenty of button references and I can get the button to work, but I am trying to learn how to do things and do not want to rely on buttons in this instance.
I saw in some other posts that if you call .get with an entry object, that the python code will just execute it and move on. I tested with a print statement in the function I want to call upon pressing enter, and the print statement appeared in the terminal before I typed anything in the entry widget. I then tried to type and press enter, and nothing would occur.
Should I abandon binding the ENTER key and stick with buttons in tkinter as a rule, or is there a proper way to do this? In my code example, you will see up_R is the function I am trying to execute when pressing Enter. If I use up_R(), it executes immediately. If I use up_R, then I get a TCL Error.
Specific Partial code located below:
def up_R():
print('Makes it here')
self.R.update_disp(self.e.get())
self.e.bind('<ENTER>',up_R)
The full code is below if required for assistance:
#NOAA SPACE WEATHER CONDITIONS
from tkinter import *
class window:
def __init__(self):
#main window
self.window = Tk()
self.window.title('NOAA SPACE WEATHER CONDITIONS')
self.window.geometry('800x600')
#window organization
self.window.grid_rowconfigure(0, weight = 1)
self.window.grid_rowconfigure(1, weight = 1)
self.window.grid_columnconfigure(0, weight = 1)
self.window.grid_columnconfigure(1, weight = 1)
#temp entry frame
self.e = Entry(self.window)
self.e.grid(row = 1, column = 0, sticky=N)
self.e.insert(END, 'R entry')
#init class R
self.R = R()
#init class S
self.S = S()
#init class g
self.G = G()
#frame for RSG
self.frame = Frame(self.window)
self.frame.grid(row = 0, column = 0, columnspan = 2, padx=10, pady=10)
#disp class R
self.rf = Frame(self.frame, highlightbackground='black', highlightcolor='black', highlightthickness=1)
self.rf.pack(side = LEFT)
self.rl = Label(self.rf, text = self.R.dkey, bg='#caf57a')
self.rl.pack(side=TOP)
self.rl_lower = Label(self.rf, text= self.R.tile_text, bg='#caf57a')
self.rl.pack(side=BOTTOM)
#Value update methods
# self.R.update_disp(self.e.get())
# #action
def up_R():
print('Makes it here')
self.R.update_disp(self.e.get())
self.e.bind('<ENTER>',up_R())
#main window call - goes at end of class
self.window.mainloop()
class R:
def __init__(self):
d = {'R':'None','R1':'Minor','R2':'Moderate','R3':'Strong','R4':'Severe','R5':'Extreme'}
self.dkey = 'R'
self.tile_text = d[self.dkey]
print(d[self.dkey])
def update_disp(self, dkey):
self.dkey = dkey
class S:
d = {'S1':'Minor','S2':'Moderate','S3':'Strong','S4':'Severe','S5':'Extreme'}
pass
class G:
d = {'G1':'Minor','G2':'Moderate','G3':'Strong','G4':'Severe','G5':'Extreme'}
pass
t = window()
The ENTER should be changed with Return, and the function should accept an event
Also, don't forget in a 'class' to use self in the method and self.method to call it.
def up_R(self, event):
print('Makes it here')
self.R.update_disp(self.e.get())
self.rl.config(text=self.R.dkey)
self.e.bind('<Return>', self.up_R)
Related
I would like to remove the highlighting from my combobox widget when the user selects an option. But the method select_clear() doesn't seem to be working :(
Any clues why ?
from tkinter import *
from tkinter.ttk import Combobox
class hey(Frame):
def __init__(self):
Frame.__init__(self)
self.comboboxVariable = StringVar()
values = (1, 2, 3, 4, 5)
self.comboBox = Combobox(self, textvariable = self.comboboxVariable, values = values, state = 'readonly')
self.comboBox.pack()
self.comboBox.bind("<<ComboboxSelected>>", self.updateData)
def updateData(self, event =None):
self.comboBox.select_clear()
myClass = hey()
myClass.pack()
root = myClass.master
root.mainloop()
What you are trying to do and what your script is attempting to do are two different things. First, you have event = None, which causes the function to be called when you first initialize an object and then never again. Instead, leave the function attribute just as 'event' so that it runs when the specified event takes place.
To remove the selection made, your updateData function would look like the following:
def updateData(self, event):
self.comboBox.set("")
However, to remove the highlighting from the chosen value, you would need to change the focus from the combobox to the root window:
def updateData(self, event):
self.focus_set()
Hope this helps.
I am currently trying to make a GUI to an existing python program using Tkinter. The program gives the user two options from which the user must choose to either accept or decline. Before using Tkinter the options were placed in the terminal and awaited for a raw_input. (y/n). How can I make this so the canvas text updates with the new data and awaits for the users button click?
To make my question more specific: How can I run another programs code while the Tkinter mainloop is running and make these two interact?
Example code below.
from Tkinter import *
root = Tk()
root.resizable(width=False, height=False)
root.geometry('{}x{}'.format(500,550))
root.wm_title("Tkinter test")
BtnFrame = Frame (root)
BtnFrame.pack(side = BOTTOM)
BtnFrame.place(y=450, x=20)
canvas_1 = Canvas(root, width = "200", height ="300")
canvas_2 = Canvas(root, width = "250", height ="300")
canvas_1.pack(side = LEFT)
canvas_2.pack(side = RIGHT)
textfield_1 = canvas_1.create_text(100,50)
textfield_2 = canvas_2.create_text(100,50,)
def update_textfiel_1(text):
global textfield_1
canvas_1.delete(textfield_1)
textfield = canvas.create_text(100,50,text = text)
def update_textfiel_2(text):
global textfield_2
canvas_2.delete(textfield_2)
textfield1 = canvas1.create_text(100,50,text = text)
Accept = Button(BtnFrame, text="Accept", width=25)
Decline = Button(BtnFrame, text="Decline", width=25)
Accept.pack(side = LEFT)
Decline.pack(side = RIGHT)
root.mainloop()
First off you have some inconsistent variable names in your update_textfiel functions, you can greatly simplify it by using .itemconfigure (documentation for methods on canvas widget)
def update_textfiel_1(new_text):
canvas_1.itemconfigure(textfield_1, text=new_text)
def update_textfiel_2(new_text):
canvas_2.itemconfigure(textfield_2, text=new_text)
If I understand correctly you want a way to have a function that will simply wait for the user to press one of the buttons and then return the result, this is very easy with tkMessageBox:
question = """Do you accept {}?
if you say no you will instead get {}"""
#this message can GREATLY be improved
# But I really don't understand what you are using it for...
def user_confirmation(name1, name2):
response = tkMessageBox.askyesno("Accept or Decline",question.format(name1,name2))
print(response)
if response: # == True
return name1
else:
return name2
I have not yet found a way to make a blocking function that works with the window you have currently...
I've been trying to create a piece of code that would take a integer as a argument and create that number of tkinter entry fields. With a submit button at the end that would retrieve the data from the fields add these data to a list then close the window.
I have been able to get it working however I cant find a way to convert this to a callable function; a requirement to use it with the rest of my program.
This is the code I have produced so far, thanks:
import tkinter as tk
b = input("Enter: ")
b = int(b)
root = tk.Tk()
newdict = dict()
outputs = list()
for i in range(b):
newdict["entry" + str(i)] = tk.Entry(root)
newdict["entry" + str(i)].pack()
button1 = tk.Button(root, text="Submit", command=lambda: Get(newdict))
button1.pack()
def Get(newdict):
for j in range(b):
outputs.append(newdict["entry" + str(j)].get())
root.quit()
root.mainloop()
print(outputs)
The basic idea is to create a window, then use the wait_window method to wait for the window to be destroyed. Once it has been destroyed you can return some value.
The problem is that the values you want to fetch must not be attributes of the window, since it will have been destroyed by the time you are ready to fetch them. You need to set up your code to save the values before the window is destroyed.
A simple way is to provide an "OK" button which gets the values and then destroys the window. Another way would be to put a trace on variables associated with each entry, and save the values immediately as they are edited.
Which method you choose depends on what behavior you want when the user clicks the window control to close the window (eg: the red circle on OSX, the [x] button on windows, etc). Do you want to return what they had input, or do you treat that as a cancel action and return nothing?
Here's a simple example using an OK button. This example assumes that you aren't already running a GUI, and that this is to be run as part of a non-GUI application.
import tkinter as tk
class Dialog(object):
def show(self, num_fields):
self.num_fields = num_fields
self.root = tk.Tk()
self.entries = []
for i in range(num_fields):
entry = tk.Entry(self.root)
entry.pack(fill="x")
self.entries.append(entry)
ok = tk.Button(self.root, text="OK", command=self.ok)
ok.pack(side="bottom", anchor="e", pady=(10,0), padx=10)
# wait for the window to be destroyed, then
# return the values. If the user clicks the OK button
# the values will be set; if they cancel the dialog
# this will return None.
self.values = None
self.root.wait_window()
return self.values
def ok(self):
# save all the values, then destroy the window
self.values = []
for i in range(self.num_fields):
self.values.append(self.entries[i].get())
self.root.destroy()
Assuming you're running a non-gui program, here's an example of how you would use this class:
b = input("Enter: ")
b = int(b)
result = Dialog().show(b)
print("result:", result)
I want to make a keyboard quick operation command with Tkinter.The keyboard event will invoke a function:when I press 'b',executive function 'buy',and when I press 's',executive function 'sell'.But there is a entry in my GUI.When I input a number in this entry,I'll press 'b' to invoke function 'buy' or press 's' to invoke function 'sell'.Of course the entry will display 'b' or 's'.I want to invoke function when I press 's' or 'b' and the entry will just distinguish and display numbers.How can I achieve this purpose ?
Here is my code:
# -*- coding: utf-8 -*-
from Tkinter import *
import tkFont
import datetime
class TradeSystem(object):
"""docstring for TradeSystem"""
def __init__(self):
self.root = Tk()
self.root.geometry('465x180')
self.root.resizable(width=True, height=False)
Label(self.root, text = 'Volume',font = tkFont.Font(size=15, weight='bold')).grid(row=0, column=0)
self.e1_str = StringVar()
self.e1 = Entry(self.root,bg = '#D2E48C',width = 10,textvariable = self.e1_str)
self.e1.grid(row = 1, column = 0)
self.v = IntVar()
self.Cb = Checkbutton(self.root,variable = self.v,text = 'Keyboard active',onvalue = 1,offvalue = 0,command = self.Keyeve)
self.Cb.grid(row = 3,column = 0)
self.currenttime = StringVar()
Label(self.root,textvariable = self.currenttime).grid(row=4, column=0,sticky = NW)
self.t_loop()
self.root.mainloop()
def buy(self,event):
print 'This is buy function.'
def sell(self,event):
print 'This is sell function.'
def rb(self):
self.root.bind('<KeyPress-b>',self.buy)
self.root.bind('<KeyPress-s>',self.sell)
def Keyeve(self):
if self.v.get():
self.rb()
else:
self.root.unbind('<KeyPress-b>')
self.root.unbind('<KeyPress-s>')
def t_loop(self):
self.currenttime.set(datetime.datetime.now().strftime("%Y-%m-%d,%H:%M:%S"))
self.root.after(1000,self.t_loop)
if __name__ == '__main__':
TradeSystem()
I input some numbers in entry self.e1,and when the keyboard active is 'on',I press 'b' to invoke function 'buy',like:
And fucntion 'buy' worked.
I just want the entry to distinguish numbers and when I press 'b' after I complete input numbers function 'buy' is invoked immediately.How can I achieve that?
Separate the text input from command hotkeys by using a modifier key, like Ctrl:
self.root.bind('<Control-b>',self.buy)
self.root.bind('<Control-s>',self.sell)
self.root.bind('<Control-B>',self.buy)
self.root.bind('<Control-S>',self.sell)
Note that the above has bound both the uppercase and lowercase keys, so that it still works if Caps Lock is on.
I am trying to make a button that when clicked updates the number on a label. What I am trying to accomplish is that when someone scores a goal, you can click the Goal! button and it will update the teams score.
import sys
from tkinter import *
root = Tk()
class team1:
score = 0
def goal(self):
self.score += 1
team1_attempt.set(text = self.score)
team1 = team1()
team1_attempt = Label(text = team1.score).pack()
team1_button = Button(text="Goal!", command = team1.goal).pack()
Hope someone can help! New to python.
You have two problems with your code.
First problem:
team1_attempt = Label(text = team1.score).pack()
This sets team1_attempt to None, because pack(0 returns None. If you want to save a reference to a widget so you can interact with it later you must do widget creation and widget layout in two steps.
Second problem:
team1_attempt.set(text = self.score)
To change an attribute of a widget, use the configure method. I don't know what documentation you read that says to call set on a label widget, but that documentation is wrong. Use configure, like so:
test1_attempt.configure(text=self.score)
Instead of using a label, try using an Entry widget that inserts the score into the Entry widget. For example:
class test:
def __init__(self, master):
self.goalButton = Button(master,
text = "goal!",
command = self.goalUpdate)
self.goalButton.pack()
self.goalDisplay = Entry(master,
width = 2)
self.goalDisplay.pack()
self.score = 0
def goalUpdate(self):
self.goalDisplay.delete(1.0, END) # Deletes whatever is in the score display
score = str(self.score)
self.goalDisplay.insert(0, score) # Inserts the value of the score variable