0

please i have a little problem white my code and i hope you can help me guys, i'm using a scrollbar to scroll over images in my text widget, but the problem is that the tab window is covered by the images when i scroll. enter image description hereenter image description hereenter image description here

this last picture shows the problem, and i want the tabs to remain showing when i scroll and the images should stay inside the tab. here's the code i used:

import tkinter as tk
from PIL import ImageTk, Image
from os import listdir
from os.path import isfile, join
from tkinter import ttk

def getPaths():
    path = "C://Users/poste/Desktop/trainCascade/p"
    onlyfiles = [f for f in listdir(path) if isfile(join(path, f))]
    return onlyfiles

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        style = ttk.Style()
        style.theme_create('pastel', settings={
            ".": {
                "configure": {
                    "background": 'white',  # All except tabs
                    "font": 'red'
                }
            },
            "TNotebook": {
                "configure": {
                    "background": '#848a98',  # Your margin color
                    "tabmargins": [2, 5, 0, 0],  # margins: left, top, right, separator
                }
            },
            "TNotebook.Tab": {
                "configure": {
                    "background": '#d9ffcc',  # tab color when not selected
                    "padding": [10, 2],
                    "font": "white"
                },
                "map": {
                    "background": [("selected", '#ccffff')],  # Tab color when selected
                    "expand": [("selected", [1, 1, 1, 0])]  # text margins
                }
            }
        })

    style.theme_use('pastel')

    tabControl = ttk.Notebook(self)

    tab1 = ttk.Frame(tabControl)
    tab2 = ttk.Frame(tabControl)

    tabControl.add(tab1, text='Tab 1')
    tabControl.add(tab2, text='Tab 2')
    tabControl.pack(expand=1, fill="both")

    text = tk.Text(tab1, wrap="none")
    vsb = tk.Scrollbar(tab1, orient="vertical", command=text.yview)
    text.configure(yscrollcommand=vsb.set)
    vsb.pack(side="right", fill="y")
    text.pack(fill="both", expand=True)

    img = []
    resized = []
    final = []
    label = []
    flag = 0
    for i in range(len(getPaths())):
        img.append(Image.open("C://Users/poste/Desktop/trainCascade/p/"+getPaths()[i]))
        resized.append(img[i].resize((107, 80), Image.ANTIALIAS))
        final.append(ImageTk.PhotoImage(resized[i]))

        label.append(tk.Label(image=final[i], bg='white'))
        label[i].image = final[i]
        text.window_create("end", window=label[i])
        flag+=1
        if flag==5:
            text.insert("end", "\n")
            flag=0

    text.configure(state="disabled")

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("575x400")
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
Mouad7991
  • 13
  • 3
  • Why not use a [scrollable frame](https://stackoverflow.com/a/66215091/11106801) instead of a scrollable text widget. In the frame you can use the `.grid` manager. – TheLizzard Aug 16 '21 at 20:17
  • Are images necessary to reproduce this problem, or does the problem also happen if you use text in the label instead of an image? Also, does the problem only occur if you use a custom style, or does it also happen with the built-in styles? – Bryan Oakley Aug 16 '21 at 20:49
  • Indentation is the posted code seems broken. Shouldn't `style.theme_use('pastel')` and the code that follows be indented inside of `__init__`? – Bryan Oakley Aug 16 '21 at 20:51
  • i used the scrollable frame that you suggested and i had the same problem – Mouad7991 Aug 16 '21 at 22:47
  • @Mouad7991 I noticed that you don't pass in `master` as the first argument when creating those `Label`s. Try using: `tk.Label(text, image=final[i], bg="white")` – TheLizzard Aug 16 '21 at 22:48
  • yes this problem happens only when i use images, it doesn't happen when i use text – Mouad7991 Aug 16 '21 at 22:49
  • @TheLizzard yes it solved the problem, thank you so much – Mouad7991 Aug 16 '21 at 22:52
  • @Mouad7991 I will write an answer. But basically I think it's a bug in `tcl`. – TheLizzard Aug 16 '21 at 22:53
  • @BryanOakley Can you please look at my answer and tell me if my reasoning makes sense? – TheLizzard Aug 16 '21 at 23:02

1 Answers1

0

The problem seems to be caused by the lack of master argument when creating those labels with the images.

As a minimal working example:

import tkinter as tk

root = tk.Tk()

label = tk.Label(root, text="If you scroll down the text box, this will " \
                            "be covered.", anchor="w")
label.pack(fill="x")

text = tk.Text(root)
text.pack()

for i in range(50):
    # Adding `text` as the first parameter here solves the problem
    label = tk.Label(text=f"Text label number {i}")
    text.window_create("end", window=label)
    text.insert("end", "\n")

root.mainloop()

When you don't specify the master argument, tkinter uses the first window that you created for the master. The problem is that the text widgets tells the Label to draw itself giving coordinates that are outside of it's borders. The Label check if it's inside it's master's border but as it's master isn't the text widget it is free to draw over your other widgets. I think it's a bug in tcl, the library that tkinter uses.

Fix: Always pass in the master argument when creating widgets.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31