tkinter - remove border / padding from gif button / label - python

I know there is a lot of info related to this question, but I cannot get any of it to work with my specific situation.
I'm trying to create a tkinter button menu out of gifs and I want these gifs to be flush up against one another, no border, no spacing. I've been able to achieve this with a regular button, but not with a button with an image file. I've attempted this with labels and there is no "border", but I still cant get rid of the padding, even after setting the relevant attributes to "0".
I'm aware of both the "bd" and the "highlightthickness" attributes and I'm pretty sure that the highlightthickness attribute is specific to the canvas widget, but I could be wrong? Either way, i've put it just about anywhere I can think and I still have this annoying border.
Can anyone point me in the right direction here? I'm a newbie to python and tkinter, but relatively comfortable with coding. This seems almost as straightforward as html tables, etc, but ive spent a couple nights scouring the internet and I can't find any answers, let alone any example of an image based button menu without spacing issues.
Apologies again for the newbie-ness of this dilemma. Any guidance will be greatly appreciated. Thanks!
code example using "Label" widget:
from Tkinter import *
root = Tk()
root.wm_title("Window Title")
root.config(background = "#FFFFFF")
leftFrame = Frame(root, width=600, height = 800, bd=0, highlightthickness=0)
leftFrame.grid(row=0, column=0, padx=0, pady=0)
try:
imageEx = PhotoImage(file = 'nav1.gif')
imageEx2 = PhotoImage(file = 'nav2.gif')
Label(leftFrame, image=imageEx).grid(row=1, column=0, padx=0, pady=0)
Label(leftFrame, image=imageEx2).grid(row=2, column=0, padx=0, pady=0)
except:
print("Image not found")
root.mainloop()
code example using "Button" widget:
import Tkinter as tk
button_flag = True
def click():
global button_flag
if button_flag:
button1.config(bg="white")
button_flag = False
else:
button1.config(bg="green")
button_flag = True
root = tk.Tk()
frame1 = tk.Frame(root)
frame1.pack(side=tk.TOP, fill=tk.X)
photo1 = tk.PhotoImage(file="nav1.gif")
button1 = tk.Button(frame1, compound=tk.TOP, width=320, height=55, image=photo1,
text="", bg='green', command=click, bd=0, highlightthickness=0)
button1.pack(side=tk.LEFT, padx=0, pady=0)
button1.image = photo1
frame2 = tk.Frame(root)
frame2.pack(side=tk.TOP, fill=tk.X)
photo2 = tk.PhotoImage(file="nav2.gif")
button2 = tk.Button(frame2, compound=tk.TOP, width=320, height=55, image=photo2,
text="", bg='green', command=click, bd=0, highlightthickness=0)
button2.pack(side=tk.LEFT, padx=0, pady=0)
button2.image = photo2
root.mainloop()

Related

grid layout just not aligning perfectly, even when following lecturer's code

I'm learning python doing a udemy course so its watching pre-recorded videos.
Following on recording laying out widgets on a screen (using tKinter) and just cannot get one button to align - even though I literally copy the code the lecturer has in the recording.
I am sure I am missing something really simple here. Everything lines up except the "Generate Password" button which is off to the right.
Its just a basic intro right now to GUI in Tkinter - so haven't gone into Frames as yet - just basic layouts.
Code is here - Everything aligns beautifully except the "Generate Password" button which shows up too far to the right - almost as if it is in another column...
from tkinter import *
def generate_pwd():
pass
def add_pwd():
pass
window = Tk()
window.title("Password Manager")
window.config(padx=50, pady=50)
# background canvas
canvas = Canvas(width=200, height=200)
img_lock = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=img_lock)
canvas.grid(column=1, row=0)
# widgets
lbl_website = Label(text="Website:")
lbl_website.grid(column=0, row=1, sticky=W)
lbl_email = Label(text="Email/UserName:")
lbl_email.grid(column=0, row=2, sticky=W)
lbl_password = Label(text="Password:")
lbl_password.grid(column=0, row=3, sticky=W)
ent_website = Entry(width=42)
ent_website.grid(column=1, row=1, columnspan=2, sticky=W)
ent_email = Entry(width=42)
ent_email.grid(column=1, row=2, columnspan=2, sticky=W)
ent_password = Entry(width=21)
ent_password.grid(column=1, row=3, sticky=W)
btn_generate = Button(text="Generate Password", command=generate_pwd)
btn_generate.grid(column=2, row=3)
btn_add = Button(text="ADD", width=35, command=add_pwd)
btn_add.grid(column=1, row=4, columnspan=2, sticky=W)
window.mainloop()
What I get:
From what I read, the width of a column is by default the width of its widest element; in your case, the culprit is the logo with its width of 100 that makes column 1 wider than it should be.
To fix this, just add a columnspan of 2 in your logo placement (in addition, the logo will be nicely centered):
...
canvas.create_image(100, 100, image=img_lock)
canvas.grid(column=1, row=0, columnspan=2)
...

