Samuel
Samuel

Reputation: 65

How to disable selecting text in a Python/Tk program?

How would that be done? I have been unable to find it on here or with Google.

#Refrences
from tkinter import *

class Interface:

    def __init__(self,stage):

        topLeft = Frame(stage,bg='black')
        test = Entry(topLeft,bg='#2a2a2a',fg='white',insertontime=0)
        test.config(insertbackground='white', exportselection=0)
        test.grid()
        topLeft.grid(row=0,column=0)

def launch():
    window = Tk()
    lobby = Interface(window)
    window.mainloop()

launch()

Upvotes: 5

Views: 3816

Answers (4)

Christopher Tadeo
Christopher Tadeo

Reputation: 11

You can set the text highlight color to match the background of entry widget. Note that the text in the widget can still be selected but the user will not see it visually which will give the illusion that selection is disabled.

test = Entry(topLeft,bg='#2a2a2a',fg='white',insertontime=0)
test.configure(selectbackground=test.cget('bg'), inactiveselectbackground=test.cget('bg'))

Upvotes: 1

Saeid Gholami
Saeid Gholami

Reputation: 9

When we select a text we tkinter trigger(fire) 3 events, which are ButtonPress, Motion and ButtonRelease all these 3 events call a event handler fucntion. The function run select_range(start, end) method which highlight selected text.

To disable this we have to hanlde ButtonPress and Motion events together and call select_clear method on the widget.

If you handle the events and call select_clear method it work but not properly, the text will be highlighted and when another event occured highligh color will be cleared. This happend because of execution order of events. That's mean you have to tell to tk handle your event after default event handler. We can change order of events execution with bindtags and bin_class methods

example:

from tkinter import *
from tkinter import ttk


def on_select(event):
    event.widget.select_clear()  # clear selected text.


root = Tk()

name_entry = ttk.Entry(root)
name_entry.pack()

# with PostEvent tag, on_select the event hanlde after default event handler
name_entry.bindtags((str(name_entry), "TEntry", "PostEvent", ".", "all"))
name_entry.bind_class("PostEvent", "<ButtonPress-1><Motion>", on_select)


root.mainloop()

Upvotes: 0

Revexious
Revexious

Reputation: 21

I assume you wish for users to not be able to edit the Entry box? If so, you must use the config parameter of (state="disabled"), eg.

test.config(insertbackground='white', exportselection=0, state="disabled")

be wary though, I could not find a way to keep the background of your entry box black. Hope this helps

Upvotes: 2

en_Knight
en_Knight

Reputation: 5381

A useful solution to Tkinter not having tons of built-in widgets (like, say, JavaFX does), is that you can easily make your own if you don't mind them being not-quite what you wanted :) Here's a rough-around-the-edges example of using a canvas to emulate an entry field that can't be selected. All I've given is the insert functionality (and delete too, I suppose, if you were clever about it), but you may want more. (Another plus is that, because it's a canvas item, you can do nifty formatting with it).

Am I right that by a not-selectable entry widget, you mean a canvas with text written on it? If you want to disable text-highlighting in ALL widgets, including the top-level frame, you could highjack the Button-1 event, deselect everything, and then consume the event whenever text is selected.

from tkinter import *

class NewEntry(Canvas):

    def __init__( self, master, width, height ):
        Canvas.__init__( self, master, width=width,height=height )
        self.width = width
        self.height = height
        self.text = ''

    def insert( self, index, text ):
        self.text =''.join([self.text[i] for i in range(index)] + [text] + [self.text[i] for i in range(index,len(self.text))])
        self.delete(ALL)
        self.create_text(self.width//2,self.height//2,text=self.text)

root = Tk()
entry = NewEntry(root,100,100)
entry.insert(0,'hello world')
entry.insert(5,'world')
entry.pack()
root.mainloop()

Upvotes: -1

Related Questions