Python Forum
[Tkinter] how do i add a margin to a Listbox
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] how do i add a margin to a Listbox
#11
wuf, I greatly appreciate the heads up on this working with pack as well. I have tried your example and have modified my lines to have what you have modified and it is not working for whatever reason. The widget is displayed and the query inserts the data but without the margin.
Here is the code that I have modified to follow your example.
INTERIOR_BORDER = 10
output = tkinter.Listbox(window_2, width=42, height=20, bd=0,
highlightthickness=0, bg = '#FFD599', fg = '#9A0615', selectmode=SINGLE)
output.pack(side='left', fill='both',expand=True, padx=INTERIOR_BORDER,
pady=INTERIOR_BORDER)
output.place(x=210, y=195)
yscroll1 = tkinter.Scrollbar(window_2, command=output.yview,
orient=tk.VERTICAL)
yscroll1.pack(side='left', fill='y')
yscroll1.place(x=463, y=196)
output.configure(yscrollcommand=yscroll1.set)
output.bind('<ButtonRelease-1>', getRecipe)
Am I overlooking something?

I believe it may have something to do with the frame setup which is not the same as my "window_2" setup:
main_frame = tk.Frame(self.main_win, relief='sunken', bd=1, bg = 'white')
main_frame.pack(fill='both', expand=True, padx=5, pady=5)
My window_2 setup uses a gif for the background:
def window_2():
    root.destroy()
    window_2 = tkinter.Tk()
    image2 = 'window2.gif'
    bg_image2 = tkinter.PhotoImage(file=image2)
    w = 1024
    h = 612
    ws = window_2.winfo_screenwidth()
    hs = window_2.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    window_2.geometry('%dx%d+%d+%d' % (w, h, x, y))
    panel2 =tkinter.Label(window_2, image=bg_image2)
    panel2.pack(side='top', fill='both', expand='yes')
    panel2.image = bg_image2
    window_2.title('Recipes')
Would you have any suggestions how to get around this part?
"Often stumped... But never defeated."
Reply
#12
Hi DT2000

Please don't mix place with pack!!!. Does the following skript work better?:
import tkinter as tk

TEST_DATA = list_item_values = ["one", "two", "three", "four", "five"]*5

def getRecipe(event):
    print('Recipe')
    
window_2 = tk.Tk()
window_2.title("Listbox with internal border")

main_frame = tk.Frame(window_2, bg='#FFD599', relief='sunken', bd=1)
main_frame.pack(fill='both', expand=True, padx=10, pady=10)

INTERIOR_BORDER = 10
output = tk.Listbox(main_frame, width=42, height=20, bd=0,
highlightthickness=0, bg = '#FFD599', fg = '#9A0615', selectmode='single')
output.pack(side='left', fill='both',expand=True, padx=INTERIOR_BORDER,
pady=INTERIOR_BORDER)
#output.place(x=210, y=195)
output.insert('end', *list_item_values)

yscroll1 = tk.Scrollbar(main_frame, command=output.yview,
orient='vertical')
yscroll1.pack(side='left', fill='y')
#yscroll1.place(x=463, y=196)

output.configure(yscrollcommand=yscroll1.set)
output.bind('<ButtonRelease-1>', getRecipe)

window_2.mainloop()
wuf :-)
Reply
#13
Hi wuf... I've tried this example and it will not work either. The Listbox does not display at all.
Here is the code as entered into my script:
INTERIOR_BORDER = 10
output = tkinter.Listbox(window_2, width=42, height=20, bd=0,
highlightthickness=0, bg = '#FFD599', fg = '#9A0615', selectmode='single')
output.pack(side='left', fill='both',expand=True, padx=INTERIOR_BORDER,
pady=INTERIOR_BORDER)
#output.place(x=210, y=195)

yscroll1 = tkinter.Scrollbar(window_2, command=output.yview,
orient='vertical')
yscroll1.pack(side='left', fill='y')
#yscroll1.place(x=463, y=196)

output.configure(yscrollcommand=yscroll1.set)
output.bind('<ButtonRelease-1>', getRecipe)
I changed the following:
main_frame to window_2 as required
removal of "listbox.insert('end', *list_item_values)" as required

It will not display without pack along with place.
if either one is not present the widget does not display.
"Often stumped... But never defeated."
Reply
#14
Quote:It will not display without pack along with place.
Get it into your head, this is illegal! It will come back and bite you, probably someplace totally unrelated.
There is another reason why it's not displaying. I'll take a closer look at in the AM unless someone has already done it,
but I'm done for the day.

Simply Don't do it!
Reply
#15
Larz, it is noted and I'll make the required change in my train of thought when writing.