tkinter centering two or more widgets

So I created a frame in which I want to put two widgets with them being centered on the x-axis. When it's one object pack() centers it automatically. But I can't figure out two widgets. I tried with grid() but there is free space left on the right which makes it look unsymetrical as seen in the image.
how could I get what is seen on the right? (I'd prefer it being dont with pack() but if there is a solution with grid() and/or place() as well i'd appreciate those as well!)
here's the code for the left picture
from tkinter import *
from tkinter import font
root = Tk()
root.geometry("500x500")
frame = Frame(root, bg="white", highlightbackground="black", highlightthickness=2)
frame.place(relwidth=0.5, relheight=0.5, relx=0.5, rely=0.5, anchor=CENTER)
label = Label(frame, bg="lime", text="label", font=font.Font(size=20))
label.grid(column=0, row=0)
button = Button(frame, bg="yellow", text="pressbutton", font=font.Font(size=20))
button.grid(column=1, row=0)
root.mainloop()
You can use frame.pack() to easily position the frame in the top, middle of its parent.
from tkinter import *
from tkinter import font
root = Tk()
root.geometry("500x500")
frame = Frame(root, bg="white", highlightbackground="black", highlightthickness=2)
frame.pack()
label = Label(frame, bg="lime", text="label", font=font.Font(size=20))
label.grid(column=0, row=0)
button = Button(frame, bg="yellow", text="pressbutton", font=font.Font(size=20))
button.grid(column=1, row=0)
root.mainloop()
You can put the label and button in another frame, and use pack() on that frame:
from tkinter import *
from tkinter import font
root = Tk()
root.geometry("500x500")
frame = Frame(root, bg="white", highlightbackground="black", highlightthickness=2)
frame.place(relwidth=0.5, relheight=0.5, relx=0.5, rely=0.5, anchor=CENTER)
frame2 = Frame(frame)
frame2.pack() # default side='top'
label = Label(frame2, bg="lime", text="label", font=font.Font(size=20))
label.pack(side='left', fill='both')
button = Button(frame2, bg="yellow", text="pressbutton", font=font.Font(size=20))
button.pack(side='left')
root.mainloop()

How can i attach my scroll bar to my text box on tkinter?

Im trying to use a vertical scrollbar for my text box but am coming across some problems:
I cant get the scroll bar to be directly touching the right side of the text box (so they are connected)
It seems the scroll bar wont affect my text box
I looked through some solutions but none seemed to work.
Heres my code:
from tkinter import *
writtenQ = Tk()
writtenQ.title("Written Response Question")
writtenQ.resizable(0,0)
header = LabelFrame(writtenQ, bg="white")
content = LabelFrame(writtenQ, bg="white")
header.columnconfigure(0, weight=1) # Forces column to expand to fill all available space
homeButton=Button(content,width=50,height=50)
try:
homeIcon=PhotoImage(file="yes.png")
homeButton.config(image=homeIcon)
homeButton.image = homeIcon
except TclError:
print("Home")
homeButton.grid(row=1, sticky="w", padx=15, pady=2)
#the image of the question will be put here
titleHeader = Label(content, text="Question Image here",pady=15, padx=20, bg="white", font=("Ariel",20, "bold"), anchor="w", relief="solid", borderwidth=1)
titleHeader.grid(row=2, column=0, columnspan=3, padx=15, pady=5, ipadx=370, ipady=150)
#this will allow the user to input their written response
answerInput = Text(content, width = 60, borderwidth=5, font=("HelvLight", 18))
answerInput.grid(row=3, column=0, ipady = 10, sticky="w", padx=(20,0), pady=20)
answerScrollBar= Scrollbar(content, command=answerInput.yview, orient="vertical")
answerScrollBar.grid(row=3, column=1, sticky="w")
submitButton = Button(content, borderwidth=1, font=("Ariel", 22), text="Submit", bg="#12a8e3", fg="black", activebackground="#12a8e3", relief="solid")
submitButton.grid(row=3, column=2, ipady=50, ipadx=70, sticky="nw", pady=20)
header.grid(row=0, sticky='NSEW')
content.grid(row=1, sticky='NSEW')
Configuring a scrollbar requires a two-way connection: the scrollbar needs to call the yview or xview method of the widget, and the widget needs to call the set method of the scrollbar.
Usually, this is done in three steps like in the following example:
answerInput = Text(...)
answerScrollBar= Scrollbar(..., command=answerInput.yview)
answerInput.configure(yscrollcommand=answerScrollBar.set)
You are forgetting the final step.
Unrelated to an actual functioning scrollbar, you're going to want to be able to see the scrollbar. You need to use sticky="ns" for the scrollbar so that it stretches in the Y direction. Otherwise it will only be a couple dozen pixels tall.
answerScrollBar.grid(row=3, column=1, sticky="ns")
Have you tried the solution here?
Let's say that the text widget is called text. Your code could be (excluding the setup of the window):
import tkinter
import tkinter.ttk as ttk
scrollb = ttk.Scrollbar(self, command=text.yview)
scrollb.grid(row=0, column=1, sticky='nsew')
text['yscrollcommand'] = scrollb.set
I have picked out what I think will be ueful for you from Honest Abe's answer. Hope it helped. Remember to set up your window before using the code...

