Inserting a button into a tkinter listbox on python? - python

...
self.myListbox=tkinter.Listbox()
self.myListbox.pack()
self.myButton=tkinter.Button(self.myListbox,text="Press")
self.myListbox.insert(1,myButton.pack())
...
I want to insert a button into listbox like inserting a sting. How can I do this?

You can't. From the listbox documentation: "A listbox is a widget that displays a list of strings".
You can, of course, use pack, place or grid to put a button inside the widget but it won't be part of the listbox data -- it won't scroll for example, and might obscure some of the data.

An alternative to a ListBox is a scrollable frame;
import functools
try:
from tkinter import *
import tkinter as tk
except ImportError:
from Tkinter import *
import Tkinter as tk#
window = Tk()
frame_container=Frame(window)
canvas_container=Canvas(frame_container, height=100)
frame2=Frame(canvas_container)
myscrollbar=Scrollbar(frame_container,orient="vertical",command=canvas_container.yview) # will be visible if the frame2 is to to big for the canvas
canvas_container.create_window((0,0),window=frame2,anchor='nw')
def func(name):
print (name)
mylist = ['item1','item2','item3','item4','item5','item6','item7','item8','item9']
for item in mylist:
button = Button(frame2,text=item,command=functools.partial(func,item))
button.pack()
frame2.update() # update frame2 height so it's no longer 0 ( height is 0 when it has just been created )
canvas_container.configure(yscrollcommand=myscrollbar.set, scrollregion="0 0 0 %s" % frame2.winfo_height()) # the scrollregion mustbe the size of the frame inside it,
#in this case "x=0 y=0 width=0 height=frame2height"
#width 0 because we only scroll verticaly so don't mind about the width.
canvas_container.pack(side=LEFT)
myscrollbar.pack(side=RIGHT, fill = Y)
frame_container.pack()
window.mainloop()

Related

centering a text within a button in tk

usually buttons in tkinter center their texts automatically but i can't seem to get it i don't know why!
from tkinter import *
from tkinter import messagebox
from PIL import Image,ImageTk
from getpass import getpass
huh=Tk()
huh.title('Login page')
huh.configure(bg='white')
huh.resizable(False,700)
huh.geometry('925x500+300+200')
my_fr=Frame(huh,width=350,height=350,bg='white')
my_fr.place(x=480,y=90)
btn=Button(my_fr,width=50,border=0,text="Connexion",bg='#000000',fg="#ffffff",font='Railway',anchor=CENTER)
btn.place(x=43,y=300)
huh.mainloop()
Here is a solution using grid() that positions the button, with text centered, at the x, y coordinates used with the original place() statement.
Note that resizeable() takes only boolean parameters, so '700' would be interpreted as True. Assuming that a maximum window height of 700 with a minimum height of 500 was the intention, resizeable() was replaced with minsize() and maxsize() statements.
The geometry() statement was retained, but if the system's default window position is suitable, then it can be removed.
Replacing my_fr.grid() with my_fr.pack() would horizontally center the button, thus ignoring the padx specification.
import tkinter as tk
huh = tk.Tk()
huh.title('Login page')
huh.configure(bg='white')
huh.geometry('925x500+300+200')
huh.minsize(925, 500)
huh.maxsize(925, 700)
my_fr = tk.Frame(huh, bg='white')
btn = tk.Button(my_fr, width=50, text="Connexion",
bg='black', fg="white", font='Railway')
my_fr.grid()
btn.grid(padx=43, pady=300)
huh.mainloop()

How can I align scrolled text to the right?

The problem is simple. The scrolled text box will be written into it in Arabic.
So I need to align the text whenever I type to the right of the box. There isn't any attribute, such as justify. Also I used a tag, but I couldn't do it.
show_note = scrolledtext.ScrolledText(canvas, width=int(monitorWidth / 65), height=int(monitorHeight / 130),
font=("Times New Roman", 14))
canvas.create_window(cord(0.45, 0.65), window=show_note, anchor="ne")
Is there an alternative to the scrolled text control, but that has these attributes (width, height, justify and can write into multiple lines)?
I did some searching and could not find any other way to do this, than to bind each keypress to a function, that adds/edits the tag to select all the item from the text box:
from tkinter import *
from tkinter import scrolledtext
root = Tk()
def tag(e):
text.tag_add('center','1.0','end')
text = scrolledtext.ScrolledText(root)
text.pack()
text.tag_config('center',justify='right')
text.bind('<KeyRelease>',tag)
root.mainloop()
You can also make your custom widget that does this, instead of repeating code for each file, so a more better form would be:
from tkinter import *
from tkinter import scrolledtext
root = Tk()
class JustifyText(scrolledtext.ScrolledText):
def __init__(self,master,*args,**kwargs):
scrolledtext.ScrolledText.__init__(self,master,*args,**kwargs)
self.tag_config('center',justify='right')
self.bind('<KeyRelease>',self.tag)
def tag(self,e):
text.tag_add('center','1.0','end')
text = JustifyText(root)
text.pack()
root.mainloop()
And yes you can make this more perfect by taking the current width of text box and shifting the insertion cursor to that point, to make it start from that point.

