Stop a Python program until a user performs an action - python

My original program used input, like this:
n = input("Enter your favorite number: ")
# do stuff with number
Now, I have switched to a GTK GUI, but still want the accomplish the same thing. Now look at this very similar piece of code:
n = myWindow.getNumber()
# do stuff with number
Would it be possible to write a getNumber() method that only returns after the user presses a submit button in the window? (like the how the input function works) or is this my only option:
def callback(widget, event):
n = myWindow.inputWidget.getValue()
# do stuff with number
n = myWindow.getNumber(callback)
Update: I'm looking to do this without a gtk.Dialog, as I don't want a dialog popping up every time user input is required.

What you need is a modal dialog. I don't know GTK (or PyGTK) at all, but there appears to be an example in the documentation.

Related

python tkinter wait until entry box widget has an input by user ONLY after then continue

I have a code snippet which runs perfectly. In some cases, I need user input, but there are also cases where user input is not necessary and code functions without it perfectly.
So, in that cases I create with conditional a flow where entry box widget is created and destroyed after value is get() by script. But I cannot make code to wait until to say stops(pauses) when the user has given input value then continues to run.
code is below;
varSheetname_GS = ''
if varsoundTitle_usernameHeroContainer == 'FloatingBlueRecords' or varsoundTitle_usernameHeroContainer == 'DayDoseOfHouse':
varSheetname_GS = varsoundTitle_usernameHeroContainer
else:
# look for sheetname as an input value entered by user
new_sheetname_entryBox=tk.Entry(canvas2,width=30).pack()
new_sheetname_entryBox.focus()
var_new_sheetName =new_sheetname_entryBox.get()
new_sheetname_entryBox.destroy()
varSheetname_GS = var_new_sheetName #input("Enter the sheetname in (GooSheets):")
I have looked for so_01 and so_02 which are related to topic but was not able to implement in my situation. So, anyone who would guide me towards that answers would be great from yourside.
Thanks ahead!
You can use the wait_window method to wait until the entry widget has been destroyed. You can then bind the return key to destroy the window. If the entry is associated with a StringVar, you can get the value after the widget has been destroyed.
The solution might look something like this:
entry_var = tk.StringVar()
new_sheetname_entryBox=tk.Entry(canvas2,width=30, textvariable=entry_var)
new_sheetname_entryBox.pack()
new_sheetname_entryBox.bind("<Return>", lambda event: new_sheetname_entryBox.destroy())
new_sheetname_entryBox.focus_set()
# wait for the entry widget to be deleted...
new_sheetname_entryBox.wait_window()
# save the value
varSheetname_GS = entry_var.get()

How do I make the numbers do their operation? Is there any module that can do that?

def equalizer(entryblock):
x = entryblock.get()
entryblock.delete(0, tk.END)
entryblock.insert('end', int(x))
so here is a function for my tkinter calculator. I am trying to make a function where it takes the entry box and does the operations and gives the result. For example, if I punch in '1+2+3', I want this function to turn it into 6. Whenever I try this, it gives this error:
ValueError: invalid literal for int() with base 10: '1+2+3'
Could I use the math module to fix this problem?
There are 3 ways to solve this problem as far as I can think:
One is to use eval but then you cannot have the user input the values into the entry, as its not safe.
Next is to implement an AST parser suitably, that way you can use user input via Entry and still be safe from the exploits of eval.
The third way would be change your logic and make the app work like how the calculator in windows works, this way you do not need eval or anything. You will have to keep reference to the last item given and then add(or any operation) with the next entered item. Video reference: Build A Simple Calculator App - Python Tkinter GUI Tutorial #6, there is a previous part but only follow the logical part of the code, the other part is quite naïve.
For the first approach, this should give you a bare example:
from tkinter import * # Note: Better to use import tkinter as tk and make changes needingly
root = Tk()
def write(num):
lbl['text'] += num # Add the user inputted number to the end of current text from label
def calc():
out = eval(lbl['text']) # Get the text and do the operations
lbl['text'] = str(out) # Change the text with the output
texts = '123456789' # Digits to loop through
lbl = Label(root,font=(0,15),justify='left')
lbl.grid(row=0,column=0,columnspan=3)
# To create a 3x3 grid of widgets, starting from 1 because 0th row/column is already taken by the label
for i in range(1,4):
for j in range(1,4):
text = texts[3*(i-1)+(j-1)] # Indexing to get the respective texts
Button(root,text=text,command=lambda num=text: write(num),width=15).grid(row=i,column=j-1)
# Some buttons outside the normal gridding behavior and with different function
Button(root,text='+',command=lambda: write('+'),width=15).grid(row=i+1,column=0)
Button(root,text='0',command=lambda: write('0'),width=15).grid(row=i+1,column=1)
Button(root,text='=',command=calc,width=15).grid(row=i+1,column=2)
Button(root,text='C',command=lambda: lbl.config(text=''),width=15).grid(row=i+2,columnspan=3,sticky='news')
root.mainloop()
You can design/place the widgets the way you want, notice how the function handles the input and user cant input any number as they wish either.
For the second approach, you can refer here for a code from Kevin that implements ast and does calculation and you can take user input as well and integrate tkinter with that function by making a few tweaks.
So to answer your question:
Could I use the math module to fix this problem?
Nothing I can think of from math does what you are looking for.

