From Vasilis.Vlachoudis at cern.ch Mon Jan 4 04:09:48 2021 From: Vasilis.Vlachoudis at cern.ch (Vasilis Vlachoudis) Date: Mon, 4 Jan 2021 09:09:48 +0000 Subject: [Tkinter-discuss] Unicode range Message-ID: <0BC70B5D93E054469872FFD0FE07220E0312E08B77@CERNXCHG51.cern.ch> Hi all, how can I "replace/strip" unicode characters that are out of the accepted tk range before inserting them to Text()? File "/usr/lib/python3.6/tkinter/__init__.py", line 3272, in insert self.tk.call((self._w, 'insert', index, chars) + args) _tkinter.TclError: character U+1c784 is above the range (U+0000-U+FFFF) allowed by Tcl Vasilis -------------- next part -------------- An HTML attachment was scrubbed... URL: From namnguyen at google.com Mon Jan 4 12:39:14 2021 From: namnguyen at google.com (Nam Nguyen) Date: Mon, 4 Jan 2021 09:39:14 -0800 Subject: [Tkinter-discuss] Unicode range In-Reply-To: <0BC70B5D93E054469872FFD0FE07220E0312E08B77@CERNXCHG51.cern.ch> References: <0BC70B5D93E054469872FFD0FE07220E0312E08B77@CERNXCHG51.cern.ch> Message-ID: Hi Vasilis, Perhaps by removing characters that are outside of that range? The error message gives you a range, from 0 to 65535. So this line might do. s = ''.join(c for c in s if 0 < ord(c) < 65535) Cheers, Nam On Mon, Jan 4, 2021 at 1:25 AM Vasilis Vlachoudis < Vasilis.Vlachoudis at cern.ch> wrote: > Hi all, > > how can I "replace/strip" unicode characters that are out of the accepted > tk range before inserting them to Text()? > > File "/usr/lib/python3.6/tkinter/__init__.py", line 3272, in insert > self.tk.call((self._w, 'insert', index, chars) + args) > _tkinter.TclError: character U+1c784 is above the range (U+0000-U+FFFF) > allowed by Tcl > > Vasilis > _______________________________________________ > Tkinter-discuss mailing list > Tkinter-discuss at python.org > https://mail.python.org/mailman/listinfo/tkinter-discuss > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4002 bytes Desc: S/MIME Cryptographic Signature URL: From Vasilis.Vlachoudis at cern.ch Mon Jan 4 14:08:56 2021 From: Vasilis.Vlachoudis at cern.ch (Vasilis Vlachoudis) Date: Mon, 4 Jan 2021 19:08:56 +0000 Subject: [Tkinter-discuss] Unicode range In-Reply-To: References: <0BC70B5D93E054469872FFD0FE07220E0312E08B77@CERNXCHG51.cern.ch>, Message-ID: <0BC70B5D93E054469872FFD0FE07220E0312E09E75@CERNXCHG51.cern.ch> Many thanks Nam, I followed your suggestion and modified a bit as _UNICODE_RANGE = re.compile(u'[^\u0000-\uFFFF]', re.UNICODE) ... except tk.TclError: # when it fails try to remove unicode outside the accepted range self.text.insert("0.0", _UNICODE_RANGE.sub("?",log.messages)) which is faster Vasilis ________________________________ From: Nam Nguyen [namnguyen at google.com] Sent: Monday, January 04, 2021 18:39 To: Vasilis Vlachoudis Cc: tkinter-discuss at python.org Subject: Re: [Tkinter-discuss] Unicode range Hi Vasilis, Perhaps by removing characters that are outside of that range? The error message gives you a range, from 0 to 65535. So this line might do. s = ''.join(c for c in s if 0 < ord(c) < 65535) Cheers, Nam On Mon, Jan 4, 2021 at 1:25 AM Vasilis Vlachoudis > wrote: Hi all, how can I "replace/strip" unicode characters that are out of the accepted tk range before inserting them to Text()? File "/usr/lib/python3.6/tkinter/__init__.py", line 3272, in insert self.tk.call((self._w, 'insert', index, chars) + args) _tkinter.TclError: character U+1c784 is above the range (U+0000-U+FFFF) allowed by Tcl Vasilis _______________________________________________ Tkinter-discuss mailing list Tkinter-discuss at python.org https://mail.python.org/mailman/listinfo/tkinter-discuss -------------- next part -------------- An HTML attachment was scrubbed... URL: From Vasilis.Vlachoudis at cern.ch Tue Jan 5 06:06:24 2021 From: Vasilis.Vlachoudis at cern.ch (Vasilis Vlachoudis) Date: Tue, 5 Jan 2021 11:06:24 +0000 Subject: [Tkinter-discuss] Extend selection in ttk.Treeview Message-ID: <0BC70B5D93E054469872FFD0FE07220E0312E0A1DC@CERNXCHG51.cern.ch> Hi all, I am currently replacing some Listbox() with ttk.Treeview() however the Treeview doesn't have the "Shift-Up/Down" and "B1-Motion" capabilities to select with the keyboard multiple items and with the mouse by click and drag. Looking the treeview.tcl I've managed to add a binding for the B1-Motion which seems to work, however I failed to find a way to correctly replicate the Listbox behavior with the Shift-Up/Down This is one of my failed tries Any suggestion? class MyTreeview(ttk.TreeView): def __init__(self, master, *kw, **args): super().__init__(master, *kw, **args) self.bind("", self.b1motion) self.bind("", self.selectUp) self.bind("", self.selectDown) def b1motion(self, event): if self.identify_row(event.y) == self.focus(): return self.tk.call("ttk::treeview::Select", self._w, event.x, event.y, "extend") def selectDown(self, event): self.tk.call("ttk::treeview::Keynav", self._w, "down") item = self.focus() self.tk.call("ttk::treeview::SelectOp", self._w, item, "extend") return "break" -------------- next part -------------- An HTML attachment was scrubbed... URL: From Vasilis.Vlachoudis at cern.ch Wed Jan 6 04:57:57 2021 From: Vasilis.Vlachoudis at cern.ch (Vasilis Vlachoudis) Date: Wed, 6 Jan 2021 09:57:57 +0000 Subject: [Tkinter-discuss] Extend selection in ttk.Treeview In-Reply-To: <0BC70B5D93E054469872FFD0FE07220E0312E0A1DC@CERNXCHG51.cern.ch> References: <0BC70B5D93E054469872FFD0FE07220E0312E0A1DC@CERNXCHG51.cern.ch> Message-ID: <0BC70B5D93E054469872FFD0FE07220E0312E0A6C9@CERNXCHG51.cern.ch> For the moment I came up with this solution, which seems to work, however I am not very happy with it. I need to define an "anchor" variable to remember from where the selection started class MyTreeview(ttk.Treeview): def __init__(self, master, *kw, **args): super().__init__(master, *kw, **args) self.bind("", self.b1motion) self.bind("", self.release) self.bind("",self.up) self.bind("", self.down) self.bind("", self.selectUp) self.bind("",self.selectDown) self._anchor = "" # ---------------------------------------------------------------------- def b1motion(self, event): # If selected item is the last one focused # then ignore, otherwise Select is selecting everything if self.identify_row(event.y) == self.focus(): return self.tk.call("ttk::treeview::Select", self._w, event.x, event.y, "extend") # ---------------------------------------------------------------------- def release(self, event): self.tk.call("ttk::treeview::Release", self._w, event.x, event.y) self._anchor = self.focus() return "break" # ---------------------------------------------------------------------- def up(self, event): self.tk.call("ttk::treeview::Keynav", self._w, "up") self._anchor = self.focus() return "break" # ---------------------------------------------------------------------- def down(self, event): self.tk.call("ttk::treeview::Keynav", self._w, "down") self._anchor = self.focus() return "break" # ---------------------------------------------------------------------- def selectUp(self, event): if not self._anchor: self._anchor = self.focus() self.tk.call("ttk::treeview::Keynav", self._w, "up") if self.focus() != self._anchor: self.tk.call("ttk::treeview::SelectOp", self._w, self._anchor, "extend") return "break" # ---------------------------------------------------------------------- def selectDown(self, event): if not self._anchor: self._anchor = self.focus() self.tk.call("ttk::treeview::Keynav", self._w, "down") if self.focus() != self._anchor: self.tk.call("ttk::treeview::SelectOp", self._w, self._anchor, "extend") return "break" ________________________________ From: Tkinter-discuss [tkinter-discuss-bounces+vasilis.vlachoudis=cern.ch at python.org] on behalf of Vasilis Vlachoudis [Vasilis.Vlachoudis at cern.ch] Sent: Tuesday, January 05, 2021 12:06 To: tkinter-discuss at python.org Subject: [Tkinter-discuss] Extend selection in ttk.Treeview Hi all, I am currently replacing some Listbox() with ttk.Treeview() however the Treeview doesn't have the "Shift-Up/Down" and "B1-Motion" capabilities to select with the keyboard multiple items and with the mouse by click and drag. Looking the treeview.tcl I've managed to add a binding for the B1-Motion which seems to work, however I failed to find a way to correctly replicate the Listbox behavior with the Shift-Up/Down This is one of my failed tries Any suggestion? class MyTreeview(ttk.TreeView): def __init__(self, master, *kw, **args): super().__init__(master, *kw, **args) self.bind("", self.b1motion) self.bind("", self.selectUp) self.bind("", self.selectDown) def b1motion(self, event): if self.identify_row(event.y) == self.focus(): return self.tk.call("ttk::treeview::Select", self._w, event.x, event.y, "extend") def selectDown(self, event): self.tk.call("ttk::treeview::Keynav", self._w, "down") item = self.focus() self.tk.call("ttk::treeview::SelectOp", self._w, item, "extend") return "break" -------------- next part -------------- An HTML attachment was scrubbed... URL: From john at mccabe.org.uk Fri Jan 8 09:42:24 2021 From: john at mccabe.org.uk (John McCabe) Date: Fri, 08 Jan 2021 14:42:24 +0000 Subject: [Tkinter-discuss] Entry widget inactive after messagebox.askquestion Message-ID: Hi, I've raised this as a bug report at https://bugs.python.org/issue42867, (based on the same issue having been reported in 2010, but closed with no real resolution in 2014), but apparently they're busy so, in the meantime... 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 - 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 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. The behaviour described here is identical on Windows 10 on Python 3.6, 3.8 and 3.9. If anyone can tell me whether there is an issue with how I'm going about this, or a way round this problem while still retaining the same functionality, I'd appreciate your help. ==== #!/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("", 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("", 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() -------------- next part -------------- An HTML attachment was scrubbed... URL: