Background of tk.Frame() is covered by tk.Label() background - python

Original Code:
import tkinter as tk
from tkinter import ttk
win = tk.Tk()
home_frame = tk.Frame(win)
home_frame.grid(column = 0, row = 0)
home_frame.config(bg = 'blue', relief = 'raised')
logo = tk.Label(home_frame)
logo.grid(column = 0, row = 0)
logo.config(text = 'Widget', font = ('Helvetica', 30), fg = 'red')
win.config(bg ='white')
win.mainloop()
Note that:
home_frame.config(bg = 'blue', relief = 'raised')
From this, I would expect the background of the frame to turn blue, yet it doesn't. It remains grey.
Output:
As far as I'm concerned, tk.Frame() does have bg as an option.
Explanation:
If we do the following changes to logo background, we get the following:
Code:
logo.config(text = 'Widget', font = ('Helvetica', 30), bg = 'green', fg = 'red')
Also, adding another widget, like an entry widget, to home_frame will yield this:
Code:
search = tk.Entry(home_frame)
search.grid(column = 1, row = 0)
From the above, we can tell logo covers home_frame background.
Question:
How would you make logo background not cover home_frame background when logo background is not defined?
By this I mean:
logo.config(text = 'Widget', font = ('Helvetica', 30), fg = 'red') #No background option included.
In this case, I set logo background to blue. I want no bg option included in logo.config(). But still display an output as above.

Related

tkinter button color autochanging

root = Tk()
root.title('Tic-Tac-Toe by Ahmed')
root.geometry('500x500')
logo = PhotoImage(file = 'download.gif')
style = ttk.Style()
style.theme_use('clam')
print(style.theme_names())
style.configure('TButton', background = 'black', foreground = 'white', font = ('Arial', 30, 'bold'))
ttk.Label(root, text = 'Welcome to Tic-Tac-Toe by Ahmed', background = 'black', foreground = 'red', font = ('Arial',20,'italic'), anchor = 'center')\
.grid(row = 0, column = 1, sticky = 'ew')
playbtn = ttk.Button(root, text = 'Play')
playbtn.grid(row = 1, column = 1, sticky = 'snew')
root.call('wm','iconphoto',root,logo)
root.columnconfigure(1, weight = 1)
root.rowconfigure(1, weight = 2)
root.mainloop()
i've tried this code but the button color automatically change when i put the cursor on it, i've also tried to use (activebackground) but it still the same :/ , how to solve that ?
style.map("TButton", foreground=[('!active', 'white'), ('active', 'white')], background=[('!active', 'red'), ('active', 'red')], font = [('!active', ('Arial', 30, 'bold')), ('active', ('Arial', 30, 'bold'))])
it's ok, this code solved the problem ! :)

Cannot make that scroll bar shows frame untill the bottom

I am trying to create a pop up help window for a tool. I managed to add the scrollbar to a frame that contains canvas and label widget. However that Scrollbar does not shows the img_canvas_3 that I added.
Here is my code:
from tkinter import *
import tkinter.filedialog
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import PIL
from PIL import Image, ImageTk
help_window = tkinter.Tk()
help_window.title("Help")
help_window.geometry("400x800")
#frame.grid(row=0,column=0)
canvas=Canvas(help_window,bg='red',width=300,height=800,scrollregion=(0,0,500,500))
scroll_y = Scrollbar(help_window, orient="vertical", command = canvas.yview)
frame=Frame(canvas,width=300,height=800, bg="green")
description_label = Label(frame, text = "\n\tMy Tool\n",anchor = "w").pack(side = TOP, fill = "both")
introduction = "This tool provides a basic workflow"
introduction_text = Label(frame, text = introduction, anchor = "w", font = "Verdana 10", bg="yellow").pack(fill = "both")
label_1 = Label(frame, text = "Input Data 1", anchor = "w", font = "Verdana 10", justify=CENTER).pack(fill = "both")
img_canvas_1 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_1.pack(side = TOP)
label_2 = Label(frame, text = "Input Data 2", anchor = "w", font = "Verdana 10", justify = CENTER).pack(fill = "both")
img_canvas_2 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_2.pack(side = TOP)
label_3 = Label(frame, text = "Input Data 3", anchor = "w", font = "Verdana 10", justify = CENTER).pack(fill = "both")
img_canvas_3 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_3.pack(side = TOP)
canvas.create_window(0, 0, anchor = 'nw', window = frame)
canvas.update_idletasks
canvas.configure(scrollregion=canvas.bbox('all'),
yscrollcommand = scroll_y.set)
canvas.pack(fill = 'both', expand = TRUE, side = 'left')
scroll_y.pack(fill = 'y', side = 'right')
help_window.mainloop()
I expected to have the scroll bar working, basically showing all the widgets and elements in the frame as I am adding more and more. That is only true for the untill img_canvas_2
Does anyone have an idea why this is not the case with my code? I tried by playing around with the scrollregion parameter in the canvas variable, but it did not work.
Thanks in advance.

