Tkinter opens instantly subprocess instead of waiting for button click [duplicate] - python

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 7 months ago.
I'm working on a code editor based on nano. I've decided to make GUI for it, and the GUI language I chose is Python. I'm trying to make a button that opens batch files on Tkinter. I did so by importing import subprocess. Now, I created a button that opens the batch file with subprocess:
ttk.Button(frm, text="New Session", command=subprocess.run(['csession.bat']) ).grid(column=0, row=1)
Little problem is, when I launch the file, the subprocess action instantly gets executed instead of waiting for the user to click. I'm using VSCode and also debugging in VSCode (if that does any difference).

you need to use lambda if you want to define the command this way.
you can also create a function and set the command to run it.
import tkinter as tk
from tkinter import ttk
import subprocess
def runBat():
subprocess.run(['foo.bat'])
root = tk.Tk()
ttk.Button(root,text="text",command= lambda: subprocess.run(['foo.bat'])).pack()
ttk.Button(root,text="text2",command=runBat).pack()
root.mainloop()

Related

How to make a program that doesnt close when X is pressed and still runs in backroun? [duplicate]

This question already has answers here:
Running a Tkinter window and PysTray Icon together
(3 answers)
Closed 10 months ago.
I want to make a script that runs every hour but i don't want the GUI to be visible in taskbar. I don't mind if the GUI is visible when the program is first opened but if the user decides to press the X i want the program to disappear from the taskbar and be visible in the bottom right corner(Skype, discord, ccleaner behaviour)
The GUI is made with tkinter.
How can i do this behaviour? If at all.
To detect if the close button is pressed in tkinter, use the following right before you run root.mainloop()
root.protocol("WM_DELETE_WINDOW", on_closing)
this will call the on_closing function when the user presses the close button, which you can use the following code to make it into a button
root.iconify()
This will minimize it to the taskbar as a button.
Note this will not work on Mac as the window will just be hidden and you will have no way to actually closing it unless killing it manually
so something like this
from tkinter import tk
root = tk.Tk()
#define widgets and other things here
def on_closing():
root.iconify()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
If you want it to be on the system tray, tkinter have no support for that, so you'll have to use something like pystray

Python, tkinter, window freeze after mainloop (on MacOSX)

Could not find anything on this topic in other posts (or maybe I just completely did not understand how tkinter works).
I have a very simple setup where after closing my window, a Shell script is supposed to be executed. The problem (at least on MacOSX) is that while the shell script runs, the window freezes and stays open.
Minimal working example:
from tkinter import Tk, Label
from subprocess import call
# GUI
root=Tk()
Label(root,text="Test window").pack()
root.mainloop()
# call
call("sleep 10", shell=True)
# Window stays open and freezes until sleep command returns
Am I missing something?
Thanks! Jan

Binding a button to a VPython 7 function

I am currently trying to make a physics simulation using VPython on my laptop. I want to make a GUI so that when the client presses the run simulation button, it opens chrome and the simulation runs, after taking the user's input from entry boxes. However, when I run the source code, chrome automatically opens and I want it to open only when the user presses the run simulation button. I tried using the lambda method to bind the function to the button, but it isn't working. Here is a very simplified version of what I am trying to do:
import tkinter as tk
from vpython import *
### Simulation ###
def run_simulation(r):
sphere(radius=r)
### GUI ###
root = tk.Tk()
text_variable = tk.StringVar()
entry = tk.Entry(root, textvariable=text_variable, width=10)
entry.pack()
button = tk.Button(root, text='Run Simulation', command= lambda: run_simulation(eval(text_variable.get())))
button.pack()
root.mainloop()
In short, if you run this code, it will open chrome automatically (even though I used lambda), but I only want it to do so if the button is clicked. Thanks in advance.
Here are a bunch of vpython demo programs that you can run in a browser using glowscript vpython
http://www.glowscript.org/#/user/GlowScriptDemos/folder/Examples/
Just click run beside the image and it runs the simulation.
These same vpthon Demo programs are also found on github here.
https://github.com/BruceSherwood/vpython-jupyter/tree/master/Demos_no_notebook
you can run the programs from the Windows Command prompt if you have python 3.6 installed on your machine. Just type
python BinaryStar.py
and it will open a web browser and run the BinaryStar vpython demo program. You can do the same for the other demo programs in the above directory on github.
Maybe you can get your button to run the command "python myVpythonProgram.py" to run the vpython program you want to run in a browser.

Tk open window issue/bug

If I type the following in the interpreter it works like a charm:
from Tkinter import Tk
from tkFileDialog import askopenfilename
Tk().withdraw()
fh = open(askopenfilename(), 'r')
However, if I write/save/run a script with exactly the same commands, though it works (kind of like expected) the open window goes blank and remains on screen (after opening the selected file) and stays on top of everything.
As a result I need to click on the Python icon again in order for the window to close. At one point this stopped happening, but when I ran a script once without the Tk().withdraw() command the problem re-emerged.
I am running OSX Mavericks. If there is no way to fix the bug, is there any command in Python I can implement that closes this window?
See the accepted answer to this question When do I need to call mainloop in a Tkinter application?. You normally need to call Tk.mainloop() to start the event loop processing for Tk. But when you are running in the interactive interpreter, Python calls the Tk event processor for you, otherwise you would not be able to use Tkinter in the interactive interpreter as easily.

Python Tkinter Window Output and Shell Input

I am having a problem between the python shell in my IDE and the Tkinter window. What I am trying to do is have all of my user input in the shell, and then I would like to output the corresponding information in a Tkinter window.
However, when my window is made and pops up, I close it to continue my program in the shell, then I continue with input. However, when I try to reinitialize my window. It says that the window has been destroyed. I understand what this means so I tried having a Toplevel window where I output my info which can be closed, and hide my root window, but the shell will not continue until I close/destroy the root window as well.
Is there a way I can continue in the shell without destroying my root window? I am fairly new to this language so any help would be very much appreciated.
This is my general idea:
from Tkinter import *
#get all my info from the shell
root = Tk()
root.withdraw() #hide the root window
main = Toplevel()
#this is the window that I want to be able to close and open later
#get more info from the shell after main is closed
#now I want to open the updated main window
Thanks in advance! (And I am working on Windows if that matters)
I'm not sure if the way you are trying to do this is the most efficient way, but i would propose these changes so far:
from Tkinter import *
#get all my info from the shell
window = Tk()
window.iconify() #hide the root window
#get more info from the shell after main is closed
window.deiconify()
window.mainloop() # to handle events
i renamed your root-Window to make it more clear for you whats happening and removed the superflous (imho) additional Toplevel-window!
Also keep in mind, that you won't accomplish anything without the mainloop and the necessary event-handlers!
Simply put, this is not how Tkinter is designed to work. Tkinter was designed to have a single root window that is created once, and with a single eventloop that is running. Using it any other way is bound to lead to undesired behavior.
If you really need code to work this way, gather your input from your shell in one process, then use a separate process to display the tkinter window. You can either communicate from one the other using a socket, or you could pass the data from the parent to the child via arguments or environment variables or temporary files.

Categories

Resources