I'll see about making the changes to the code to use 1 instead of both.
"Often stumped... But never defeated."
Reply
#16
Hi my dear friend DT2000

Could you please present your complete code snippet, wich is executable. Pack mixed with Place is a captital offence. To get it working correctly you need the main_frame as container for the listbox.

wuf :-)
Reply
#17
ditto
Reply
#18
Here is the window_2 portion of the code. I have removed a few lines regarding the image used for the background and the binding for clicking the items from the query to load the actual recipe (line 94). I have also changed the code to remove the pack() and I have only used place() as you have pointed out.

import os
import tkinter
import sqlite3
import win32print
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
#===================================== MAIN ====================================
def main():
#============================= CONNECT TO DATABASE =============================
    conn = sqlite3.connect('Recipe.db')
    c = conn.cursor()
#========================= CREATE DATABASE WITH TABLES =========================
    c.execute('''CREATE TABLE IF NOT EXISTS Recipes(
    Dish_Type CHAR(50),
    Recipe CHAR(50),
    Cook_Time CHAR(15),
    Serves CHAR(8),
    Ingredients CHAR(10000) ,
    Instructions CHAR(10000));''')
    conn.commit()

    c.execute('''CREATE TABLE IF NOT EXISTS Version(
    Welcome Decimal(10));''')
    conn.commit()

    c.execute('''CREATE TABLE IF NOT EXISTS Welcome(
    Welcome TEXT(2500));''')
    conn.commit()
#================================== WINDOW 2 ===================================
    window_2 = tkinter.Tk()
    window_2.title('Recipes')
    w = 1024
    h = 612
    ws = window_2.winfo_screenwidth()
    hs = window_2.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    window_2.geometry('%dx%d+%d+%d' % (w, h, x, y))
#================================ SELECT QUERY =================================
    def select():
        try:
            output.delete(0, END)
            selection = var.get()
            c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC',
            {'selection': selection})
            results = c.fetchall()
            for recipe, in results:
                output.insert(0,recipe)
        except:
            messagebox.showerror('Recipes', 'Failed to load category')
