简体   繁体   中英

selection moves from ttk.Entry to tkinter.Text

Here's a python/tkinter program that puzzles me. The window displays a ttk.Entry that is readonly and a tkinter.Text that is disabled. It programmatically selects one character in the Entry box and never changes this selection. However the selection will change if I try to select text in the other box (the disabledText). This doesn't seem right.

Python 3.5.0 and tcl/tk 8.5.18 on OS X

  1. When you run the program, you can see the "A" highlighted in the Entry (upper) box.
  2. Push the "Write Data" button a few times; the print statement will display the "A" that's selected in the Entry box.
  3. Sweep the mouse over some text in the Text (lower) box; it won't be highlighted, but the highlighting in the Entry will disappear.
  4. Push the "Write Data" button; the print statement will display the characters you swept with the mouse.
  5. Those characters came from selection_get() on the Entry! You can tell that it got them from the Text because the two boxes have no characters in common.

If somebody can explain this, I'd be most grateful.

import tkinter
from tkinter import ttk

class ButtonPanel(ttk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.data = ttk.Entry(self, width=27, takefocus=False)
        self.data.insert(0, "ABCDEFG")
        self.data.select_range(0, 1)                            # select the "A"
        self.data.state(["readonly"])
        self.data.bind('<ButtonPress>', lambda e: 'break')      # ignore mouse clicks
        button = ttk.Button(self, text="Write Data", command=self.master.write)
        self.data.grid(column=0, row=0, padx=10)
        button.grid(column=1, row=0, padx=10)

    def get(self):
        return self.data.selection_get()                 # should always be the "A"

class App(ttk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.bp = ButtonPanel(self)
        self.display = tkinter.Text(self, width=50, height=10, wrap="char", takefocus="False")
        self.display.insert('end', "HIJKLMNOPQRSTUV")
        self.display.config(state="disabled")
        self.bp.pack()
        self.display.pack()

    def write(self):
        char = self.bp.get()                # should always be the "A"
        print("this should be just one character: ->{}<-".format(char))

if __name__ == "__main__":
    root = tkinter.Tk()
    root.title("What's up here?")
    App(root).pack()
    root.mainloop()

What you are observing is the default behavior. Both of those widgets (as well as the listbox) have an attribute named exportselection , with a default value of True . When True , the widget will export the selection to be the primary selection. On old unix systems (where tcl/tk and tkinter got its start), you could only have one "primary" selection at a time.

The simple solution is to set this option to False for the text widget. This will allow your application to have multiple items selected at once, but only the entry widget exports the selection to the clipboard (which is required for selection_get to work.

...
self.display = tkinter.Text(self, ..., exportselection=False)
...

The other issue is that on OSX the selection won't show for a disabled text widget. The text is being selected, you just can't see it. More accurately, the selection won't show except when the widget has focus, and by default, it is not given focus when you click on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM