1

I have a nice design for my GUI. I would want to be able to select the text displayed in Message widgets. The only suggestions I saw are to either use an Entry widget in the read only mode, but this looks completely different than a Message widget or to use a Text widget which again looks completely different. How can I select the text in a Message widget?

If this is not possible, how would I get a Text or Entry widget to look and behave the same as a Message widget?

Hakaishin
  • 2,550
  • 3
  • 27
  • 45
  • You have complete control over the colors, fonts, and borders of both the entry and text widgets. What difficulty are you having in making them look like a message widget? – Bryan Oakley Oct 09 '18 at 13:59
  • Before trying to make a car look like a bike I wanted to make sure that only a car can be used for this job. And I've seen bad advice before especially concerning GUIs where it says to use this and that and customize x and y to latter realize that there was a built in option to do what I wanted all along. If the answer is you can't do that with a Message widget that is fine too but I would still like to know – Hakaishin Oct 09 '18 at 14:03
  • "select" as in within the GUI, using the mouse cursor to select the text to copy? Or "select" as in get the text within the code and do something with it? – r.ook Oct 09 '18 at 14:06
  • Select as in be able to copy past it. Like you can select nearly anything in a browser to copy paste it – Hakaishin Oct 09 '18 at 14:16

1 Answers1

2

Short answer is no, you can't. You might be able to do some clever workaround with event capturing but it's much more work than you might be anticipating.

The most likely way to implement this as you mentioned is just emulate the Message look on an Entry or Text widget. An easy way is using ttk.Style to copy the look and feel of the widgets under ttk instead. However there's no Message widget under ttk, but Label cuts pretty close:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
lbl = ttk.Label(root, text='foo')
lbl.winfo_class()

# 'TLabel'
# This means ttk.Label uses a 'TLabel' style

# Set a StringVar to update the message without updating the state
my_txt = tk.StringVar()

my_msg = ttk.Entry(root, text=my_txt, style='TLabel', justify='center', state='readonly')

# justify to emulate the Message look (centered).
# state = `readonly` to protect the Entry from being overwritten

my_txt.set('message here')

Your Entry widget will now look like a Message widget with the text 'message here' to copy without write access.

Edit: If you want to resize the entry based on the characters, assuming you have a fixed-length font, you can try this:

my_msg.pack(expand=True, fill=tk.BOTH)
my_txt.set('this is a way longer message so give it a try whatever')
my_msg.configure(width=len(my_txt.get()))

If your font is not fixed-length you can guestimate an average/max width per character increase and multiply the ratio to the len():

my_msg.configure(width=int(len(my_txt.get())*0.85))
# where you anticipate each character might take only up to 85% of the normal character width
r.ook
  • 13,466
  • 2
  • 22
  • 39
  • This is nearly perfect. How could I make the entry expand to fit the content? I tried .pack(expand=True, fill="both") but with limited success. It expands but only untill it hits the root border and then it is scrollable instead of expanding the root more – Hakaishin Oct 23 '18 at 12:36
  • Another option, if you will be using a fixed length font, you can increase the `width` per character added, and the `root` should expand to fit. If your font is not fixed length, you can try a guestimate of the width increase per character. I've updated the answer with a quick sample. – r.ook Oct 23 '18 at 15:04