tkinter dialog window not working inside while loop? - python-3.x

Apparently, tkinter doesn't allow you to use a while loop as it already runs its own loop so I need help on making my code work with the while loop. I believe it has something to do with "mainloop()" but I'm not sure how to use it.
Code below (works without loop):
while (1):
choice = input("Choose 1 to open dialog, 2 to end the program.\n")
if choice == "1":
from tkinter import *
root = Tk()
root.withdraw()
fileName = filedialog.askopenfilename(filetypes = ([("Text file","*.txt")]),title='Please select a text file')
file = open(fileName)
sentence = file.read()
file.close()
elif choice == "2":
break

Once you've witdrawn the window with root.witdraw() all the code associated with the root will not run, so you need to keep the window open while the user is opening dialog
You could stick a label on the window saying "Choose some dialogue to open", or as Bryan Oakley said you could use either command line or graphical interface
choice = ""
while choice != "2": # no need for brackets here
choice = input("Choose 1 to open dialog, 2 to end the program.\n")
if choice == "1":
from tkinter import *
root = Tk()
root.title("Choose dialog")
#root.withdraw() this causes the problem
fileName = filedialog.askopenfilename(filetypes = ([("Text file","*.txt")]),title='Please select a text file')
if fileName != "": # if they choose not to open a file
file = open(fileName)
sentence = file.read()
print(sentence)
file.close()
root.destroy() # destroys the window
I've tested it and this does work, hope this helps you

Related

How to remove the option to select what's inside a text widget, (not by using state = disabled)

I have tried using exportselection = False
this is the code I use to get the input from the user, if the user is highlighting the text widget (while inputting their answer), they are able to edit where the input get's printed
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
numb_of_times = 5
window.geometry('1920x1080')
window.configure(bg = 'blue')
input_board = tk.Text(window,state = "disabled")
input_board.pack()
input_board.place(x = 100,y = 40)
def send():
input_board.configure(state="normal")
input_board.insert(tk.INSERT, '%s\n' % user_input)
input_board.configure(state="disabled")
for i in range(numb_of_times):
user_input = input()
print(user_input)
send()
window.mainloop()
I have tried using exportselection = False
When the selection changes in the text widget, it emits a <<Selection>> event. You can bind to that event and remove the selection. This should prevent any text from being selected.
The selection is represented by the tag "sel", which you can pass to tag_remove.
The solution might look something like this:
def remove_selection(event):
event.widget.tag_remove("sel", "1.0", "end")
input_board.bind("<<Selection>>", remove_selection)

'Exception in tkinter callback' and '[Errno 24] Too many open files.'

