Adjust height of a row in Tkinter Treeview depending on wraped strings - python

I was making a treeview for my tkinter program, and when I insert the data into it, there are some rows with too many characters and some of them are unseen.
Is there any way to set an auto line feed for the row height? I don't want to add a horizontal scrollbar to solve this. This means when the width of a strings is bigger then th columns with a newline should be iserted (automaticly). In that case the height of the row should be adjusted (automaicly) in that case to display more then one line.
from tkinter import *
import tkinter.ttk as ttk
root = Tk()
frame = Frame(root)
frame.pack()
tree = ttk.Treeview(frame, height=15,
columns=('c1', 'c2'),
show="headings")
tree.column('c1', width=100, anchor='center')
tree.column('c2', width=200, anchor='center')
tree.heading('c1', text='text1')
tree.heading('c2', text='text2')
tree.pack()
tree.insert('', 1, values=['edew', 'dewd'])
tree.insert('', 2, values=['abcd'*10, 'wxyz'*10])
root.resizable(width=False, height=False)
root.mainloop()

The height of alls row can be modified with this code.
root = Tk()
style = ttk.Style(root)
style.configure('Treeview', rowheight=45)
It would be very nice to know if each row in a Treeview can have it's own style to defined individual rowheight (depending on newline characters).

In response to Aleksandar Beat's question:
In order to change the style of a specific Treeview, you have to define a different identifier before the ttk widget name:
Style().configure('AnythingYouWantHere.Treeview', rowheight=45)
# The '.Treeview' can not be changed
However, if you do it this way, you have to specify the style option of the ttk widget.
Sample usage:
root = Tk()
Style().configure('MyStyle1.Treeview', rowheight=45)
styledTreeView = Treeview(root, style='MyStyle1.Treeview')
normalTreeView = Treeview(root) # Style will not automatically apply
This also applies to any ttk widgets.

Related

How do I create internal x padding for an Entry?

I have an Entry input_field and I'm trying to create some internal x padding for the Entry so when you input a value the characters aren't so close to the left side of the Entry.
My code:
from tkinter import *
screen = Tk()
input_field = Entry(font=("Calibri", 16, "bold"), width=25,).pack()
screen.mainloop()
My output:
I would like something like this:
I have tried to use ipadx into the .pack() method but simply doesn't change. I've also looked through documentation and found no other replacements to ipadx except padx but this only creates external padding around the Entry.
Is there a way to create internal x padding instead of manually adding in spaces?
You need to use ttk.Entry and configure the Style like this:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
style = ttk.Style(root)
style.configure('My.TEntry', padding=(20,0, 0,0))
#padding = (padx left, pady up,padx right,pady down)
widget = ttk.Entry(root, style='My.TEntry')
widget.pack(expand=True, fill='both')
root.mainloop()

Why does "ttk.style()" adds additional styles to the Entry widget?

So, I have 4 Entry Widgets on my window and I just wanted to add some internal left padding on the last Entry Widget. I did so using ttk.style(), which added the desired padding but it also added some additional styling like a black border, some hover effect, then the entry widget gets a blue border when selected.
This is my Code:
from tkinter import *
from tkinter import ttk
root = Tk()
root.configure(padx=50)
input1 = Entry(root)
input1.grid(row=1, column=0, pady=10)
input2 = Entry(root)
input2.grid(row=2, column=0, pady=10)
input3 = Entry(root)
input3.grid(row=3, column=0, pady=10)
style = ttk.Style(root)
style.configure('padded.TEntry', padding=[15, 0, 0, 0])
e = ttk.Entry(root, style='padded.TEntry')
e.grid(row=4,column=0, pady=10)
root.mainloop()
Look how the 4th Entry Widget has a Black Border around it
Look how a Blue Border appears when the widget is selected
The only styling that I was excepting is the little increase in width because of the left-padding, but how are these other styles being triggered.
It is because the fourth entry is a ttk.Entry widget but the other three are tkinter.Entry widgets. If you make all four ttk.Entry widgets you'll see that they all have the additional styles.
Even though the tkinter and ttk modules have widgets with the same name, they are completely different widgets with their own sets of defaults.

Tkinter toplevel: Opening treeview to fit the frame

Am having challenge letting my treeview fill the toplevel window have created have tried fill= "x" and fill="both" but not getting the result.Any suggestion to do this.
from tkinter import ttk
import tkinter as tk
def my_treeview():
mt = tk.Toplevel()
mt.geometry("1000x580")
tree = ttk.Treeview(mt)
tree.insert("", "0", "item1", text="fill width")
tree.insert("", "1", "item2", text="fill height")
tree.pack(fill="both")
root = tk.Tk()
root.geometry("400x400")
treeview = tk.Button(root, text="open treeview", command=my_treeview).pack()
root.mainloop()
fill="both" means "fill all the area that has been allocated to you". It is doing just that. The treeview widget has a certain height it wants to be, so pack allocates just enough space for it to fit. That leaves a lot of extra space that has not been allocated.
If you want the treeview to expand to fill all remaining space and not just the space that it needs, use the expand option in addition to the fill option.
Example:
tree.pack(fill="both", expand=True)

get default background of ttk.Frame

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.
#!/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()
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)
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)
I found the closest match to Mac OS grey as 'gray93'. Maybe that helps you achieve the same colour.
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')

Python: Listbox without border

I want to get a table, but when I realized, that there's no table in python, I decided to fix it with two listboxes.
The point is, that I don't want a border between them.
So my Question is: How to remove the border from the Tk Listbox in Python?
Even if it'll become white I had a solution...
You want to set the borderwidth to zero, but you also want to set highlightthickness to zero. Highlightthickness represents a rectangle that surrounds the whole widget when it has keyboard focus. Finally, when you use pack or grid, make sure you don't add any padding between them.
If you want to complete the illusion that the two widgets are one, put them in a frame and give the frame a borderwidth and relief.
import Tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, borderwidth=1, relief="sunken")
lb1 = tk.Listbox(self, borderwidth=0, highlightthickness=0)
lb2 = tk.Listbox(self, borderwidth=0, highlightthickness=0)
lb1.pack(side="left", fill="both", expand=True)
lb2.pack(side="left", fill="both", expand=True)
lb1.insert(0, "left")
lb2.insert(0, "right")
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True, padx=8, pady=8)
root.mainloop()
I think the best you can achieve would be this:
import tkinter as tk
root = tk.Tk()
wrapper = tk.Frame(root, bd=2, relief="sunken")
L1 = tk.Listbox(wrapper, bd=0)
L2 = tk.Listbox(wrapper, bd=0)
L1.grid(column = 1, row = 1)
L2.grid(column = 2, row = 1)
wrapper.pack()
root.mainloop()
note setting the border of each listbox to 0, (bd=0) and to give the overall widget a similar look to the original listbox i've wrapped it in a frame and given that the same border style as the default listbox.
also worth nothing that you need to get the bindings right to make them scroll as expected, just binding to the scroll wheel and scroll bar is insufficient as the lists can be moved with the arrow keys when an item is highlighted, like in the second example on this page:
scrolling multiple listboxes together
by Santiclause
Speicfy borderwidth as 0 when you create a listbox.
For example:
from Tkinter import * # from tkinter import * (Python 3.x)
root = Tk()
lb = Listbox(borderwidth=0) # <---
lb.pack()
root.mainloop()

Categories

Resources