0

Aspects of this question have most certainly been asked before, but not altogether.

[using Python 3.7.1]

Most of it works fine, but the display of scrolling textboxes is just not working... they expand southwards, and the scrollbar sliders never appear.

Never mind that the boxes and labels are too spaced apart.

Whilst it would probably be better to start again, with classes and use pack(), for the sake of understanding better, I would like to see if there's a way to make this work with grid() in a procedural way.

I can't quite get it over the line...

rtmiss = StringVar()

...

# COMMENT: Scrolled Text boxes
scrolledtext1_box=ScrolledText(framemain,width=30,height=10)
scrolledtext1_box.grid(sticky='n',row=5,column=0,rowspan=1,columnspan=1)
ttk.Label(scrolledtext1_box, anchor='w', width=20, text='placeholder', style='TLabel').grid(column=1, row=0, padx=0, pady=0)
tdiff_label = ttk.Entry(scrolledtext1_box, width=20, textvariable=tdiff)
scrolledtext1_box.insert(1.0, chars="anything")
tdiff_label.grid(column=0, row=5, columnspan=1, padx=1, pady=1)

no idea why this is so difficult. It's not the same as just inserting some free text into a textbox and adding a scrollbar.

tdiff_labelframe = ttk.LabelFrame(framemain, text='Title')
tdiff_labelframe.grid(column=0, row=5, padx=8, pady=4)
scrol_w  = 30
scrol_h  =  3
scrolledtext1_box = scrolledtext.ScrolledText(tdiff_labelframe, width=scrol_w, height=scrol_h, wrap=tk.WORD)
scrolledtext1_box.grid(sticky='nw',row=5,column=0,rowspan=1,columnspan=1)
tdiff_labelframe = ttk.Entry(framemain, width=20, textvariable=tdiff)
tdiff_entry = ttk.Entry(scrolledtext1_box, width=12, textvariable=tdiff)
tdiff_entry.grid(column=0, row=5)

I looked inside the Class Entry(Widget, XView) stuff...

    def insert(self, index, string):
        """Insert STRING at INDEX."""

You can insert a string, as most examples will show you, as "my string", and I am able to get the contents of a StringVar into the text box, but only as a contiguous string, with no scrolling.

In the form in the codesnippet above...

tk.Tk()= myframe(root)
my_stringvar = stringvar()
my_labelframe = ttk.LabelFrame(my_frame, text='My Text')
my_labelframe = Entry(my_frame, textvariable = my_stringvar)

The scrolled stuff seems to be on a different "layer". The two blocks of code seem to be unconnected: apart from the scrolledtext function variable referring to the labelframe, which just sticks it onto that layer.

my_scrollheight = 20
my_scrollwidth = 10
my_scrolledtext = scrolledtext.ScrolledText(my_labelframe, width=my_scrollwidth, height=my_scrollheight, wrap=tk.WORD)
my_scrolledtext.grid(row=0,column=0,sticky='news')

