[New-bugs-announce] [issue42867] Entry Widget not editable on Windows 10, but is on Linux Ubuntu 16.04
John McCabe
report at bugs.python.org
Fri Jan 8 07:46:13 EST 2021
New submission from John McCabe <john at mccabe.org.uk>:
I've built an application using tkinter (see below). I'm fairly new to tkinter, despite having substantial software experience (33 years), so the layout might be a bit odd/wrong, and the example obviously doesn't follow PEP-8 guidelines, however...
Basically this application (which is a bit more than minimal, but should be easy to follow) is designed to manage pairs of text values as JSON, saving/loading from a file. When it starts, the user is asked if they want to read in an existing file of data; if they select NO, a fairly empty frame with 3 buttons showing "+", "Save" and "Quit" is displayed.
At this point, if "+" is pressed, a new row with two labels and two Entry widgets is added to the frame.
However (and this is the problem which appears to be identical to that reported in Issue #9673), it is not possible to set focus into either of the Entry widgets on Windows 10; there is no problem doing this on Ubuntu 16.04 (although I've only got Python 3.5 on there)
If the "Save" button is then pressed, a message box pops up telling the use that no changes have been saved. Once OK has been pressed on that, it becomes possible to set focus into the Entry widgets.
One of the problems with Issue #9673 was that no 'minimal' example was provided showing this behaviour, and the very minimal example given in https://bugs.python.org/issue9673#msg218765 doesn't exhibit the problem, hence the example below being a bit more than minimal, while still not being particularly complicated.
====
#!/usr/bin/python3
import os
import tkinter as tk
from tkinter import filedialog, messagebox
import json
class Application(tk.Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.grid()
self.originalJson = {}
self.inFileName = ""
self.leftRightEntries = []
self.fileDlgOpts = { "initialdir" : os.getcwd(),
"initialfile" : "file.json",
"filetypes" : (("JSON File", "*.json"), ("All Files","*.*")),
"defaultextension" : '.json',
"title" : "Select A File" }
self.createWidgets()
def openInFile(self):
fileName = ""
reuse = tk.messagebox.askquestion("Use An Existing File", "Do you want to load and use an existing file?")
if reuse == "yes":
fileName = tk.filedialog.askopenfilename(**self.fileDlgOpts)
if fileName is not "":
try:
with open(fileName, 'r') as json_file:
self.originalJson = json.load(json_file)
json_file.close()
except Exception:
tk.messagebox.showerror("Use An Existing File", "File could not be loaded; continuing without one.")
fileName = ""
else:
tk.messagebox.showwarning("Use An Existing File", "No existing file specified; continuing without one.")
return fileName
def createWidgets(self):
self.inFileName = self.openInFile()
# We add the buttons to some huge numbered row because we might want to insert more
# rows, and the layout manager will collapse everything in between. Also we
# add these first because of the way the tab order is set up
self.addBtn = tk.Button(self.master, text = "+", command = self.addNew)
self.addBtn.grid(row = 100, column = 0, sticky = tk.W)
# Save button; pretty self-explanatory
self.saveBtn = tk.Button(self.master, text = "Save", command = self.save)
self.saveBtn.grid(row = 100, column = 2, sticky = tk.W)
# Quit button; pretty self-explanatory
self.quitBtn = tk.Button(self.master, text = "QUIT", fg = "red", command = self.quit)
self.quitBtn.grid(row = 100, column = 3, sticky = tk.E)
# If there is original json, work through each key and put the fields on the display
rowNum = 0
for leftText in sorted(self.originalJson.keys()):
self.insertRow(rowNum, leftText);
rowNum = rowNum + 1
self.nextEmptyRow = rowNum
self.redoPadding()
def redoPadding(self):
for child in self.master.winfo_children():
child.grid_configure(padx = 5, pady = 5)
def focusNextWidget(self, event):
event.widget.tk_focusNext().focus()
return("break")
def insertRow(self, rowNum, initialLeft = None):
tk.Label(self.master, height = 1, text = "Left: ").grid(row = rowNum, column = 0, sticky = tk.W)
leftBox = tk.Entry(self.master, width = 20)
leftBox.grid(row = rowNum, column = 1, sticky = tk.W)
leftBox.bind("<Tab>", self.focusNextWidget)
if initialLeft is not None:
leftBox.insert(tk.END, initialLeft)
tk.Label(self.master, height = 1, text = "Right: ").grid(row = rowNum, column = 2, sticky = tk.W)
rightBox = tk.Entry(self.master, width = 20)
rightBox.grid(row = rowNum, column = 3, sticky = tk.W)
rightBox.bind("<Tab>", self.focusNextWidget)
if initialLeft is not None:
rightBox.insert(tk.END, initialLeft)
self.leftRightEntries.append((leftBox, rightBox))
leftBox.focus_set()
def addNew(self):
# Add a new row before the button
self.insertRow(self.nextEmptyRow)
self.nextEmptyRow = self.nextEmptyRow + 1
self.redoPadding()
def getCurrent(self):
# Work through the rows and check stuff
current = {}
for (leftEntry, rightEntry) in self.leftRightEntries:
leftText = leftEntry.get()
rightText = rightEntry.get()
if leftText == "" and rightText == "":
pass
elif leftText == "":
print("No leftText specified for rightText [{}]".format(rightText))
elif rightText == "":
print("No rightText specified for leftText [{}]".format(leftText))
else:
print("lefText: {}, rightText: {}".format(leftText, rightText))
current[leftText] = rightText
return current
def save(self):
# Get the current values, and then dump the new json to a file, if it's changed!
finalResult = self.getCurrent()
if finalResult != self.originalJson:
if self.inFileName == "":
self.inFileName = tk.filedialog.asksaveasfilename(**self.fileDlgOpts)
if self.inFileName != "":
with open(self.inFileName, 'w') as json_file:
json.dump(finalResult, json_file, indent = 4)
self.originalJson = finalResult
tk.messagebox.showinfo("Save Data", "Data saved to {}".format(self.inFileName))
else:
tk.messagebox.showwarning("Save Data", "Data has not been saved; no file name was supplied!")
else:
tk.messagebox.showwarning("Save Data", "Data has not been saved; there are no changes")
def quit(self):
# Deal with quitting when the file's been modified, check original vs current JSON
reallyQuit = True
finalResult = self.getCurrent()
if finalResult != self.originalJson:
answer = tk.messagebox.askquestion("Quit", "Data has changed; do you really want to quit?", icon = "warning")
if answer != "yes":
reallyQuit = False
if reallyQuit:
self.master.destroy()
if __name__ == "__main__":
root = tk.Tk()
root.title("Inactive Entry Example")
app = Application(root)
root.protocol("WM_DELETE_WINDOW", app.quit)
app.mainloop()
----------
components: Tkinter
messages: 384655
nosy: cosimo193
priority: normal
severity: normal
status: open
title: Entry Widget not editable on Windows 10, but is on Linux Ubuntu 16.04
type: behavior
versions: Python 3.6
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue42867>
_______________________________________
More information about the New-bugs-announce
mailing list