Expanding the background image to fit window and stacking the frames over it in tkinter

I am trying to add a background image to my GUI app using tkinter. In the root window, I have two frames, named container_1 and container_2. When I am adding the background image, these framed are pushed outside the image. I can see them as the window size is higher than image size. If it is less, it isn't even visible. How can I make them place over the background image? Is it possible to give different background images for container_1 and container_2?
ans suggestions please.
(imgae in the comment link)
import tkinter as tk
def FnToShow():
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
def FnToHide():
container_2.pack_forget()
root = tk.Tk()
root.geometry('800x600')
#bg image
background_image=tk.PhotoImage(file= "bgPic.png")
background_label = tk.Label(root, image=background_image)
background_label.pack() # is pack problematic here?
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
settingBtn = tk.Button(container_1, text="Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text="Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text="Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text="close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
root.mainloop()
#setting background image
background_main_img=tk.PhotoImage(file= "bgMain.png")
background_main = tk.Label(root, image=background_main_img)
background_main.place(relx=.5, rely=.5, anchor="center")
#setting background image for container frame
background_con_1=tk.PhotoImage(file= "bgContainer.png")
background_label = tk.Label(container_1, image=background_con_1)
background_label.place(relx=.5, rely=.5, anchor="center")

How to add multiline text dynamically in tkinter python?

I have created a chat application, in which i use ListBox for showing the chat history. It looks good until I enter a long sting which goes beyond the screen. Is there a way to break the string and show in new line or any other way to show the complete string. I'm new to Tkinter and im not aware of many widgets available.
Here is my sample code
from tkinter import *
class Actions:
def chatUpdate(chat):
chatlist.insert(Actions.chatLast,chat)
Actions.chatLast=Actions.chatLast+1
chatlist.pack( side=LEFT, fill=BOTH)
chatBox.config(command=chatlist.yview)
def callUpdater():
txt=textBox.get()
text_text.set("")
Actions.chatUpdate(txt)
root = Tk()
root.title("Chat App")
frame1 = Frame(root, bd=4)
frame1.pack(side=TOP)
frame2 = Frame(root, bd=4)
frame2.pack(side=TOP)
frame3 = Frame(root, bd=4)
frame3.pack(side=TOP)
# chat box
chatBox = Scrollbar(frame1)
chatBox.pack(side=RIGHT, fill=Y)
chatlist = Listbox(frame1, yscrollcommand = chatBox.set, width=50)
Actions.chatLast=0
Actions.chatUpdate(" ")
# text box
textView = Label(frame2, text="Input: ")
textView.pack(side=LEFT)
text_text = StringVar()
textBox = Entry(frame2, textvariable=text_text, bd=0, width=40, bg="pink")
textBox.pack(side=RIGHT)
# send button
button = Button(frame3, text="Send", fg="black", command=callUpdater)
button.pack(side=TOP)
root.mainloop()
You can replace the Listbox by a Text widget in 'disabled' mode which automatically wraps long lines. You will just need to put the widget back in 'normal' mode each time you insert text:
from tkinter import *
def callUpdater():
text = textBox.get()
textBox.delete(0, 'end')
chat.configure(state='normal')
chat.insert('end', text + '\n')
chat.configure(state='disabled')
root = Tk()
chatBox = Scrollbar(root)
chat = Text(root, wrap='word', state='disabled', width=50,
yscrollcommand=chatBox.set)
chatBox.configure(command=chat.yview)
chat.grid(row=0, columnspan=2, sticky='ewns')
chatBox.grid(row=0, column=2, sticky='ns')
Label(root, text="Input: ").grid(row=1, column=0)
textBox = Entry(root, bd=0, width=40, bg="pink")
textBox.grid(row=1, column=1)
Button(root, text="Send", command=callUpdater).grid(row=2, columnspan=2)
root.mainloop()
By the way, both the Listbox and Text widgets support the index 'end' so you don't have to keep track of how many lines you have inserted.

Categories