So is the StringVar just being inserted into the Frame, above the LabelFrame layer, and thus not being "seen" by the scrolledtext part?

  • I feel like you are asking alot of things. The best I can think of to express your situation here is, to show what you got vs what you want/expected to get. – Delrius Euphoria Aug 22 '22 at 00:59
  • my situation is that I'm trying to learn what the limitations are of grid() when it comes to building a simple GUI. The main problem I'm having is getting a scrollbar to work inside a nested structure where the objective is to display some text on part of a window, in a way that lets you scroll vertically through it. At the moment, the scrollbar doesn't display correctly. The end goal is to have a scrollable text box (or more than one) with text in it on the lower half of a GUI, and other widgets on the top half. I want to use grid() and procedural is because the rest of it is in that. – Reginald Lloyd Aug 22 '22 at 01:02
  • 1
    Then the answer is, there are not much limitations as you'd think – Delrius Euphoria Aug 22 '22 at 01:04
  • _"The text box is inside the canvas..:"_ Not really, the textbox is inside the frame – Delrius Euphoria Aug 22 '22 at 01:05
  • This is the thing, as I understand it, frame doesn't play well with scrollbars, which is why I put a canvas there. The idea is that the canvas does the scrollbar for the text box. The text box is fed content from the output variable. – Reginald Lloyd Aug 22 '22 at 01:07
  • Did you know there is a `scrolledtext` module for `tkinter`, which provides you with a scrollbar on a `Text` widget? – Delrius Euphoria Aug 22 '22 at 01:09
  • I can get the text from the output variable to display in the window (with a different colour field behind it, which I don't know why I can't get rid of), but instead of staying within the field, and a scrollbar slider appearing, it just expands the field. – Reginald Lloyd Aug 22 '22 at 01:09
  • scrolledtext sounds good... although some don't seem to see the point of it: https://stackoverflow.com/questions/42006805/python-scrolledtext-module – Reginald Lloyd Aug 22 '22 at 01:12
  • Does this answer your question? [How to attach a Scrollbar to a Text widget?](https://stackoverflow.com/questions/13832720/how-to-attach-a-scrollbar-to-a-text-widget) – Delrius Euphoria Aug 22 '22 at 01:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/247437/discussion-between-delrius-euphoria-and-reginald-lloyd). – Delrius Euphoria Aug 22 '22 at 01:28
  • Why do you want Canvas? – toyota Supra Aug 22 '22 at 02:21
  • I don't "want" canvas... I want the text box on the window, to stay the same size when the programme sends text to display in it. At the moment, the text box expands beyond the window frame, and no scrollbar slider appears. – Reginald Lloyd Aug 22 '22 at 02:24
  • You don't really need `scrolledtext` - the `Text` widget has the ability to scroll, and it's only a couple of lines of code to add scrollbars. – Bryan Oakley Aug 22 '22 at 02:52
  • that's true... except it doesn't (seem to) work... (when I try this with grid() in a simple application as described above) so, what to do?! – Reginald Lloyd Aug 22 '22 at 02:54
  • maybe if I put something underneath the text box it will force it to not expand, and to show the scrollbar slider? Trying to place it inside a canvas or frame, didn't work so far... – Reginald Lloyd Aug 22 '22 at 03:17
  • @ReginaldLloyd: I don't understand your reply to me. Are you wanting to scroll the widget as a whole, versus scrolling the content inside the text widget? – Bryan Oakley Aug 22 '22 at 03:28
  • Please try to reduce this code down to a [mcve]. Surely you can create a program with a single text widget to reproduce the problem. Do we really need all of this other code? – Bryan Oakley Aug 22 '22 at 03:30
  • I want to scroll the content inside the text widget.... if you run the code, you will see that three textboxes appear at the bottom if you load a couple of similar text files with lines of text in them... the trouble is, the bottom the window is not "hard", so they just extend down, and you never see the slider... I can try to reduce it, but I don't know if that helps. – Reginald Lloyd Aug 22 '22 at 03:30
  • If you want to scroll the text inside the text widget, you just need to attach scrollbars to it. Attaching scrollbars to a text widget only requires a couple lines of code, so it's not clear what the problem is. – Bryan Oakley Aug 22 '22 at 03:32
  • Also, `grid` doesn't affect the ability to scroll at all. – Bryan Oakley Aug 22 '22 at 03:33
  • It appears maybe you misunderstand what text widgets are for. Why are you adding `Labels` to the text widget? You won't be able to scroll it any widgets added to a text widget or canvas using `pack`, `place`, or `grid`. A text widget can only scroll the text added with `insert`, or widgets added with `window_create`. – Bryan Oakley Aug 22 '22 at 03:35
  • If you see the textvariable, that's the content in memory following the process, that I want to place in the scrolledtextbox. If using tk.Label is not going to work, is "insert" the appropriate way to do it? – Reginald Lloyd Aug 22 '22 at 03:39
  • Yes, you need to use `insert` to add text to a widget so that it can be scrolled. – Bryan Oakley Aug 22 '22 at 03:43
  • so, [referring to the code above...] remove tdiff_label etc... and add something like scrolledtext1_box.insert(textvariable = rtmiss)? I don't think that works, event with chars='rtmiss' – Reginald Lloyd Aug 22 '22 at 14:42
  • This answer seems to offer some hope: https://stackoverflow.com/questions/21507178/tkinter-text-binding-a-variable-to-widget-text-contents – Reginald Lloyd Aug 22 '22 at 14:51
  • maybe I can do: rtmiss = tk.StringVar() rtmiss_entry = ttk.Entry( framemain, textvariable=rtmiss, show='*' ) rtmiss_entry.grid() – Reginald Lloyd Aug 22 '22 at 15:05

1 Answers1

0

I have a partial answer to this, that I happened upon myself, but it creates a new problem. Before I could print the filepath, but not get the file contents to print and scroll; now it's the other way round.

I started off with this code: Button errors in Tkinter - Selecting files, adding their paths ...trimmed it down to bare bones and one of each thing; then added my own junk, and eventually I accidentally made it work.

The solution to getting the text into a scrolled text widget, as in the question "how to send StringVar() content to Scrolled Text box using grid() and using procedural code?" is this:

def forkscroll():
    mylabelframe = tk.LabelFrame(myframe, text='My Long Text:').pack()
    scroll_w = 30
    scroll_h = 10
    myscrolledtext = scrolledtext.ScrolledText(mylabelframe, width=scroll_w, height=scroll_h, wrap=tk.WORD)
    myscrolledtext.vbar.config(width=20)
    myscrolledtext.grid(sticky='news', row=6, column=0, rowspan=1, columnspan=1, padx=5, pady=5)

# Open a dialogue; select and load a text file; read the text file directly into the scrolledtext widget (box)
    fork = open(filedialog.askopenfilename(), 'r') # it's the same as "infile" above; but it's not a string
    myscrolledtext.insert(tk.END, fork.read()) ### This reads the content of "fork" into the scrolledtext widget

...mainly those bottom two lines.

I then go on to put the file path of the selected text file into an Entry widget, but I can't get it to work... the best I could do was to keep the browsefunc and open the file twice... once for the path, and once for the contents... which is obviously a rubbish bodge.

    forkit = StringVar()
    forkit.set(fork.get())
    mynormaltext = Text(mylabelframe, width = 10, height = 1, wrap=tk.WORD)
    mynormaltext.grid(sticky='news', row=5, column=0, rowspan=1, columnspan=1, padx=5, pady=5)
    mynormaltext.insert(tk.END, forkit.get())

# Even though it does the same thing in one line as it does in three, the outcome is not the same for scrolledtext
#    forkname = filedialog.askopenfilename()
#    forkfile = open(forkname, 'r')
#    fork = forkfile.read()

# above... "fork" is a textIO, but Text can read it...

The best I can do, is get the content of the text file to fill the scrolledtext widget, and to print "<_IO.TextWrapper", as in the attached image. That's a bit better than just printing "PYVAR4" or something. I have tried converting the "TextIO" or "PathLike" file into a string to inset it; I've tried doing set()/get(), and read() and lambda and tried putting things in different functions, and inputting and returning things, all sorts to try and get the filepath out again, but not really getting anywhere.

At least I've become more familiar with what some things do, and how, but I think I've hit a wall with the total solution, which is:

  1. present 2 labels with 2 buttons each with a field: one as a text widget field; and scrolledtext widget field.
  2. to click a button to browse to a text file, and read it into memory, and print its path into the text widget field
  3. to click the other button, and print the contents of the same file into the scrolledtext field, and have it present within the frame, with a nice long scrollbar.

enter image description here