Rich Apodaca
Rich Apodaca

Reputation: 29014

Single line text entry UI element that word-wraps text in Tkinter?

My UI needs to accept a single line of text. However, if the length of the text exceeds the width of UI element, the text should wrap to the next line.

The Tkinter Entry class gives what I'm looking for with respect to accepting a single line of text. However, if the text exceeds the width of the element, text isn't wrapped. Instead, it's scrolled left. This prevents the user from seeing what the first few characters were.

The Tkinter Text class supports word wrap, but it also allows the user to enter linefeeds. My text needs to be entered as a single line.

I'm looking for something in-between: a UI element that accepts a single line of text (no line breaks), but also wraps when input overflows the width of the element.

What are my options?

Upvotes: 4

Views: 2352

Answers (1)

TidB
TidB

Reputation: 1759

There's no such widget, but you can do this:

import tkinter as tk

class ResizableText:
    def __init__(self, text_max_width=20):
        self.text_width = text_max_width
        self.root = tk.Tk()

        self.text = tk.Text(self.root, width=self.text_width, height=1)
        self.text.pack(expand=True)

        self.text.bind("<Key>", self.check_key)
        self.text.bind("<KeyRelease>", self.update_width)

        self.root.mainloop()

    def check_key(self, event):
        # Ignore the 'Return' key
        if event.keysym == "Return":
            return "break"

    def update_width(self, event):
        # Get text content; ignore the last character (always a newline)
        text = self.text.get(1.0, tk.END)[:-1]
        # Calculate needed number of lines (=height)
        lines = (len(text)-1) // self.text_width + 1
        # Apply changes on the widget
        self.text.configure(height=lines)

Upvotes: 4

Related Questions