Multiple Buttons to change the colours of multiple labels TKINTER, PYTHON?

So I have multiple buttons
and i need the buttons of each name:
i.e. Violet button to turn the LABEL above it into violet,
and purple button to turn the above LABEL purple.
AND the reset button resets them all to grey.
AND if someone could fix my code so that the spacing of the "RESET" button is between purple and Blue (but still a row down), that'd be greatly appreciated.
WHAT MY CODE DOES NOW:
It turns all of the boxes all the colours.
How do I make it so when I press the one button, the one label changes colour AND I wish to do this in one function if possible (i've already thought of making multiple functions and thought this would be nicer).
Import the Tkinter functions
from tkinter import *
# Create a window
the_window = Tk()
# Give the window a title
the_window.title('MULTI Button Colour')
#Variables
window_font = ('Arial', 8)
button_size = 10
label_size = 7
margin_size_width = 10
margin_size_height = 2
label_violet = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_violet.grid(row = 0, column = 0)
label_purple = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_purple.grid(row = 0, column = 1)
label_blue = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_blue.grid(row = 0, column = 2)
label_green = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_green.grid(row = 0, column = 3)
def change_colour():
if violet_button:
label_violet['bg'] = 'violet'
if purple_button:
label_purple['bg'] = 'purple'
if blue_button:
label_blue['bg'] = 'blue'
if green_button:
label_green['bg'] = 'green'
# if reset_button:
# label_violet['bg'] = 'grey'
# label_purple['bg'] = 'grey'
# label_blue['bg'] = 'grey'
# label_green['bg'] = 'grey'
violet_button = Button(the_window, text = 'Violet', width = button_size,
font = window_font, command = change_colour)
purple_button = Button(the_window, text = 'Purple', width = button_size,
font = window_font, command = change_colour)
blue_button = Button(the_window, text = 'Blue', width = button_size,
font = window_font, command = change_colour)
green_button = Button(the_window, text = 'Green', width = button_size,
font = window_font, command = change_colour)
reset_button = Button(the_window, text = 'RESET', width = button_size,
font = window_font, command = change_colour)
#----------------------------------------------------------------
violet_button.grid(row = 1, column = 0, padx = margin_size_width, pady = margin_size_height)
purple_button.grid(row = 1, column = 1, padx = margin_size_width, pady = margin_size_height)
blue_button.grid(row = 1, column = 2, padx = margin_size_width, pady = margin_size_height)
green_button.grid(row = 1, column = 3, padx = margin_size_width, pady = margin_size_height)
reset_button.grid(row = 2, column = 1, pady = margin_size_height)
# Start the event loop to react to user inputs
the_window.mainloop()
This should do what you want:
def get_function(cmd):
def change_colour():
if 'violet' == cmd:
label_violet['bg'] = 'violet'
if 'purple' == cmd:
label_purple['bg'] = 'purple'
if 'blue' == cmd:
label_blue['bg'] = 'blue'
if 'green' == cmd:
label_green['bg'] = 'green'
if 'reset' == cmd:
label_violet['bg'] = 'grey'
label_purple['bg'] = 'grey'
label_blue['bg'] = 'grey'
label_green['bg'] = 'grey'
return change_colour
violet_button = Button(the_window, text = 'Violet', width = button_size,
font = window_font, command = get_function('violet'))
purple_button = Button(the_window, text = 'Purple', width = button_size,
font = window_font, command = get_function('purple'))
blue_button = Button(the_window, text = 'Blue', width = button_size,
font = window_font, command = get_function('blue'))
green_button = Button(the_window, text = 'Green', width = button_size,
font = window_font, command = get_function('green'))
reset_button = Button(the_window, text = 'RESET', width = button_size,
font = window_font, command = get_function('reset'))
For the issue with the reset button, just specifie the columnspan argument of the grid function:
reset_button.grid(row = 2, column = 1, pady = margin_size_height, columnspan = 2)
You have a lot of code in there that you copy / paste. Computers are really good at repeating things with a few variables changed. You could argue that that's ALL a computer is good at. So by doing that yourself, you are doing the computer's job. Also, you are making more work for your future self if you want to change something later. It's much better to put things in a single location, so that you can make a single change later instead of changing for every label. I can see you thought about this a little already since you have so many constants. Taking that one step further is to make a "constant" widget that all your instances copy from. It's a little advanced, but here's how you would do that:
import tkinter as tk
# Constants (aka variables that don't change during the program run)
BUTTON_SIZE = 10
FONT=('Arial', 8)
class Corey(tk.Frame):
'''a new widget that combines a Label and a Button'''
instances = []
def __init__(self, master=None, color='grey', **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.color = color
self.lbl = tk.Label(self, bg=color) # set initial color
self.lbl.grid(sticky='nsew') # sticky makes the label as big as possible
btn = tk.Button(self, text=color.title(), width=BUTTON_SIZE, command=self.colorize, font=FONT)
btn.grid()
self.instances.append(self)
def colorize(self):
self.lbl.config(bg=self.color)
#classmethod
def reset(cls):
for widget in cls.instances:
widget.lbl.config(bg='grey')
# Create a window
the_window = tk.Tk()
# Give the window a title
the_window.title('MULTI Button Colour')
# make some Corey widgets
colors = 'violet', 'purple', 'blue', 'green'
for col, color in enumerate(colors):
widget = Corey(the_window, color)
widget.grid(row=0, column=col, padx=10, pady=2)
reset_button = tk.Button(the_window, text = 'RESET', width=BUTTON_SIZE, command=Corey.reset, font=FONT)
reset_button.grid(row=1, column=0, columnspan=len(colors), pady=4)
the_window.mainloop()
The immediate advantage is that in order to add or subtract colors from my version, you only have to change one line. Also, if you want to change the appearance, say add a relief or change the button to a checkbox, again you only have to change a single line. Subclasses like this are a huge part of GUI design, I recommend you jump into this as soon as you can.

Tkinter: Creating a static frame size inside a pre-existing frame window

I have an app that has a frame which houses a gridview of information regarding product data. I want frame3 to have a static window size with a scroll bar. The scroll bar, not implemented yet, will allow the user to scroll down to see the remaining product data not visibly seen inside the static window.
My problem is that frame3 as of right now, doesn't seem to have a visible, static frame size. It just looks like it takes up one row in my overall app gridview, as seen in the picture:
picture of current program
I would like the "Bar Code - Product Description ..." section to acquire most of the screen real-state of the app but i can't seem to get it to work. I've tried creating a canvas inside frame3 but it still doesn't work.
Any ideas?
The code below is just a short snippet of my overall application
frame3 = Frame(self, bg = "black", width = 690, height = 400, borderwidth = 1)
frame3.pack()
frame3Label1 = tk.Label(frame3, text="Bar Code", font=NORMAL_FONT, relief = SUNKEN, width = 16)
frame3Label1.grid(row = 0, column = 0)
frame3Label2 = tk.Label(frame3, text="Product Description", font=NORMAL_FONT, relief = SUNKEN, width = 30)
frame3Label2.grid(row = 0, column = 1)
frame3Label3 = tk.Label(frame3, text="Price", font=NORMAL_FONT, relief = SUNKEN, width = 10)
frame3Label3.grid(row = 0, column = 2)
frame3Label4 = tk.Label(frame3, text="Quantity", font=NORMAL_FONT, relief = SUNKEN, width = 8)
frame3Label4.grid(row = 0, column = 3)
frame3Label5 = tk.Label(frame3, text="Discount", font=NORMAL_FONT, relief = SUNKEN, width = 8)
frame3Label5.grid(row = 0, column = 4)
frame3Label6 = tk.Label(frame3, text="Cost", font=NORMAL_FONT, relief = SUNKEN, width = 10)
frame3Label6.grid(row = 0, column = 5)
#Function that creates more labels/entry boxes under these static existing labels
frame3.pack(expand=True)
I just used the expand property as per mentioned in a comment

Tkinter PIL image not displaying inside of a function

I am using Tkinter to display images in a Toplevel() but when I put it inside of a function it doesn't work(This is very beginner I know)
# -*- coding: utf-8 -*-
import Tkinter
from Tkinter import *
import tkMessageBox
from tkMessageBox import *
import Image, ImageTk
import PIL.Image, PIL.ImageTk
import os
import subprocess
root = Tk()
root.title("Test")
quin=Toplevel()
C = Tkinter.Canvas(quin, bg="white", height = 350, width = 350)
directory=os.path.dirname(os.path.abspath(__file__))
filename=os.path.join(directory, 'un.png')
img=PIL.Image.open(filename)
tkimg=PIL.ImageTk.PhotoImage(img)
image = C.create_image(175,175,image=tkimg)
C.grid(row=5,column=5)
def Head():
h1 = Label(root, text = "How to Secure a Computer", fg ="white", bg = "#00b8ff", width = 6,bd=2, height =2, font = "Arial", relief = RAISED)
h1.grid(row= 0, column = 0, ipadx=122, pady=3, padx=5,columnspan=3)
def Mainmenu():
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=root.destroy)
menubar.add_cascade(label="Options", menu=filemenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_radiobutton(label="Help")
helpmenu.add_radiobutton(label="User Manual Security Configuration Guide")
menubar.add_cascade(label="Help", menu=helpmenu)
root.config(menu=menubar)
def Mainbuttons():
B1=Button(root,text="Services",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff",command=Services)
B2=Button(root,text="Account Policies",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B3=Button(root,text="Firewall Config",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B4=Button(root,text="User Logon Time",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B5=Button(root,text="Security Policies",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B1.grid(row = 1, column = 0, ipadx=120,pady=2,padx=5)
B2.grid(row = 1, column = 1, ipadx=120,pady=2,padx=5)
B3.grid(row = 2, column = 1, ipadx=120,pady=2,padx=5)
B4.grid(row = 2, column = 0, ipadx=120,pady=2,padx=5)
B5.grid(row = 3, column = 0, ipadx=120,pady=2,padx=5)
def Services():
serv=Toplevel()
servcanv=Canvas(serv,height=250, width=250)
servtext=Text(serv,width=26)
servtext.insert(INSERT, "To start go to your start menu, in the search bar\ntype services.msc")
servtext.grid(row=0, column=0)
servcanv.grid(row=0, column=1)
s = Tkinter.Canvas(serv, bg="white", height = 350, width = 350)
directory=os.path.dirname(os.path.abspath(__file__))
filename=os.path.join(directory, 'un.png')
img=PIL.Image.open(filename)
tkimg=PIL.ImageTk.PhotoImage(img)
image=s.create_image(175,175,image=tkimg)
s.grid(row=5,column=5)
Mainmenu()
Mainbuttons()
Head()
root.mainloop()
As you can see the code used to display the image is used twice, once inside a function and once outside. When outside it works perfectly, but when inside it doesn't work, it says the variable image is assigned but never used.
It does not work inside function, since tkimg is garbage collected after function finishes. You need to bind your images into variables that wont be garbage collected. For example to global variables, or instance variables in a class, rather than local variables.
To make tkimg be able to write to the global tkimg use global tkimg in the function.

Categories