Terminating an exe built from a GUI in python from Background Processes - user-interface

I created a simple GUI in python 3.4 using tkinter 8.5. I used cx_freeze to build an exe from this GUI. Now when I run this exe, sometimes I notice that the program still shows under 'Background Processes' in Task Manager even after I terminate it using a Quit button or using the close button in the window.
The GUI works like this: You select a file type from a drop down list, read the file using a command button and save it as a separate file. Now this problem happens only if I close the GUI after using it. If I simply open the GUI and close it using the Quit button or close button, it does not stay as a background process.
Is it normal for it to behave like this? If not what can I do to terminate it properly?
The simplified code for the GUI is given below. The function 'fileselect' calls functions from the module 'dataselect'. If needed, I will provide the code for the 'dataselect' module also.
from dataselect import *
from openpyxl import Workbook
from tkinter import *
from tkinter import ttk, filedialog
root = Tk()
root.title("Select Data File")
# Actual File Selection based on Combobox Selection
def fileselect():
file_type = filetype.get()
if file_type == ".txt":
text = selecttxt()
textfile = filedialog.asksaveasfile(mode='w', defaultextension=".txt")
for line in text:
for number in line:
textfile.write(str(number)+" ")
textfile.write('\n')
elif file_type == ".xlsx":
excel = selectxlsx()
excelfile = filedialog.asksaveasfile(mode='w', defaultextension=".xlsx")
excelfilename = excelfile.name
excelbook = Workbook()
excelsheet = excelbook.active
rows = 0
for excel_row in excel:
cols = 0
for excel_cell in excel_row:
excelsheet.cell(row=rows, column=cols).value = excel[rows][cols]
cols += 1
rows += 1
excelbook.save(excelfilename)
def quit():
global root
root.destroy()
# Select the File Type to be opened (.txt or .xlsx for now)
ttk.Label(root, text="Please select the file type").grid(column=2, row=1)
filetype = StringVar()
sel_type = ttk.Combobox(root,values=('.txt','.xlsx'),textvariable=filetype)
sel_type.grid(column=2,row=2,sticky=E)
# Command Button for Opening File
cb_open = ttk.Button(root, text="Select File", command=fileselect)
cb_open.grid(column=2, row=3)
# Command Button for Quitting GUI
cb_quit = ttk.Button(root, text="Quit", command=quit)
cb_quit.grid(column=1, row=3)
root.mainloop()

There are two things you need to change:
1) Add sys.exit() to your quit method
def quit():
root.quit
root.destroy
sys.exit()
2) Add protocol to your root
root.protocol("WM_DELETE_WINDOW", quit)
Finally, don't forget to import sys.

Related

My toplevel window in tkinter is no longer being destroyed. It was working fine until I tried changing other aspects of my function

I'm trying to get a popup window to display random text and a picture every time a button is pressed in tkinter. My original code was going to use an if/elif statement to do this. It worked as intended but I thought it might be easier to pair the data in a dictionary since there would be 50 elif statements otherwise (is it frowned upon to use so many? I actually found it easier to read).I was able to get this working but now the toplevel window in tkinter is not being destroyed like it was in the original function. A new Label is just being created on top of it and I can't figure out why. The function code is below. Thanks in advance, any help would be appreciated!
def Add_Gemstone2():
global Addstone
#destroy the previous window if there is one.
try:
AddStone.destroy()
except(AttributeError, NameError):
pass
#create the window.
AddStone=Toplevel()
AddStone.configure(bg='White', height=200, width=325)
AddStone.geometry('325x180+10+100')
# add gemstones to list from file.
gem_stones = open('gemstones.txt')
all_gem_stones = gem_stones.readlines()
gemstones = []
for i in all_gem_stones:
gemstones.append(i.rstrip())
# Add pictures to list.
path = r'C:\Users\Slack\Desktop\PYTHON WORKS\PYTHON GUI PROJECT\gems'
gempictures = []
# r=root, d=directories, f = files
for r,d,f in os.walk(path):
for file in f:
if '.gif' in file:
gempictures.append(os.path.join(r, file))
#create dictionary from lists.
gemdiction = dict(zip(gemstones, gempictures))
key, val = random.choice(list(gemdiction.items()))
# create the labels.
glbl1 = Label(AddStone, text=key, bg='gold', wraplength=300)
glbl1.pack()
image = ImageTk.PhotoImage(Image.open(val))
glbl2 = Label(AddStone, image=image)
glbl2.image = image
glbl2.pack()