#================================ OPTION MENU ==================================
    var = tkinter.StringVar(window_2)
    var.set('Category')
    choices = [
        'Appetizers',
        'Beef',
        'Beverages',
        'Bakery',
        'Desserts',
        'Eggs',
        'Lamb',
        'Pasta',
        'Pork',
        'Potato',
        'Poultry',
        'Rice',
        'Salads',
        'Sandwiches',
        'Sauces/Dips',
        'Sea Food',
        'Slow Cooker',
        'Soups/Chili',
        'Stews',
        'Sushi',
        'Vegetables',
        'Vegetarian',
        'Wild Game']
    option = tkinter.OptionMenu(window_2, var, *choices)
    option.config(font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615')
    option.place(x=210, y=136)
    option['menu'].config(bg = '#F9F8D6', fg = '#9A0615')
    button = tkinter.Button(window_2, text='Load Category',
    font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615', command=select)
    button.place(x=362, y=139)
#=================================== WINDGETS ==================================
    output = tkinter.Listbox(window_2, font=('Times 10'), height = 20,
    width=42, bd=0, bg = '#FFD599', fg = '#9A0615', selectmode=SINGLE)
    output.place(x=210, y=195)
    yscroll1 = tkinter.Scrollbar(command=output.yview,
    orient=tkinter.VERTICAL)
    yscroll1.place(x=463, y=196)
    output.configure(yscrollcommand=yscroll1.set)
##    output.bind('<ButtonRelease-1>', getRecipe)
    window_2.mainloop()
if __name__ == '__main__':
    main()
"Often stumped... But never defeated."
Reply
#19
Hi DT2000

Thanks for presenting your complete script. I have replaced the 'place' instruction by 'pack' ones. Don't use 'place' for ordinary GUI applications. Try to enbed widget-groups in Frames. Also try to use classes for GUI-Applications.
Following i placed two scripts. The first one is not engaging the 'win32print'- and 'sqlite3'-module. The second includes these missing modules.
First script:
import os
#import tkinter
#import sqlite3
#import win32print
#from tkinter import *
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# Testdata for the listbox
TEST_DATA = list_item_values = ["one", "two", "three", "four", "five"]*5
# X&Y-Border for the listbox
INTERIOR_X_BORDER = 10
INTERIOR_Y_BORDER = 5

#===================================== MAIN ====================================
def main():
##============================= CONNECT TO DATABASE =============================
    #conn = sqlite3.connect('Recipe.db')
    #c = conn.cursor()
##========================= CREATE DATABASE WITH TABLES =========================
    #c.execute('''CREATE TABLE IF NOT EXISTS Recipes(
    #Dish_Type CHAR(50),
    #Recipe CHAR(50),
    #Cook_Time CHAR(15),
    #Serves CHAR(8),
    #Ingredients CHAR(10000) ,
    #Instructions CHAR(10000));''')
    #conn.commit()
 
    #c.execute('''CREATE TABLE IF NOT EXISTS Version(
    #Welcome Decimal(10));''')
    #conn.commit()
 
    #c.execute('''CREATE TABLE IF NOT EXISTS Welcome(
    #Welcome TEXT(2500));''')
    #conn.commit()
#================================== WINDOW 2 ===================================
    window_2 = tk.Tk()
    window_2.title('Recipes')
    w = 1024
    h = 612
    ws = window_2.winfo_screenwidth()
    hs = window_2.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    window_2.geometry('%dx%d+%d+%d' % (w, h, x, y)) 
#================================ SELECT QUERY =================================
    def select():
        try:
            output.delete(0, END)
            selection = var.get()
            c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC',
            {'selection': selection})
            results = c.fetchall()
            for recipe, in results:
                output.insert(0,recipe)
        except:
            messagebox.showerror('Recipes', 'Failed to load category')
#================================ OPTION MENU ==================================
    var = tk.StringVar(window_2)
    var.set('Category')
    choices = [
        'Appetizers',
        'Beef',
        'Beverages',
        'Bakery',
        'Desserts',
        'Eggs',
        'Lamb',
        'Pasta',
        'Pork',
        'Potato',
        'Poultry',
        'Rice',
        'Salads',
        'Sandwiches',
        'Sauces/Dips',
        'Sea Food',
        'Slow Cooker',
        'Soups/Chili',
        'Stews',
        'Sushi',
        'Vegetables',
        'Vegetarian',
        'Wild Game']
        
    main_frame = tk.Frame(window_2)
    main_frame.pack(expand=True)
    
    # Container for option-button & other buttons
    option_frame = tk.Frame(main_frame)
    option_frame.pack(fill=tk.X, pady=(0, 20))
    
    # Container for listbox-frame & y-scrollbar
    listbox_container_frame = tk.Frame(main_frame)
    listbox_container_frame.pack(fill=tk.BOTH)

    # Container for the listbox widget only
    listbox_frame = tk.Frame(listbox_container_frame, bg='#FFD599')
    listbox_frame.pack(side=tk.LEFT, fill=tk.BOTH)
            
    option = tk.OptionMenu(option_frame, var, *choices)
    option.config(font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615')
    #option.place(x=210, y=136)
    option.pack(side=tk.LEFT)
    option['menu'].config(bg = '#F9F8D6', fg = '#9A0615')
    
    button = tk.Button(option_frame, text='Load Category',
        font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615', command=select)
    #button.place(x=362, y=139)
    button.pack(side=tk.LEFT)
#=================================== WINDGETS ==================================
    output = tk.Listbox(listbox_frame, font=('Times 10'), height=20,
        width=42, bd=0, bg='#FFD599', fg='#9A0615', selectmode=tk.SINGLE,
        highlightthickness=0)
    #output.place(x=210, y=195)
    output.pack(fill=tk.BOTH, padx=INTERIOR_X_BORDER, pady=INTERIOR_Y_BORDER)
    
    yscroll1 = tk.Scrollbar(listbox_container_frame, command=output.yview,
        orient=tk.VERTICAL)
    #yscroll1.place(x=463, y=196)
    yscroll1.pack(side=tk.LEFT, fill=tk.Y)
    
    output.configure(yscrollcommand=yscroll1.set)
    
    # For testfill of the listbox only
    # Please insert here your own app specific list data !!!
    output.insert('end', *list_item_values)
    
##    output.bind('<ButtonRelease-1>', getRecipe)
    window_2.mainloop()
    
    
if __name__ == '__main__':
    main()
Second script:
import os
#import tkinter
import sqlite3
import win32print
#from tkinter import *
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# Testdata for the listbox
TEST_DATA = list_item_values = ["one", "two", "three", "four", "five"]*5
# X&Y-Border for the listbox
INTERIOR_X_BORDER = 10
INTERIOR_Y_BORDER = 5

#===================================== MAIN ====================================
def main():
#============================= CONNECT TO DATABASE =============================
    conn = sqlite3.connect('Recipe.db')
    c = conn.cursor()
#========================= CREATE DATABASE WITH TABLES =========================
    c.execute('''CREATE TABLE IF NOT EXISTS Recipes(
    Dish_Type CHAR(50),
    Recipe CHAR(50),
    Cook_Time CHAR(15),
    Serves CHAR(8),
    Ingredients CHAR(10000) ,
    Instructions CHAR(10000));''')
    conn.commit()
 
    c.execute('''CREATE TABLE IF NOT EXISTS Version(
    Welcome Decimal(10));''')
    conn.commit()
 
    c.execute('''CREATE TABLE IF NOT EXISTS Welcome(
    Welcome TEXT(2500));''')
    conn.commit()
#================================== WINDOW 2 ===================================
    window_2 = tk.Tk()
    window_2.title('Recipes')
    w = 1024
    h = 612
    ws = window_2.winfo_screenwidth()
    hs = window_2.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    window_2.geometry('%dx%d+%d+%d' % (w, h, x, y)) 
#================================ SELECT QUERY =================================
    def select():
        try:
            output.delete(0, END)
            selection = var.get()
            c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC',
            {'selection': selection})
            results = c.fetchall()
            for recipe, in results:
                output.insert(0,recipe)
        except:
            messagebox.showerror('Recipes', 'Failed to load category')
#================================ OPTION MENU ==================================
    var = tk.StringVar(window_2)
    var.set('Category')
    choices = [
        'Appetizers',
        'Beef',
        'Beverages',
        'Bakery',
        'Desserts',
        'Eggs',
        'Lamb',
        'Pasta',
        'Pork',
        'Potato',
        'Poultry',
        'Rice',
        'Salads',
        'Sandwiches',
        'Sauces/Dips',
        'Sea Food',
        'Slow Cooker',
        'Soups/Chili',
        'Stews',
        'Sushi',
        'Vegetables',
        'Vegetarian',
        'Wild Game']
        
    main_frame = tk.Frame(window_2)
    main_frame.pack(expand=True)
    
    # Container for option-button & other buttons
    option_frame = tk.Frame(main_frame)
    option_frame.pack(fill=tk.X, pady=(0, 20))
    
    # Container for listbox-frame & y-scrollbar
    listbox_container_frame = tk.Frame(main_frame)
    listbox_container_frame.pack(fill=tk.BOTH)
    
    # Container for the listbox widget only (used to get y-& x-pad for the
    # listbox interior
    listbox_frame = tk.Frame(listbox_container_frame, bg='#FFD599')
    listbox_frame.pack(side=tk.LEFT, fill=tk.BOTH)
    
    #listbox_container_frame = tk.Frame(listbox_frame, bg='#FFD599')
    #listbox_container_frame.pack(side=tk.LEFT, fill=tk.BOTH)
        
    option = tk.OptionMenu(option_frame, var, *choices)
    option.config(font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615')
    #option.place(x=210, y=136)
    option.pack(side=tk.LEFT)
    option['menu'].config(bg = '#F9F8D6', fg = '#9A0615')
    
    button = tk.Button(option_frame, text='Load Category',
        font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615', command=select)
    #button.place(x=362, y=139)
    button.pack(side=tk.LEFT)
#=================================== WINDGETS ==================================
    output = tk.Listbox(listbox_frame, font=('Times 10'), height=20,
        width=42, bd=0, bg='#FFD599', fg='#9A0615', selectmode=tk.SINGLE,
        highlightthickness=0)
    #output.place(x=210, y=195)
    output.pack(fill=tk.BOTH, padx=INTERIOR_X_BORDER, pady=INTERIOR_Y_BORDER)
    
    yscroll1 = tk.Scrollbar(listbox_container_frame, command=output.yview,
        orient=tk.VERTICAL)
    #yscroll1.place(x=463, y=196)
    yscroll1.pack(side=tk.LEFT, fill=tk.Y)
    
    output.configure(yscrollcommand=yscroll1.set)
    
    # For testfill of the listbox only
    # Please insert here your own app specific list data !!!
    output.insert('end', *TEST_DATA)
    
##    output.bind('<ButtonRelease-1>', getRecipe)
    window_2.mainloop()
    
    
if __name__ == '__main__':
    main()
Please study the scripts and try them out.
N.B. Whishing you a lot of fun with Tkinter & Python.

Greetings wuf :-)
Reply
#20
I appreciate you taking the time and I will certainly study what you have done here and I will try to implement this into my code and see what happens and I'll let you know what occurs.

I have a number of books in pdf format for python, tkinter and now wxPython but it can be difficult to decide which is best or the most useful. Each writing style varies and each has their own way to explain things, and in many case without actually explaining anything relevant or what is happening or should be happening when writing code.
I am always looking for more information or suggestions on what would be beneficial to read and things to learn for proper code structure.
"Often stumped... But never defeated."
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] Text Button - How Do I Reduce The Margin? vman44 6 11,037 Apr-27-2020, 10:48 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020