Pycharm automatically closes a program, python idle doesnt - python

When running a tkinter program in the standard python idle program the window displays and you are able to interact with it, yet running the same program in pycharm causes the program window to flash up briefly then close.
I'm assuming its to do with the mainloop, what do you need to modify in your code to prevent the program from automatically closing when running in pycharm
An excert from my code follows
from tkinter import *
import tkinter
from tkinter import Text, Tk, ttk
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, root):
....
def main():
global label
root = Tk()
root.title(" My program")
root.geometry("550x330+600+300")
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
root.configure(bg=mycolor)
gui = GUI(root)
main()
Update : After a bit of mucking around, partly due to my code not being the best (rookie), I've managed to get it to work. For anyone interested heres the modification:
from tkinter import *
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, master):
self.master = master
master.title(" My Programs")
master.geometry("550x330+600+300")
master.iconbitmap('logo.ico')
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
master.configure(bg=mycolor)
....... Most of the above is program set up stuff but shown
MAIN CODE HERE
root = Tk()
gui = GUI(root)
root.mainloop()
Works now as expected

Python has a -i startup option which cause Python to enter interactive move when the program finishes, instead of exiting. IDLE executes code as if one entered python -i file.py at the terminal. This allows one to interactively explore the live gui by entering code in the Shell.
From this question and the one referenced by flyingmeatball, it appears that PyCharm does not use or simulate -i. So one must finish a tkinter program with root.mainloop to see anything. Unless one adds a button to quit the mainloop without destroying the application, one will not be able to interact with interactive statements. (Again, this is completely based on what has been posted on SO, as I have no experience with PyCharm.)

Related

How can i avoid Tkinter GUI freezing in Python3?

I am quite new in python and made a Tkinter application that will execute all python files existing in the directory when pressed the start button. My GUI also has progressbar to see the current progress.
so here is my code
import os
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
directory = dir_path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(directory)
root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')
v = 0
def begin():
global v
for x in files:
os.system('pyinstaller '+x)
v=v+1
p['value']=v
p = Progressbar(root,length=200,max=len(files))
b = Button(root,text="Start",command=lambda: begin())
p.place(x=0,y=0)
b.place(x=62,y=30)
root.mainloop()
but my problem is, Whenever i press start button, The GUI freezes and codes start getting compiled and when completed, the GUI unfreezes and the Progressbar fills itself full at once...
So i want the GUI not to freeze while processing and show correct progress on the Progressbar.
Example code and Explanation will be better for me.
Thanks for your valuable time...
This worked.No need to use .after() to check the thread is finished.
import os
from tkinter import *
from tkinter.ttk import *
import threading
def use_pyinstaller(): # this function is to execute pyinstaller command and add value to progressbar.
v = 0
for x in files:
os.system('pyinstaller '+x)
v+=1
p['value'] = v
def begin():
threading.Thread(target=use_pyinstaller).start() # create a non-block thread to start the function.
directory = dir_path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(directory)
root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')
p = Progressbar(root,length=200,max=len(files))
b = Button(root,text="Start",command=begin)
p.place(x=0,y=0)
b.place(x=62,y=30)
root.mainloop()
First off, the command argument for the button can just be: command=begin.
GUI toolkits like tkinter are event-driven. They depend on a smooth flow of keyboard and mouse events to work properly.
Callbacks (like the command from a button) are called from witin the event loop (root.mainloop).
So a callback should only take a short time (say 50 ms) as to not freeze the GUI. You should therefore never run a long-running loop in a callback. You have to program in a different style.
The above link takes you to an article on my website where I compare a simple command-line program with an equivalent GUI program. While that program doesn't use external processes, it illustrates the principle.
The proper way to do this in a GUI, is to start a multiprocessing.Process from the button callback.
Then use the root.after method to periodically run a callback that checks if the Process is finished, and then start a new process.

Tkinter button open another window that i don't want