Tkinter Listbox make a selection

I am trying to create a pop-up box to select multiple years. I have the box created but I cannot figure out how to make a button to actually select multiple years. The goal is to take that selection and store it in a list.
from tkinter import *
import pandas as pd
import tkinter as tk
test_years = ["2016", "2017", "2018", "2019"]
root = tk.Tk()
root.title("Test Year Selection")
lb = Listbox(root, selectmode=MULTIPLE, height = len(test_years), width = 50) # create Listbox
for x in test_years: lb.insert(END, x)
lb.pack() # put listbox on window
root.mainloop()
To clarify I am looking to select lets say 2017 and 2018 and have that selection stored in a list using tkinter listbox.
Any assistance would be greatly appreciated.
A example to get the value you select when you press the Start button:
from tkinter import *
# import pandas as pd
import tkinter as tk
def printIt():
SelectList = lb.curselection()
print([lb.get(i) for i in SelectList]) # this will print the value you select
test_years = ["2016", "2017", "2018", "2019"]
root = tk.Tk()
root.title("Test Year Selection")
lb = Listbox(root, selectmode=MULTIPLE, height = len(test_years), width = 50) # create Listbox
for x in test_years: lb.insert(END, x)
lb.pack() # put listbox on window
tk.Button(root,text="Start",command=printIt).pack()
root.mainloop()
Basically you want to add the value of selected item of listbox to a list. you need to call bind() method on the listbox widget. here is the code from this amazing tutorial on tkinter listbox
def get_value(event):
# Function to be called on item click
# Get the index of selected item using the 'curseselection' method.
selected = l.curselection()
if selected: # If item is selected
print("Selected Item : ",l.get(selected[0])) # print the selected item
# Create a listbox widget
l = Listbox(window)
l.bind('<>',get_value)
l.pack()

Trying to print the output from my function inside my GUI window

Im trying to make a little program that endlessly prints out numbers inside GUI window, I can not find a way to print the out put of the function in a text box inside the GUI window instead of the python shell, please help, here is my code so far...
import sys
from tkinter import *
root = Tk()
def number(event):
x = 420
while True:
x +=420
print(x^70)
button_1 = Button(root, text="Start...")
button_1.bind("<Button-1>", number)
button_1.pack()
root.mainloop()
Thanks Harvey
You'll find it hard to constantly insert a value into a widget. The widget does not update with each insert. You can think of it has having a temporary variable for it. It can be accessed during the loop (as shown with print). However you'll notice that the widget itself doesn't update until the loop is over. So if you have while True then your widget will never update, and so you won't have the numbers streaming into the widget.
import sys
from tkinter import *
root = Tk()
def number():
x = 420
while x < 8400: # Limit for example
x +=420
textbox.insert(END, str(x^70)+'\n')
print(textbox.get(1.0, END)) # Print current contents
button_1 = Button(root, text="Start...", command=number) #Changed bind to command, bind is not really needed with a button
button_1.pack()
textbox = Text(root)
textbox.pack()
root.mainloop()

How to fit Tkinter listbox to contents

I'm adding strings to a listbox using the code below. When I run the code and the window opens, the longer strings get clipped as the window is not large enough (see screenshot). I have tried making the window resizeable and adding scroll bars but I was wondering if there was a way to automatically size it to fit the content.
master = tk.Tk()
listbox = tk.Listbox(master, selectmode=tk.SINGLE)
games = ["Garry's Mod", "Mount and Blade: Warband", "Tekkit"]
for game in sorted(games):
listbox.insert(tk.END, game)
button = tk.Button(master, text="Execute", command=execute)
listbox.pack()
button.pack()
tk.mainloop()
Resetting the listbox width worked for me. I used the Oblivion's answer and noticed that the width is always zero.
listbox = tk.Listbox(master, selectmode=tk.SINGLE)
listbox.config(width=0)
I also recommend to reset the root window geometry after reloading a content of the list. Otherwise if user manually extends a window the window would stop accommodate size of its content.
root.winfo_toplevel().wm_geometry("")
just give width and height 0 as below
listbox.config(width=0,height=0)
tkListAutoWidth.py shows one way to do it.
Edit:
So you might have something along the lines of,
import tkinter as tk
from tkinter import font
class NewListbox(tk.Listbox):
def autowidth(self, maxwidth=100)
autowidth(self, maxwidth)
def autowidth(list, maxwidth=100):
f = font.Font(font=list.cget("font"))
pixels = 0
for item in list.get(0, "end"):
pixels = max(pixels, f.measure(item))
# bump listbox size until all entries fit
pixels = pixels + 10
width = int(list.cget("width"))
for w in range(0, maxwidth+1, 5):
if list.winfo_reqwidth() >= pixels:
break
list.config(width=width+w)
if __name__ == "__main__":
master = tk.Tk()
listbox = NewListbox(master, selectmode=tk.SINGLE)
# ...
# ...
keys = serverDict.keys()
for key in sorted(keys):
listbox.insert("end", key)
listbox.pack()
button = tk.Button(master, text="Execute", command=execute)
button.pack()
listbox.autowidth()
master.mainloop()

Categories

Resources