How to specify input language for Entry or any other input field?

In short, i try to type letters (in input components like "Entry", "Text") that are allowed by Windows language-keyboard (i'm using "Latvan(QWERTY)" keyboard) and i can't write long letters like 'ā', 'č', 'ģ' and others.
For example, when i try to write 'ā', the result is 'â'.
The interesting part - when i focus on specific GUI input fiend and change Windows keyboard-language (with "Alt+Shift" shortcut or manually) twice (for example, from "Latvan(QWERTY)" to "Russian" and back to "Latvan(QWERTY)") - then i can write all letters i needed.
What i want is to set all input fields keyboard-language so i could write all letters i want without doing things mentioned above every time i launch my GUI program.
If you need more info or there is already place where this question is answered, please leave a comment and i will act accordingly.
Edit 1:
I am using PyCharm to write my Python Tkinter code. I tried to assign necessary keyboard to my program's generated GUI form according to this guide but it didn't work (i guess that because i used it on temporary created GUI forms).
I was able to solve my problem by using pynput.
Here is simplified version of my final code:
from tkinter import *
from pynput.keyboard import Key, Controller
def change_keyboard_lang(event):
keyboard = Controller()
for i in range(2):
keyboard.press(Key.alt)
keyboard.press(Key.shift_l)
keyboard.release(Key.shift_l)
keyboard.release(Key.alt)
root = Tk()
word_input = Entry(root)
word_input.focus_set()
word_input.bind("<FocusIn>", change_keyboard_lang)
word_input.pack()
root.mainloop()
In short, if cursor is focused on Entry field "word_input", system calls function "change_keyboard_lang" that changes input language from original to other and back to original - and now i can write necessary letters.
It's not the best solution since i need to bind event to every input field in my GUI form but it gets the job done. If you have a better solution please post it here.

A global key that that takes you back to menu

I have tried to find what I am seeking before posting this. But I have a hard time formulating the question and finding an answer.
I wonder if there is any way of having a key, such as "b", that takes the user back to the main menu where ever he is while running my program.
I have a menu and sub-menus and I want the user to be able to go back to the menu wherever he is by just pressing "b". I wonder if there is any easy way of doing this instead of putting
if choice= b:
menu()
whenever I have an input()...
I hope this is not too confusing! Would really appreciate a answer!
Not recommended for making your code easy to read but...
You could make your 'b' input check a function, then run that function at the start of each input check
def b_check(option):
if option == 'b':
main_menu()
else:
return option
def main_menu():
#your main menu function goes here
#your active menu code goes here
#ask the user to make their selection
#Note: for Python 2.x use `raw_input`
option = input('Enter your choice')
b_check(option)
if option == 'a':
#do this
elif option =='c':
#do that

How can I call a "command" with tkinter.simpledialog?

So I'm trying to create a dialog box that asks the user for an input (a number) with python's built-in Tkinter library. In particular, I googled that this could be easily achieved with the method simpledialog.askinteger.
In a normal tkinter.button, I have the argument "command" which allows me to call a method. This is how I first made this part of my code within the main window:
self.generate_game_button = tkinter.Button(self.main_window, text='Start!', \
command=self.create_grid)
But as I want to ask for this number in a pop up window, in tkinter.simpledialog.askinteger, there is no argument for command, so I'm left with no way of calling my create_grid method... The code looks like:
def press_newgame(self):
global a
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
My create_grid method basically makes a set of buttons using the inputted int... How can I achieve this using a pop up window to ask the user for a number, and then call the create grid method similar to how the tkinter.Button works?
I hope this makes sense... Thanks.
Well, this is working differently than a simple button, because askinteger is a dialog window, which is not there constantly, it has to be called, and then it will automatically return you a value -- as you expect it.
So I guess you want to do something with the given a value (you probably want to pass it to the create_grid method, so all you have to do is call the method after you got the integer value, something like this:
def press_newgame(self):
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
self.create_grid(a)
I'm not sure a perfectly understand your usecase. If i understand well, you have a "New game" button, and after the user pressed that button, you want to show the askinteger dialog to get the size of the grid you have to generate for the player. In this case, why you just call your your grid-creating function simply after you came back from the dialog, so like:
global a
a = tkinter.simpledialog.askinteger('Inputz', 'Enter the gameboard size')
createGrid(size=a) # or whatever your function is

Categories

Resources