1

I want to create a Text widget where a canvas can be inserted to text. I have almost got it perfect however I need the canvas to take up two lines of space. I want the first line 'Tom 24/11/2019' to be aligned with the top of the canvas and the second line 'Hi Jim' to be aligned with the bottom of the canvas. Is what I'm trying to do possible in any way?

import tkinter as tk

sender='Tom'
dt='24/11/2019'
message='Hi Jim!'

root = tk.Tk()

text = tk.Text(root)
text.pack(padx = 10, pady = 10)

text.window_create(tk.END, window = tk.Canvas(root,bg='red',width=50,height=50)) # Example 2

text.tag_configure("sender", font="Arial 12 bold")
text.tag_configure("message", font="Arial 10",lmargin1=55,lmargin2=55)
text.tag_configure("date", font="Arial 8")

text.insert("end", sender.title()+' ',"sender")
text.insert("end", dt+'\n','date')
text.insert("end", message+'\n\n', 'message')


root.mainloop()
Maks Ovnik
  • 65
  • 9
  • maybe you should put Text inside Canvas, not Canvas inside Text. – furas Nov 24 '19 at 21:04
  • thanks but this is for a huge project where I had many memory problems doing it this way as if I wanted to update the text elements then I would have to run thousands of events to update each one but with a text on the outside i just have to run the update function on the text. – Maks Ovnik Nov 24 '19 at 21:09
  • frankly, I don't understand what you try to do. – furas Nov 24 '19 at 21:13
  • maybe you should put in this order: first text, canvas, next text. – furas Nov 24 '19 at 21:14

2 Answers2

1

No, an embedded widget can't span more than one line in the text widget.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
1

The widget window_create() adds to the Text is kind of like a single character, and you can't add text on multiple lines next to it.

Here's a workaround (if I understand what you're wanting). It creates a Frame to hold the image and the Text widgets and packs them next to one another. This makes the text independent of the image and you can put strings into it an they will be aligned to the left edge.

Getting the second string to align right at the bottom may be possible, but I don't know of a way offhand to do it precisely. In the code below, I just inserted a blank line between the two strings and it just happened to work out pretty well (IMO).

import tkinter as tk


sender = 'Tom'
dt = '24/11/2019'
message = 'Hi Jim!'

root = tk.Tk()

frame = tk.Frame(root, bg='white', bd=0, highlightthickness=0)
frame.pack()

canvas = tk.Canvas(frame, bg='red', width=50, height=50)
canvas.pack(side=tk.LEFT, anchor=tk.NW)
text = tk.Text(frame, bd=0)
text.pack(side=tk.LEFT, anchor=tk.NW)

text.tag_configure("sender", font="Arial 12 bold")
text.tag_configure("message", font="Arial 10") # , lmargin1=55, lmargin2=55)
text.tag_configure("date", font="Arial 8")

text.insert("end", sender.title()+' ', "sender")
text.insert("end", dt+'\n', 'date')
text.insert("end", '\n') # Add a blank line to move next one down.
text.insert("end", message+'\n\n', 'message')

root.mainloop()

Screenshot

screenshot showing text lined up next to image

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Hi thanks this is a great solution! The only issue I'm seeing is If I had for example 20 of these objects underneath each other how easy would it be to get scrolling of the text widget AND the canvas at the same time. – Maks Ovnik Nov 24 '19 at 21:43
  • 1
    Maks. I think it would be possible by nesting the red image and `Text` widgets inside an outer `Canvas` (instead of a `Frame`) and then scroll _that_. Since they're both part of it, they'd both scroll together when the outer `Canvas` was scrolled. Hope that makes sense. – martineau Nov 24 '19 at 22:03
  • P.S. See the question [Tkinter scrollbar for frame](https://stackoverflow.com/questions/16188420/tkinter-scrollbar-for-frame) and @Bryan Oakley's answer to it for more info. – martineau Nov 24 '19 at 22:37