4

I combined a scrollbar with a ttk notebook by adapting this example and additionally porting it to Python3.

I am using ttk widgets as often as possible to get a more 'modern' UI. However, there is no ttk canvas widget, so I used the standard tkinter canvas. By default the backgroundcolor of the canvas widget seems to be white (at least on Mac OS), while the default background of all ttk widgets is grey (see screenshot below).

How can I get the default background of the ttk frame containing the label widgets, so that I can pass it to the canvas by Canvas(parent, background='bg_color') and remove the white space around the ttk frame containing the ttk labels?

I know that ttk uses styles to define the look of the widgets. However, I have no idea about how to read the background value of the (default) style.

screenshot

#!/usr/bin/env python3
# coding: utf-8

from tkinter import *
from tkinter import ttk

master = Tk()

def populate():
    """Put in some fake data"""
    for row in range(100):
        ttk.Label(frame, text="%s" % row, width=3, borderwidth="1", relief="solid").grid(row=row, column=0)
        t="this is the second column for row %s" % row
        ttk.Label(frame, text=t).grid(row=row, column=1)

def OnFrameConfigure(event):
    """Reset the scroll region to encompass the inner frame"""
    canvas.configure(scrollregion=canvas.bbox("all"))

nbook = ttk.Notebook(master)
nbook.grid()
tab = Frame(nbook)

canvas = Canvas(tab, borderwidth=0)
frame = ttk.Frame(canvas)
vsb = Scrollbar(tab, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)

vsb.pack(side="right", fill="y")
canvas.pack(side='left', fill='both', expand=True)
canvas.create_window((0, 0), window=frame, anchor='nw', tags='frame')

frame.bind("<Configure>", OnFrameConfigure)

populate()

nbook.add(tab, text='Test')

master.mainloop()
Community
  • 1
  • 1
albert
  • 8,027
  • 10
  • 48
  • 84

3 Answers3

8

You can use s.lookup() to get settings of a style. If you want the background setting of your ttk Frame use:

s = ttk.Style()
bg = s.lookup('TFrame', 'background')

Which you can apply to your Canvas:

canvas = Canvas(tab, borderwidth=0, background=bg)
fhdrsdg
  • 10,297
  • 2
  • 41
  • 62
  • In general, this explains how to get settings of the given style, which basically solves half of my question. However, after passing the background to the canvas nothing changed (at least on Mac). While testing the same code on Windows it showed up, that the background has the correct color automatically (without passing it from the style.lookup). I think the strange Mac OS Tkinter behaviour is due to some lacks of Tk on Mac, because I am using the default Tkinter version and not the recommended ActiveTcl version, but I did not proofe this... – albert Jan 13 '15 at 16:18
  • I only have a windows pc, so I'm afraid I can't help you with any Mac OS related issues since I can't reproduce them. Did you check that `bg` contains the colour you expected? – fhdrsdg Jan 13 '15 at 17:52
  • I expected the default Mac grey (don't know how this is called). However, `print(bg)` returns `systemWindowBody`. – albert Jan 14 '15 at 08:44
  • Oh, apparently that's some kind of standard color which gives no more information whatsoever.. See http://stackoverflow.com/q/26472565/3714930 – fhdrsdg Jan 14 '15 at 13:10
  • Oh, I found that using `master.winfo_rgb(bg)` you can get a tuple of the 16-bit rgb values. This should work for any string that represents a color, so also `'systemWindowBody'`. Maybe that can help you? – fhdrsdg Jan 16 '15 at 08:30
0

I came across, a similar problem. Setting the background colour to 'systemWindowBody' does not do anything.

Upon searching further, I came across this website with tkinter colors (http://www.science.smith.edu/dftwiki/index.php/Color_Charts_for_TKinter)

enter image description here

I found the closest match to Mac OS grey as 'gray93'. Maybe that helps you achieve the same colour.

Denis Rasulev
  • 3,744
  • 4
  • 33
  • 47
skg
  • 11
  • 2
0

For anyone curious about how to just get the color of a frame (or widget), you can use the following line

widget.cget('bg')

where widget is the widget from which you want to retrieve the background color.

Thus, for a frame you can do:

your_frame.cget('bg')