Application console for Tkinter program?
Terry Reedy
tjreedy at udel.edu
Sat Mar 5 05:15:16 EST 2016
On 3/5/2016 2:52 AM, Christian Gollwitzer wrote:
> is there an easy way to add an application console to a Tkinter program?
Right now, you should turn the question around. Is there an easy way to
run a tkinter program within an interactive console? Answer: yes, two
ways, after removing the runshell stuff and mainloop call*.
1. Call your program mytk.py. In your system console, run 'python -i
myth.py'. When the code ends, control passes to the console running
python. Statements like 'print(nvar.get())' will be executed in the
main namespace of the still running program.
2. Load (or write) the file into an IDLE Editor and hit F5 (Run -> Run
module on the menu). This simulates the console command above.
* The tk loop is started with the Tk() call. Most things work without
the blocking mainloop() call. When this is true, the mainloop call
serves mainly to keep the program running instead of exiting. The -i
option does the same.
If you need mainloop(), then add
def quit(): # or quit(self):
root.exit()
b = tk.Button(root, command=quit)
b.grid() # or pack or place
The root.quit() call ends the blocking mainloop call and allows console
entry. I believe a subsequent root.mainloop() in the console will work
when needed.
> For instance, can you embed IDLE into a program such that when a button
> is pressed, it pops up a REPL window where the running program can be
> examined?
If the REPL window is defined in an imported module, the problem is
linking the main namespace of the tkinter program with the REPL loop in
such a way that commands entered into the REPL are executed in the main
module, not in the REPL module.
> Say, there is a simple program like:
>
> ====================
> import Tkinter as tk
>
> def runshell():
> from idlelib.PyShell import main
> main()
>
> root=tk.Tk()
> nvar=tk.StringVar(root)
> en=tk.Entry(textvariable=nvar)
> en.pack()
>
> btn=tk.Button(text="Shell", command=runshell)
> btn.pack()
>
> root.mainloop()
> ====================
>
> I want the button to popup a shell window, and then nvar.get() should
> give me whatever is currently written in the entry. The code above does
> not work as intended, it pops up a shell, but:
>
> 1) I can't reach the variables from the main program, i.e. print(nvar)
> gives me a NameError
This is the linkage problem I mentioned.
> 2) If you click the Shell button twice, it locks up the program, because
> main() obviously starts it's own mainloop
IDLE executes user code in a separate process, linked by sockets, so
that execution of IDLE GUI code and user code do not interfere with each
other. I would like to refactor IDLE so that the Shell window would
contain a Shell Frame (or LabelledFrame) that could also be used as pane
in a single-window version of IDLE. It would be possible to create a
Shell frame without starting a new mainloop.
It might be possible to adapt such a component as an embedded console.
An imported frame should not interfere with the main-module code or code
in other modules. The main problems are a) namespace linkage (mentioned
before), b) the need for sys.stdin/out/err to not be None, and c) for
capturing exceptions in code entered in the console, so as to not crash
the main program.
--
Terry Jan Reedy
More information about the Python-list
mailing list