I am using Pywinauto GUI automation & facing errors with controls on the Adobe Acrobat menus or its submenus

Below is a snippet of the code & the error message.
Any help would be highly appreciated.
pdf_file = "C:\\Users\\Test1.PDF"
from pywinauto.application import Application
app = Application(backend='uia').start(cmd_line=u"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe " +pdf_file)
appw = app.connect(title="Adobe Acrobat Reader DC").window(class_name='AcrobatSDIWindow')
app_menu = appw.child_window(title="Application", control_type="MenuBar")
app_menu.child_window(title="File").expand()
file1 = appw.child_window(title="File", control_type="Menu")
file1.child_window(title="Print...").click_input()
Error message:
raise ElementNotFoundError(kwargs)
pywinauto.findwindows.ElementNotFoundError: {'title': 'Adobe Acrobat Reader DC', 'backend': 'uia', 'visible_only': False}
Process finished with exit code 1
Try below code
'''
import time
from pywinauto.application import Application
pdf_file = r"C:\Users\Test1.PDF"
acrobat_path = r"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
wpfApp = Application(backend=u'uia').start(cmd_line = acrobat_path + ' ' + pdf_file)
time.sleep(1)
wpfApp = Application(backend=u'uia').connect(path=acrobat_path) # Reconnect
wind = wpfApp.windows()
title = wind[0].get_properties()[u'texts'][0] # retrive Title of window
app_wind = wpfApp.window(title = title) #get access tp main window
app_menu = app_wind.children(title="Application", control_type="MenuBar") #get access to app menu
app_menu[0].children(title="File")[0].click_input() #click on File Menu
file_menu = app_wind.children(title="File", control_type="Menu") #get access to file menu window
file_menu[0].children(title="Print... Ctrl+P")[0].click_input() #click on Print
time.sleep(5) #wait for print dialog to open
'''

Tkinter windows not responding when using update() in a while loop

I am a beginner in programming. I do this as hobby and to improve my productivity at work.
I am writing a program to automatically paste the clipboard to a Tkinter entry whenever a user copy a line of text.
I use a while loop to detect if there is a change in the current clipboard, then paste the newly copied clipboard text to the Tkinter entry.
The GUI update perfectly when I copy a new line of text.
However the GUI is not responding and I can't click the TK entry to type something that I want.
FYI I am using Python 3.5 software.
Thanks in advance.
My code:
from tkinter import *
import pyperclip
#initial placeholder
#----------------------
old_clipboard = ' '
new_clipboard = ' '
#The GUI
#--------
root = Tk()
textvar = StringVar()
label1 = Label(root, text='Clipboard')
entry1 = Entry(root, textvariable=textvar)
label1.grid(row=0, sticky=E)
entry1.grid(row=0, column=1)
#while loop
#-----------
while(True): #first while loop: keep monitoring for new clipboard
while(old_clipboard == new_clipboard): #second while loop: check if old_clipboard is equal to the new_clipboard
new_clipboard = pyperclip.paste() #get the current clipboard
print('\nold clipboard pre copy: ' + old_clipboard)
old_clipboard = new_clipboard #assign new_clipboard to old_clipboard
print('current clipboard post copy: ' + old_clipboard)
print('\ncontinuing the loop...')
textvar.set(old_clipboard) #set the current clipboard to GUI entry
root.update() #update the GUI
root.mainloop()
You need to put your while loop in a def, then start it in a new thread, that way your gui won´t freeze.
eg:
import threading
def clipboardcheck():
#Your while loop stuff
class clipboardthread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
clipboardcheck()
clipboardthread.daemon=True #Otherwise you will have issues closing your program
clipboardthread().start()

