Entry widget inactive after messagebox.askquestion
"John McCabe" <[email protected]> Fri, 08 Jan 2021 14:42:24 +0000
| Newsgroups | gmane.comp.python.tkinter |
|---|---|
| Message-ID | <em4cbbe767-e62d-4880-a078-08d714ba47d3@kt-lap20-jm01> |
--===============7222930007056600878==
Content-Type: multipart/alternative;
boundary="------=_MBA77EFA12-4206-43FF-A3C0-E84E441E8637"
--------=_MBA77EFA12-4206-43FF-A3C0-E84E441E8637
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Hi,
I've raised this as a bug report at https://bugs.python.org/issue42867,=20
(based on the same issue having been reported in 2010, but closed with=20
no real resolution in 2014), but apparently they're busy so, in the=20
meantime...
I've built an application using tkinter (see below). I'm fairly new to=20
tkinter, despite having substantial software experience (33 years), so=20
the layout might be a bit odd/wrong, and the example obviously doesn't=20
follow PEP-8 guidelines, however...
Basically this application (which is a bit more than minimal, but should=20
be easy to follow) is designed to manage pairs of text values as JSON,=20
saving/loading from a file. When it starts, the user is asked if they=20
want to read in an existing file of data; if they select NO, a fairly=20
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=20
Entry widgets is added to the frame.
However (and this is the problem which appears to be identical to that=20
reported in Issue #9673 - at the Python Issue Tracker, in 2010), it is=20
not possible to set focus into either of the Entry widgets on Windows=20
10; there is no problem doing this on Ubuntu 16.04 (although I've only=20
got Python 3.5 on there)
If the "Save" button is then pressed, a message box pops up telling the=20
use that no changes have been saved. Once OK has been pressed on that,=20
it becomes possible to set focus into the Entry widgets.
One of the problems with Issue #9673 was that no 'minimal' example was=20
provided showing this behaviour, and the very minimal example given in=20
https://bugs.python.org/issue9673#msg218765 doesn't exhibit the problem,=20
hence the example below being a bit more than minimal, while still not=20
being particularly complicated.
The behaviour described here is identical on Windows 10 on Python 3.6,=20
3.8 and 3.9. If anyone can tell me whether there is an issue with how=20
I'm going about this, or a way round this problem while still retaining=20
the same functionality, I'd appreciate your help.
=3D=3D=3D=3D
#!/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 =3D master
self.grid()
self.originalJson =3D {}
self.inFileName =3D ""
self.leftRightEntries =3D []
self.fileDlgOpts =3D { "initialdir" : os.getcwd(),
"initialfile" : "file.json",
"filetypes" : (("JSON File",=20
"*.json"), ("All Files","*.*")),
"defaultextension" : '.json',
"title" : "Select A File" }
self.createWidgets()
def openInFile(self):
fileName =3D ""
reuse =3D tk.messagebox.askquestion("Use An Existing File", "Do=20
you want to load and use an existing file?")
if reuse =3D=3D "yes":
fileName =3D tk.filedialog.askopenfilename(**self.fileDlgOpts)
if fileName is not "":
try:
with open(fileName, 'r') as json_file:
self.originalJson =3D json.load(json_file)
json_file.close()
except Exception:
tk.messagebox.showerror("Use An Existing File",=20
"File could not be loaded; continuing without one.")
fileName =3D ""
else:
tk.messagebox.showwarning("Use An Existing File", "No=20
existing file specified; continuing without one.")
return fileName
def createWidgets(self):
self.inFileName =3D self.openInFile()
# We add the buttons to some huge numbered row because we might=20
want to insert more
# rows, and the layout manager will collapse everything in=20
between. Also we
# add these first because of the way the tab order is set up
self.addBtn =3D tk.Button(self.master, text =3D "+", command =3D=
=20
self.addNew)
self.addBtn.grid(row =3D 100, column =3D 0, sticky =3D tk.W)
# Save button; pretty self-explanatory
self.saveBtn =3D tk.Button(self.master, text =3D "Save", command =
=3D=20
self.save)
self.saveBtn.grid(row =3D 100, column =3D 2, sticky =3D tk.W)
# Quit button; pretty self-explanatory
self.quitBtn =3D tk.Button(self.master, text =3D "QUIT", fg =3D "r=
ed",=20
command =3D self.quit)
self.quitBtn.grid(row =3D 100, column =3D 3, sticky =3D tk.E)
# If there is original json, work through each key and put the=20
fields on the display
rowNum =3D 0
for leftText in sorted(self.originalJson.keys()):
self.insertRow(rowNum, leftText);
rowNum =3D rowNum + 1
self.nextEmptyRow =3D rowNum
self.redoPadding()
def redoPadding(self):
for child in self.master.winfo_children():
child.grid_configure(padx =3D 5, pady =3D 5)
def focusNextWidget(self, event):
event.widget.tk_focusNext().focus()
return("break")
def insertRow(self, rowNum, initialLeft =3D None):
tk.Label(self.master, height =3D 1, text =3D "Left: ").grid(row=
=3D=20
rowNum, column =3D 0, sticky =3D tk.W)
leftBox =3D tk.Entry(self.master, width =3D 20)
leftBox.grid(row =3D rowNum, column =3D 1, sticky =3D tk.W)
leftBox.bind("<Tab>", self.focusNextWidget)
if initialLeft is not None:
leftBox.insert(tk.END, initialLeft)
tk.Label(self.master, height =3D 1, text =3D "Right: ").grid(row =
=3D=20
rowNum, column =3D 2, sticky =3D tk.W)
rightBox =3D tk.Entry(self.master, width =3D 20)
rightBox.grid(row =3D rowNum, column =3D 3, sticky =3D 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 =3D self.nextEmptyRow + 1
self.redoPadding()
def getCurrent(self):
# Work through the rows and check stuff
current =3D {}
for (leftEntry, rightEntry) in self.leftRightEntries:
leftText =3D leftEntry.get()
rightText =3D rightEntry.get()
if leftText =3D=3D "" and rightText =3D=3D "":
pass
elif leftText =3D=3D "":
print("No leftText specified for rightText=20
[{}]".format(rightText))
elif rightText =3D=3D "":
print("No rightText specified for leftText=20
[{}]".format(leftText))
else:
print("lefText: {}, rightText: {}".format(leftText,=20
rightText))
current[leftText] =3D rightText
return current
def save(self):
# Get the current values, and then dump the new json to a file,=20
if it's changed!
finalResult =3D self.getCurrent()
if finalResult !=3D self.originalJson:
if self.inFileName =3D=3D "":
self.inFileName =3D=20
tk.filedialog.asksaveasfilename(**self.fileDlgOpts)
if self.inFileName !=3D "":
with open(self.inFileName, 'w') as json_file:
json.dump(finalResult, json_file, indent =3D 4)
self.originalJson =3D finalResult
tk.messagebox.showinfo("Save Data", "Data saved to=20
{}".format(self.inFileName))
else:
tk.messagebox.showwarning("Save Data", "Data has not=20
been saved; no file name was supplied!")
else:
tk.messagebox.showwarning("Save Data", "Data has not been=20
saved; there are no changes")
def quit(self):
# Deal with quitting when the file's been modified, check=20
original vs current JSON
reallyQuit =3D True
finalResult =3D self.getCurrent()
if finalResult !=3D self.originalJson:
answer =3D tk.messagebox.askquestion("Quit", "Data has=20
changed; do you really want to quit?", icon =3D "warning")
if answer !=3D "yes":
reallyQuit =3D False
if reallyQuit:
self.master.destroy()
if __name__ =3D=3D "__main__":
root =3D tk.Tk()
root.title("Inactive Entry Example")
app =3D Application(root)
root.protocol("WM_DELETE_WINDOW", app.quit)
app.mainloop()
--------=_MBA77EFA12-4206-43FF-A3C0-E84E441E8637
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
<html><head>
<style id=3D"css_styles">=20
blockquote.cite { margin-left: 5px; margin-right: 0px; padding-left: 10px;=
padding-right:0px; border-left: 1px solid #cccccc }
blockquote.cite2 {margin-left: 5px; margin-right: 0px; padding-left: 10px;=
padding-right:0px; border-left: 1px solid #cccccc; margin-top: 3px; padding=
-top: 0px; }
a img { border: 0px; }
li[style=3D'text-align: center;'], li[style=3D'text-align: center; '], li[s=
tyle=3D'text-align: right;'], li[style=3D'text-align: right; '] { list-sty=
le-position: inside;}
body { font-family: Segoe UI; font-size: 12pt; }=20
.quote { margin-left: 1em; margin-right: 1em; border-left: 5px #ebebeb soli=
d; padding-left: 0.3em; }
</style>
</head>
<body>Hi,<div><br /></div><div>I've raised this as a bug report at=C2=A0<a=
href=3D"https://bugs.python.org/issue42867" style=3D"font-size: 12pt;">http=
s://bugs.python.org/issue42867</a><span>, (based on the same issue having b=
een reported in 2010, but closed with no real resolution in 2014), but appa=
rently they're busy so, in the meantime...</span></div><div><br /></div><di=
v>I've built an application using tkinter (see below). I'm fairly new to tk=
inter, despite having substantial software experience (33 years), so the la=
yout might be a bit odd/wrong, and the example obviously doesn't follow PEP=
-8 guidelines, however...<br /><br />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 "Qu=
it" is displayed.<br /><br />At this point, if "+" is pressed, a new row wi=
th two labels and two Entry widgets is added to the frame.<br /><br />Howev=
er (and this is the problem which appears to be identical to that reported=
in Issue #9673 - at the Python Issue Tracker, in 2010), it is not possible=
to set focus into either of the Entry widgets on Windows 10; there is no pr=
oblem doing this on Ubuntu 16.04 (although I've only got Python 3.5 on ther=
e)<br /><br />If the "Save" button is then pressed, a message box pops up t=
elling 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.<br /><br />=
One of the problems with Issue #9673 was that no 'minimal' example was prov=
ided showing this behaviour, and the very minimal example given in <a href=
=3D"https://bugs.python.org/issue9673#msg218765">https://bugs.python.org/is=
sue9673#msg218765</a> doesn't exhibit the problem, hence the example below=
being a bit more than minimal, while still not being particularly complicat=
ed.<br /><br />The behaviour described here is identical on Windows 10 on P=
ython 3.6, 3.8 and 3.9. If anyone can tell me whether there is an issue wit=
h how I'm going about this, or a way round this problem while still retaini=
ng the same functionality, I'd appreciate your help.</div><div><br /></div>=
<div>=3D=3D=3D=3D<br />#!/usr/bin/python3<br /><br />import os<br />import=
tkinter as tk<br />from tkinter import filedialog, messagebox<br />import j=
son<br /><br />class Application(tk.Frame):<br /><br />=C2=A0 =C2=A0 def __=
init__(self, master):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 super().__init_=
_(master)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.master =3D master<br /=
>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.grid()<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 self.originalJson =3D {}<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 se=
lf.inFileName =3D ""<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.leftRightEn=
tries =3D []<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.fileDlgOpts =3D { "=
initialdir"=C2=A0 =C2=A0=C2=A0 =C2=A0 : os.getcwd(),<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 "initialfile"=C2=A0 =C2=A0=C2=A0 =C2=A0: "=
file.json",<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 "filetype=
s"=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 : (("JSON File", "*.json"), ("All Files"=
,"*.*")),<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 "defaulte=
xtension" : '.json',<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=
"title"=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0: "Select A File=
" }<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.createWidgets()<br /><br />=
=C2=A0 =C2=A0 def openInFile(self):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 f=
ileName =3D ""<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 reuse =3D tk.messagebo=
x.askquestion("Use An Existing File", "Do you want to load and use an exist=
ing file?")<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if reuse =3D=3D "yes":<br =
/>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0fileName =3D tk.file=
dialog.askopenfilename(**self.fileDlgOpts)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 =C2=A0if fileName is not "":<br />=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 try:<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 with o=
pen(fileName, 'r') as json_file:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0self.or=
iginalJson =3D json.load(json_file)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0jso=
n_file.close()<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 =C2=A0 except Exception:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 tk.messagebox.showerror("Use=
An Existing File", "File could not be loaded; continuing without one.")<br=
/>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 fileName =3D ""<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=
=C2=A0 =C2=A0else:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0 tk.messagebox.showwarning("Use An Existing File", "No exis=
ting file specified; continuing without one.")<br /><br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 return fileName<br /><br />=C2=A0 =C2=A0 def createWidgets=
(self):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.inFileName =3D self.open=
InFile()<br /><br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 # We add the buttons t=
o some huge numbered row because we might want to insert more<br />=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 # rows, and the layout manager will collapse eve=
rything in between. Also we<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 # add the=
se first because of the way the tab order is set up<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 self.addBtn =3D tk.Button(self.master, text =3D "+", comma=
nd =3D self.addNew)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.addBtn.grid(=
row =3D 100, column =3D 0, sticky =3D tk.W)<br /><br />=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 # Save button; pretty self-explanatory<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 self.saveBtn =3D tk.Button(self.master, text =3D "Save", c=
ommand =3D self.save)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.saveBtn.gr=
id(row =3D 100, column =3D 2, sticky =3D tk.W)<br /><br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 # Quit button; pretty self-explanatory<br />=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 self.quitBtn =3D tk.Button(self.master, text =3D "QUIT"=
, fg =3D "red", command =3D self.quit)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 self.quitBtn.grid(row =3D 100, column =3D 3, sticky =3D tk.E)<br /><br=
/>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 # If there is original json, work throug=
h each key and put the fields on the display<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 rowNum =3D 0<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 for leftText i=
n sorted(self.originalJson.keys()):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0self.insertRow(rowNum, leftText);<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0rowNum =3D rowNum + 1<br /><br />=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 self.nextEmptyRow =3D rowNum<br /><br />=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 self.redoPadding()<br /><br />=C2=A0 =C2=A0 def=
redoPadding(self):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 for child in self.=
master.winfo_children():<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0child.grid_configure(padx =3D 5, pady =3D 5)<br /><br />=C2=A0 =C2=
=A0 def focusNextWidget(self, event):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
event.widget.tk_focusNext().focus()<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=
return("break")<br /><br />=C2=A0 =C2=A0 def insertRow(self, rowNum, initia=
lLeft =3D None):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 tk.Label(self.master=
, height =3D 1, text =3D "Left: ").grid(row =3D rowNum, column =3D 0, stick=
y =3D tk.W)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 leftBox =3D tk.Entry(self=
.master, width =3D 20)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 leftBox.grid(r=
ow =3D rowNum, column =3D 1, sticky =3D tk.W)<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 leftBox.bind("<Tab>", self.focusNextWidget)<br />=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 if initialLeft is not None:<br />=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0leftBox.insert(tk.END, initialLeft)<br />=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 tk.Label(self.master, height =3D 1, text =
=3D "Right: ").grid(row =3D rowNum, column =3D 2, sticky =3D tk.W)<br />=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 rightBox =3D tk.Entry(self.master, width =
=3D 20)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 rightBox.grid(row =3D rowNum=
, column =3D 3, sticky =3D tk.W)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 righ=
tBox.bind("<Tab>", self.focusNextWidget)<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 if initialLeft is not None:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0rightBox.insert(tk.END, initialLeft)<br />=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 self.leftRightEntries.append((leftBox, rightBox))<br />=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 leftBox.focus_set()<br /><br />=C2=A0 =C2=
=A0 def addNew(self):<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 # Add a new row =
before the button<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.insertRow(sel=
f.nextEmptyRow)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.nextEmptyRow =3D =
self.nextEmptyRow + 1<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 self.redoPaddi=
ng()<br /><br />=C2=A0 =C2=A0 def getCurrent(self):<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 # Work through the rows and check stuff<br />=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 current =3D {}<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 fo=
r (leftEntry, rightEntry) in self.leftRightEntries:<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0leftText =3D leftEntry.get()<br />=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0rightText =3D rightEntry.g=
et()<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0if leftText =
=3D=3D "" and rightText =3D=3D "":<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 pass<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0elif leftText =3D=3D "":<br />=C2=A0 =C2=A0=C2=A0=
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 print("No leftText specified fo=
r rightText [{}]".format(rightText))<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0elif rightText =3D=3D "":<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 print("No rightText specified fo=
r leftText [{}]".format(leftText))<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=
=C2=A0=C2=A0 =C2=A0else:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0 print("lefText: {}, rightText: {}".format(leftText, ri=
ghtText))<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0 current[leftText] =3D rightText<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 return current<br /><br />=C2=A0 =C2=A0 def save(self):<br />=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 # Get the current values, and then dump the new json =
to a file, if it's changed!<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 finalRes=
ult =3D self.getCurrent()<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if finalRes=
ult !=3D self.originalJson:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 =C2=A0if self.inFileName =3D=3D "":<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 self.inFileName =3D tk.filedialog.asks=
aveasfilename(**self.fileDlgOpts)<br /><br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0if self.inFileName !=3D "":<br />=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 with open(self.inFileName, '=
w') as json_file:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 json.dump(finalResult, json_file, indent =
=3D 4)<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 self.originalJson =3D finalResult<br />=C2=A0 =C2=A0=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 tk.messagebox.showinfo=
("Save Data", "Data saved to {}".format(self.inFileName))<br />=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0else:<br />=C2=A0 =C2=A0=C2=A0=
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 tk.messagebox.showwarning("Save =
Data", "Data has not been saved; no file name was supplied!")<br />=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 else:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0tk.messagebox.showwarning("Save Data", "Data has not been s=
aved; there are no changes")<br /><br />=C2=A0 =C2=A0 def quit(self):<br />=
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 # Deal with quitting when the file's been=
modified, check original vs current JSON<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=
=A0 reallyQuit =3D True<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 finalResult =
=3D self.getCurrent()<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if finalResult =
!=3D self.originalJson:<br />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =
=C2=A0answer =3D tk.messagebox.askquestion("Quit", "Data has changed; do y=
ou really want to quit?", icon =3D "warning")<br />=C2=A0 =C2=A0=C2=A0 =C2=
=A0=C2=A0 =C2=A0=C2=A0 =C2=A0if answer !=3D "yes":<br />=C2=A0 =C2=A0=C2=A0 =
=C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0 reallyQuit =3D False<br /><b=
r />=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if reallyQuit:<br />=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 =C2=A0self.master.destroy()<br /><br />if __n=
ame__ =3D=3D "__main__":<br />=C2=A0 =C2=A0 root =3D tk.Tk()<br />=C2=A0=
=C2=A0 root.title("Inactive Entry Example")<br />=C2=A0 =C2=A0 app =3D Applic=
ation(root)<br />=C2=A0 =C2=A0 root.protocol("WM_DELETE_WINDOW", app.quit)<=
br />=C2=A0 =C2=A0 app.mainloop()<br /></div></body></html>
--------=_MBA77EFA12-4206-43FF-A3C0-E84E441E8637--
--===============7222930007056600878==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Tkinter-discuss mailing list
[email protected]
https://mail.python.org/mailman/listinfo/tkinter-discuss
--===============7222930007056600878==--