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("&lt;Tab&gt;", 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("&lt;Tab&gt;", 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==--