quite new to Python and come across a problem that I'm struggling to diagnose.
I am working on a project involving a Tkinter menu and using an ADC connected to a potentiometer (which will hopefully be replaced by a muscle sensor once I've gotten the essential code working). I am using a raspberry Pi and breadboard for this, with my IDE as Thonny.
The imports are:
from time import sleep
import busio
import digitalio
import board
import adafruit_mcp3xxx.mcp3008 as ADC
from adafruit_mcp3xxx.analog_in import AnalogIn
import tkinter as tk
from tkinter import Menu
import easygui
import RPi.GPIO as GPIO
The overall menu and code works until I try to use the Run() function, which uses all of the files and compares AnalogIn to a threshold value previously found. When the Run button is clicked, it comes up with the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
File "/home/pi/Documents/NEA_Python/NEA2023.py", line 280, in Run
File "/usr/local/lib/python3.9/dist-packages/adafruit_mcp3xxx/analog_in.py", line 53, in value
File "/usr/local/lib/python3.9/dist-packages/adafruit_mcp3xxx/mcp3xxx.py", line 80, in read
File "/usr/local/lib/python3.9/dist-packages/adafruit_bus_device/spi_device.py", line 93, in __enter__
File "/usr/local/lib/python3.9/dist-packages/busio.py", line 335, in configure
File "/usr/local/lib/python3.9/dist-packages/adafruit_platformdetect/board.py", line 650, in any_embedded_linux
File "/usr/local/lib/python3.9/dist-packages/adafruit_platformdetect/board.py", line 532, in any_raspberry_pi
File "/usr/local/lib/python3.9/dist-packages/adafruit_platformdetect/board.py", line 205, in _pi_rev_code
File "/usr/local/lib/python3.9/dist-packages/adafruit_platformdetect/__init__.py", line 42, in get_cpuinfo_field
OSError: [Errno 24] Too many open files: '/proc/cpuinfo'
Run() Function code:
def Run():
threshold_valid = False
output_valid = False
#validity checks for all necessary fields
if threshold_valid == False:
thres = open('Threshold.txt', 'r')
threshold = thres.read()
if threshold == '':
print("Missing threshold voltage. Please refer to Main Menu/Options/Edit Muscle Data/Find threshold voltage")
else:
threshold_valid = True
if output_valid == False:
output = open('OutputOption.txt', 'r')
outputOption = output.read()
if outputOption == '':
print("Missing output option. Please refer to Main Menu/Options/Edit Muscle Data/Choose output/ in order to select output")
elif outputOption == 'notification':
with open('Message.txt', 'r') as message:
if message.read() == '':
print("Missing message to display. Please refer to Main Menu/Options/Edit Muscle Data/Choose output/Display message/")
else:
output_valid = True
message.close()
elif outputOption() == 'LED':
output_valid = True
else:
print("Something went wrong. Try deleting stored data at Main Menu/Options/Edit Muscle Data/Delete Data/ and try again")
while threshold_valid == True and output_valid == True:
spiBus = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
# create the chip select
chipSelect = digitalio.DigitalInOut(board.D22)
#creates the object for adc
adc = ADC.MCP3008(spiBus, chipSelect)
#creates analogue input channel on ADC's pin 0
analogueInChan = AnalogIn(adc, ADC.P0)
instantaneousAIn = analogueInChan.value
if instantaneousAIn> int(threshold):
if outputOption == 'LED':
output_flashLED()
elif outputOption == 'notification':
output_notification()
thres.close()
output.close()
All of the validity checks for this work fine, but it fails once it reaches the part inside the 'while threshold_valid == True and output_valid == True:' statement.
The menu is a menubar with cascade menus coming off of it.
The Tkinter menu code is:
#Root window
root = tk.Tk()
root.title("Main Menu")
#Creates a menubar
menubar = Menu(root, bg = 'powderblue', activebackground = '#84b7c4', tearoff = 0)
root.config(menu = menubar)
#Creates the main menu with the menubar as its parent window
#bg is the natural background colour, activebackground is the colour when the mouse hovers over it
main_menu = Menu(menubar, bg = 'lightcyan', activebackground = 'powderblue', tearoff = 0)
#Adds option to main_menu
main_menu.add_command(
label = "Instructions",
command = instructions
)
main_menu.add_command(
label= "Run",
command = Run
)
#Adds the main_menu as cascade to the menubar
menubar.add_cascade(
label = "Options",
menu = main_menu
)
#Creates menu muscleData_menu with main_menu as parent window
muscleData_menu = Menu(main_menu, tearoff = 0, bg = 'lightcyan', activebackground = 'powderblue')
#Adds option to muscleData_menu
muscleData_menu.add_command(
label = "Instructions",
command = instructions
)
muscleData_menu.add_command(
label = "Find threshold voltage",
command = findThreshold
)
#Creates menu output_menu with muscleData_menu as parent window
output_menu = Menu(muscleData_menu, tearoff = 0, bg = 'lightcyan', activebackground = 'powderblue')
#Adds option to output_menu
output_menu.add_command(
label = "Flash LED",
command = menuoption_flashLED
)
output_menu.add_command(
label = "Display message",
command = menuoption_notification
)
#Adds output_menu as cascade within muscleData_menu
muscleData_menu.add_cascade(
label = "Choose output",
menu = output_menu
)
#Creates menu deleteData_menu with muscleData_menu as parent window
deleteData_menu = Menu(muscleData_menu, tearoff = 0, bg = 'lightcyan', activebackground = 'powderblue')
#Adds option to deleteData_menu
deleteData_menu.add_command(
label = "Delete stored threshold voltage",
command = deleteThreshold
)
deleteData_menu.add_command(
label = "Delete stored output option",
command = deleteOutput
)
deleteData_menu.add_command(
label = "Delete stored notification message",
command = deleteMessage
)
deleteData_menu.add_command(
label = "Delete all stored data",
command = wipeData
)
#adds deleteData_menu as cascade to the muscleData_menu
muscleData_menu.add_cascade(
label = "Delete stored data",
menu = deleteData_menu
)
muscleData_menu.add_command(
label = "Run",
command = Run
)
#Adds muscleData_menu as cascade within main_menu
main_menu.add_cascade(
label = "Edit Muscle Data",
menu = muscleData_menu,
)
#Ends menu program
#root.destroy completely erases root/menu
main_menu.add_command(
label = "Quit",
command=root.destroy,
)
#Runs menu continuously until quit, awaiting user inputs
root.mainloop()
The actual menu works fine, the issue resides inside of the Run() function, however it is a Tkinter related issue. As I understand it, the menu works by the root looping continuously in the background whilst allowing other parts of the code to work, so this may be the issue but I'm not sure how to fix it. I have checked and in all instances of me opening the textfiles across the code, I have closed them again directly after. I have changed the ulimit and it continues to show the same error. I couldn't find a working solution in other stackoverflow answers and so believed it was an issue more localised to my exact code, but apologies if this is a repetition.
The full code is in this google doc, if anyone finds it relevant:
https://docs.google.com/document/d/1Oj5M6jSTXepXSBm9kjj4o_41AN4IhGcgc63iedZSMdQ/edit?usp=sharing
Can you limit the number of files that have to be open at the same time?
I was also reading from this thread,
IOError: [Errno 24] Too many open files:
Please have a look , it might help.
You need to use a with block to deal with your files, so they actually get closed and you won't run out of file descriptors.
Replace things like
thres = open('Threshold.txt', 'r')
threshold = thres.read()
with
with open('Threshold.txt', 'r') as f:
threshold = f.read()

Filedialog creating blank lines when opening file explorer

I noticed using filedialog.askdirectory() creates two blank lines when it opens file explorer (see picture below). I've been looking into this for weeks and I can't figure out why this is happening. Is there a way to prevent these blank lines from being created?
#!/usr/bin/python3
import tkinter
from tkinter import filedialog
export_file_path = ""
#Export path for output file
def export_path():
global export_file_path
print("Before askdirectory() is called")
is_empty = filedialog.askdirectory()
print("After askdirectory() is called")
if is_empty != '':
export_file_path = is_empty.replace('/', '\\')
export_path()
print(export_file_path)
input('PAUSE')

File dialog input with pyqt4 comes up without any font glyphs

I'm trying to create a GUI based application that will perform CRC match between a file copied to card and its source. I'm using PyQT4 from Cygwin with XWindows. When I open up the file dialog to browse to the file that was copied to the card, I donot see file system as one would expect to see when using QFileDialog.getOpenFileName. I see blank squares instead. I've a hunch that this might be due to the fact that it is trying to access a Unix based file system on a Windows machine. Your help is appreciated.
#!/usr/bin/env python
import zlib
import sys
from PyQt4.QtGui import *
def crc(fileName, count):
if count == 0:
return "%X"%(zlib.crc32(open(fileName,"rb").read()) & 0xFFFFFFFF)
else:
return "%X"%(zlib.crc32(open(fileName,"rb").read(count)) & 0xFFFFFFFF)
def compare(cr1, crc2):
if crc1 == crc2:
return "CRC Matched"
else :
return "CRC not Equal"
a = QApplication(sys.argv)
w = QWidget()
w.resize(320, 240)
w.setWindowTitle("CRC Check")
fileName = QFileDialog.getOpenFileName(w, 'Open File', '/')
crc1 = crc(fileName , count = 0)
print "Generated file CRC", crc1
crc2 = crc(fileName = "/dev/sdc", count = 5000000)
print "Copied file CRC", crc2
print compare(crc1, crc2)
w.show()
sys.exit(a.exec_())

tkinter need to click in shell to get gui fields to update

I have a tkinter gui with Python 3.4.2 in which there are various buttons, a user entry field and a text field. Everything works except that I appear to have to click in the Python shell (IDLE) and out of the gui to get fields to update in response to button presses. The updates are immediate when I click on the shell. I have copied this tkintergui from http://ubuntuforums.org/showthread.php?t=1156637 which gives the same problem on my Mac. Immediate update if IDLE shell clicked or very slow update in the GUI
#!/usr/bin/python
from tkinter import *
from tkinter.filedialog import *
class SimpleEdApp:
def __init__(self, parent=Tk()):
self.mainWindow = (parent)
self.mainWindow.title("Simple Editor")
self.mainWindow.resizable(0, 0)
self.make_mnu()
self.make_txt()
def make_txt(self):
self.text = Text(self.mainWindow, width = 80, height = 40, background = 'white')
self.scrollY = Scrollbar(self.mainWindow, orient = VERTICAL, command = self.text.yview, troughcolor = 'white')
self.text["yscrollcommand"] = self.scrollY.set
self.scrollY.pack(side = RIGHT, fill = Y)
self.text.pack(expand = TRUE, fill = BOTH)
def make_mnu(self):
self.menubar = Menu(self.mainWindow)
self.filemenu = Menu(self.menubar, tearoff = 0)
self.filemenu.add_command(label = "Open", command = self.file_open)
self.filemenu.add_command(label = "Save as...", command = self.file_save)
self.filemenu.add_separator()
self.filemenu.add_command(label = "Exit", command = self.mainWindow.destroy)
self.menubar.add_cascade(label = "File", menu = self.filemenu)
self.mainWindow.config(menu = self.menubar)
def file_open(self):
filename =askopenfilename(filetypes=[("pythonfiles","*.py"),("tclfiles","*.tcl"),("allfiles","*")])
f = open(filename, 'r')
data = f.read()
f.close()
self.text.delete(1.0, END)
self.text.insert(1.0, data)
def file_save(self):
filename =asksaveasfilename(filetypes=[("pythonfiles","*.py"),("tclfiles","*.tcl"),("allfiles","*")])
f = open(filename, 'w')
data = self.text.get(1.0, END)
f.write(data)
f.close()
app = SimpleEdApp()
app.mainWindow.mainloop()
Grateful for correct implementation
There is nothing wrong with your code. This looks to be a bug in IDLE.
In the comments you asked how to run the program outside of IDLE. To do that, open up a prompt and type the command python myfile.py, where myfile.py is the name of your python file (assuming "python" is in your PATH).
*note: depending on what is installed in your system, you may need to use python3 rather than python.

Resources