PyQt QFileDialog getOpenFileName not working from command line (windows)

I'm trying to make a gui (Qt Designer) to import an excel file and display the data in the gui.
The script works fine when I run it from within my IDE (Spyder), but if I run it from the command window or by opening the python file from windows explorer, the import function does not work. (The gui starts up fine but when the import button is pressed and the file is selected, nothing happens and no error is produced. When running from Spyder, the data is imported and displayed in the gui as expected).
If I pre-select the file location (commented out in the code below), then the script works fine from the command line or by clicking from explorer.
Thanks for any help!
Python 2.7 (Anaconda), Windows 10, PyQt4
import sys
from PyQt4 import QtGui
from excel_import_gui import Ui_MainWindow
import xlrd
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setupSignals()
def set_import_data(self,data_to_import,table_to_change):
for row in range(len(data_to_import)):
for col in range(len(data_to_import[0])):
table_to_change.setRowCount(len(data_to_import))
table_to_change.setColumnCount(len(data_to_import[0]))
item = data_to_import[row][col]
table_to_change.setItem(row,col,QtGui.QTableWidgetItem(str(item)))
def setupSignals(self):
self.ui.importData_btn.clicked.connect(self.select_file)
def select_file(self):
excel_file = QtGui.QFileDialog.getOpenFileName(self,
"Select Excel file to import","","Excel (*.xls *.xlsx)")
# excel_file = "C:/Users/Ben/Work/Python tests/Qt GUIs/Excel_import_GUI/fish_test.xlsx"
if excel_file:
open_excel_file = xlrd.open_workbook(excel_file)
self.start_import_data(open_excel_file)
def start_import_data(self, workbook):
#import data from excel file
workbook_data = []
for sheetNum in range (workbook.nsheets):
worksheet = workbook.sheet_by_index(sheetNum)
workbook_data.append([[worksheet.cell_value(row,col) for col in range (worksheet.ncols)] for row in range(worksheet.nrows)])
# Set each worksheet of workbook_data to each tab in GUI widget
self.set_import_data(workbook_data[0],self.ui.fish_table)
self.set_import_data(workbook_data[1],self.ui.boats_table)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
Well I found a solution myself by converting the excel_file variable to a string.
excel_file = str(QtGui.QFileDialog.getOpenFileName(self, "Select Excel file to import","","Excel (*.xls *.xlsx)"))

PyQt getOpenFileName default directory

I'm using Qt.Gui.QFileDialog.getOpenFileName method to open a file. If I set the default file directory to "/Users/me/Documents/data/2013/today/" the dialog box opens to "/Users/me/Documents/data/2013/" with the "today" folder selected. How do I get the the correct default folder to be opened in the window?
fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file', "/Users/me/Documents/data/2012/20121102/images/",'*.npy')
Opens a dialog box in /Users/me/Documents/data/2012/20121102. I want the window to open in /Users/me/Documents/data/2012/20121102/images/
The most probable reason is that the file doesn't exist at the time you are requesting it be opened. For opening folders use QtGui.QFileDialog.getExistingDirectory:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButtonOpen = QtGui.QPushButton(self)
self.pushButtonOpen.setText("Open Folder")
self.pushButtonOpen.clicked.connect(self.on_pushButtonOpen_clicked)
self.layoutHorizontal = QtGui.QHBoxLayout(self)
self.layoutHorizontal.addWidget(self.pushButtonOpen)
#QtCore.pyqtSlot()
def on_pushButtonOpen_clicked(self):
folderName = QtGui.QFileDialog.getExistingDirectory(
self, "Open Directory",
"/path/to/folder",
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontResolveSymlinks,
)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
For someone's information (even though 8 years passed)
You could pass the directory argument to getOpenFileName for the default folder in PyQt5.

Resources