as I say in the title, when I click on a button (analyse) another windows open and I don't want it. The problems is, in the analyse function, the first line is an import of my tkinter file.
Thanks in advance for any help.
I tried to delete the import and the second windows does not pop up, so I am pretty sure it is the problem. Moreover I need to do this import in the analyse function because I already import the other module in my tkinter file
tkinter file :
import fileb
def analyser():
output=fileb.analyse(name)
fenetre = Tk()
fenetre.geometry("800x500")
label = Label(fenetre, text='Emotion Video')
label.pack()
boutonanalyse=Button(fenetre, text='analyze', command=analyser)
boutonanalyse.pack(side=BOTTOM)
fileb :
def analyse(name):
import tkinter_essais
When you import your Tkinter file, you are running that file. This means that the code is run twice and so you have two windows opened up. A way to bypass this is by putting your tkinter setup into a function, and having that run if it is the main program only using something like this:
import fileb
def analyser():
output=fileb.analyse(name)
def tkSetup():
fenetre = Tk()
fenetre.geometry("800x500")
label = Label(fenetre, text='Emotion Video')
label.pack()
boutonanalyse=Button(fenetre, text='analyze', command=analyser)
boutonanalyse.pack(side=BOTTOM)
if "__name__" == "__main__":
tkSetup()
The if name == main checks if the program is being run originally (best way I can think to describe it) and so it wont be run if you import the file.

Problem with tkinter code execution order

I have my principal script running with terminal that works perfectly. Im trying to make a gui for it but im stuck at this point.
Like you see on the screen, at the start of the script it asks if it should check the database. And just after, it asks first the platform before opening the captcha for the database check. The problem happens exactly here on my GUI version, look.
Like you see, the gui starts, but when i click on check for new database, it directly opens the captcha without asking the platform... And it asks me the platform only after i solved the captcha which i dont want to after...
Here is the main testkinter.py code:
import tkinter as tk
from tkinter import messagebox
import commands
import CheckDatabase
import SetPlatformfile
def check_and_hide():
CheckDatabase.db_download(root)
checkdb.pack_forget()
checkdb1.pack_forget()
root = tk.Tk()
checkdb = tk.Button(root, text="Check for new databases", command=check_and_hide)
checkdb.pack()
checkdb1 = tk.Button(root, text="No")
checkdb1.pack()
root.mainloop()
Here is the set_platform function called in the Checkdatabse file:
import tkinter as tk
import config
from tkinter import messagebox
def set_platform(root):
platform = tk.Label(root,text="'a'|Android -- 'i'|iOS: ")
platform.pack()
androidbutton=tk.Button(root,text="Android",command=renameplatformandroid)
iosbutton=tk.Button(root,text="iOS",command=renameplatformios)
androidbutton.pack()
iosbutton.pack()
def renameplatformandroid():
config.platform = 'android'
print(config.platform)
def renameplatformios():
config.platform = 'ios'
print(config.platform)
And cuz of my checkdatabase file is really really long, i'll just put a screen at the exact moment where set_platform is called (its called in the func signup which itself is directly called at the beginning of db_download) .
I hope my question is clear! Let me know if you need more details.

How to close a running windows OS program using a button?

I'm making a simple GUI using Python 3.7.3 and tkinter to open and close windows applications. I'm not able to find a way to close a running program using an onscreen button. I need the 'close' button to do something else as well, hence the simply using 'x' button (which is next to the minimize and maximize) won't work for my case.
from tkinter import *
import os, subprocess
root = Tk()
root.geometry("300x300")
def OpenCalc():
app1 = os.startfile("C:\Windows\System32\calc.exe")
def CloseCalc():
os.close(app1)
# or
# os.closefile("C:\Windows\System32\calc.exe")
b1=Button(root, text="Open Calc", command=OpenCalc).pack()
b2=Button(root, text="Close Calc", command=CloseCalc).pack()
root.mainloop()

Restart program tkinter

I am wondering on how I can create a restart button that once clicked, can restart the entire script. What I thought was that you destroy the window then un-destroy it but apparently there is no un-destroy function.
I found a way of doing it for a generic python program on this website: https://www.daniweb.com/programming/software-development/code/260268/restart-your-python-program. I wrote an example with a basic tkinter GUI to test it:
import sys
import os
from tkinter import Tk, Label, Button
def restart_program():
"""Restarts the current program.
Note: this function does not return. Any cleanup action (like
saving data) must be done before calling this function."""
python = sys.executable
os.execl(python, python, * sys.argv)
root = Tk()
Label(root, text="Hello World!").pack()
Button(root, text="Restart", command=restart_program).pack()
root.mainloop()
The following solution works as well but is quite harsh, i.e. the entire environment is lost.
# kills the whole application and starts a fresh one
def restart():
root.destroy()
root = Tk()
root.mainloop()
I would Like to Use this Function:-
First of All Import os Module
import os
Then Use this Code:-
# Restarts the Whole Window
def restart():
root.destroy()
os.startfile("main.py")
Or if You want no console behind then Simply Change the extension of the file to .pyw
And Run this Code:-
# Restarts the Whole Window
def restart():
root.destroy()
os.startfile("main.pyw")

Categories