Tkinter background color issue at scrollbar - python-3.x

I am working on a tkinter script which has a vertical and horizontal scrollbar.
A portion of the window below the vertical scrollbar is not picking up the background color I'm applying.
I have tried the following color options still the small portion is not picking up.
Image:
Sample window snapshot
Full Code:
from tkinter.tix import *
from tkinter import *
import collections
root = Tk()
root.configure(background='steel blue')
# Global variables
fname = ''
# Variables for setting the height and width of widget
# Variables to set Height
actualRootHeight = 300
rootHScale = 25
rootHOffset = 100
canvasHeight = 300
root2CanvasHMargin =65
# Variables to set Width
rootWScale = 10
rootWOffset = 200
canvasWidth = 300
root2CanvasWMargin = 20
inpWidth = 0
# Lists to save configs
inpParamList = collections.OrderedDict()
paramListRef = collections.OrderedDict()
updatedParamList = collections.OrderedDict()
entryList = []
labels = []
# All widget coding is done here
class guiList(Frame):
global root
# Constructor - Use as a control structure
def __init__(self,parent):
Frame.__init__(self,parent)
self.parent = parent
self.readParams()
self.setGeometry()
self.initUI()
self.controlUI()
def onFrameConfigure(self, event, Canvas1):
# Reset the scroll region to encompass the inner frame
Canvas1.configure(scrollregion=Canvas1.bbox("all"), background='steel blue')
# All widget edition is done here
def initUI(self):
global paramListRef
titleStr = sys.argv[1]
self.parent.title(titleStr)
self.grid(row=0, column=0)
inpConfigs = inpParamList.items()
# Add a canvas and call Frame as it's child widget
# Scrollbar can be added to Canvas
Canvas1 = Canvas(self, width=canvasWidth, height=canvasHeight, borderwidth=0, bg="light steel blue")
vsb = Scrollbar(self, orient="vertical", command=Canvas1.yview, bg="light steel blue", troughcolor="steel blue", highlightcolor="light steel blue", activebackground="light steel blue", highlightbackground="light steel blue")
Canvas1.configure(yscrollcommand=vsb.set)
vsb.grid(column=2, sticky='NS')
hsb = Scrollbar(self, orient="horizontal", command=Canvas1.xview, bg="light steel blue", troughcolor="steel blue")
Canvas1.configure(xscrollcommand=hsb.set)
hsb.grid(column=0, sticky='EW')
Canvas1.grid(row=0, column=0, sticky='NWES')
# Create new Frame for input configs
Frame1 = Frame(Canvas1, width=canvasWidth, height=canvasHeight, bg="light steel blue")
Canvas1.create_window((1,1),window=Frame1, anchor="nw", tags="Frame1")
Frame1.bind("<Configure>", lambda event, arg=Canvas1: self.onFrameConfigure(event, arg))
# Loop through the input configs
i = 0
# Add label and combobox in loop
for k,v in inpConfigs:
# Label widgets
lbl1 = Label(Frame1, text=k, bg="light steel blue", font=("Helvetica", 12, "bold"), fg="steel blue")
lbl1.grid(row = i, column = 0, padx=10, pady=5, sticky='W')
labels.append(lbl1)
# Combo-box widget for configurations
tkvar = StringVar(Frame1)
tkvar.set(v[0])
entry1 = OptionMenu(Frame1, tkvar, *v)
entry1.configure(width=20, anchor=W, bg="steel blue", fg="white", font=("Helvetica", 11, "bold"))
entry1.grid(row = i, column=1, padx=10, pady=5, sticky='E')
#entry1.grid_columnconfigure(2, weight=2)
paramListRef[k] = tkvar
i += 1
# Read the updated configs after the button click
def readUpdatedParams(self):
global updatedParamList
for k,v in paramListRef.items():
updatedParamList[k] = v.get()
root.destroy()
self.writeBack()
# Seperate Frame for buttons
# Upon clicking read updted params
def controlUI(self):
Frame2 = Frame(self, bg="steel blue")
Frame2.grid(row=2, column = 0, sticky="EW")
b = Button(Frame2, text="OK", command=self.readUpdatedParams, bg="light steel blue", fg="steel blue", font=("Helvetica", 11, "bold"))
#b.grid(row=1, column=1, pady=10)
b.pack(fill="none", expand=True, pady = 10)
# Read the file and create a key, value pair for configs
# Lines in file is split with space as delimiter
# First column is the config name and rest are all possible value
def readParams(self):
global inpParamList
global inpWidth
f = open(fname)
for line in f:
val = {}
val = line.split()
key = val.pop(0)
# Get the max width of key to adjust widget width
inpWidth = len(key) if (len(key) > inpWidth) else inpWidth
inpParamList[key] = val
# Geometry ( X-width x Y-width + X-position + Y-position)
# Based on the number of elements in the config list
# the height of the widget is set (Max is 75% of screen size)
def setGeometry(self):
global actualRootHeight
global canvasWidth
global canvasHeight
listLen = len(inpParamList)
rootWinwidth = int(inpWidth *rootWScale) + rootWOffset
rootWinheight = (listLen * rootHScale ) + rootHOffset
screenWidth = self.winfo_screenwidth()
screenHeight = int(self.winfo_screenheight() * 0.75)
if rootWinheight < screenHeight :
actualRootHeight = rootWinheight
else :
actualRootHeight = screenHeight
canvasWidth = rootWinwidth - root2CanvasWMargin
canvasHeight = actualRootHeight - root2CanvasHMargin
rootWinresolution = str(rootWinwidth)+'x'+str(actualRootHeight)+'+'+'0'+'+'+'0'
root.geometry(rootWinresolution)
# Sub routine to write back the config file.
def writeBack(self):
fr = open("bt_top.param.config",'w')
for k,v in updatedParamList.items():
print(k,v)
fr.write(k)
fr.write(" ")
fr.write(v)
fr.write("\n")
fr.close()
# Main Function
# Define Window geometry and other top level stuff here
# Do not go into widget coding here
def main():
global fname
# Get File name from command line argument
fname = sys.argv[2]
app = guiList(root)
root.mainloop()
# The __name__ variable decides what to run
# Below lines make this file run stand-alone
if __name__ == '__main__':
Any suggestions are welcome. Thanks
-Vinay

The piece of black is the background of self, your guiList class. Add a line self.config(bg="steel blue") to its __init__() function (or to initUI() I suppose) to fix it.

Related

All other widgets are affected when one of the widgets move in a GUI (using the tkinter library in python 3)

Whenever I try to move individual widgets or click a button that produces words effectively moving other widgets that had nothing to do those both specified actions above.
Here is my code:
import tkinter as tk
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background = "#777474")
def calculate_price():
global input_field
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input* 0.1
answer.config(text = (f"Your price is ","%.3f"%price,"KWD"))
except ValueError as ve:
answer.config(text = 'What you have just entered are not numbers whatsoever, try again!', fg = "#CD5F66")
price_input = tk.Label(window, text = "Total Pages:", font = "Arial", bg = "#777474", fg = "#FEFCF2")
price_input.grid(column = 0, row = 0)
input_field = tk.Entry(window, font = "Arial", bg = "#FEFCF2")
input_field.grid(column = 1, row = 0, padx = 0,pady = 10)
answer = tk.Label(window, bg = "#777474")
answer.grid(pady = 20)
button_return = tk.Button(window, text = "Calculate Price", command = calculate_price).grid()
# Run the main loop
window.mainloop()
This is my GUI before I click on the button which is called "Calculate Price":
This is my GUI after I have clicked on the button:
The problem here is that I don't want the Total Pages and the entry field to move away from each other whenever I click on the button.
I would suggest to put price_input and input_field into a frame for easier layout management. I also use sticky="w" on the frame, answer and button_return so that they are aligned at the left.
Below is the modified code:
import tkinter as tk
FGCOLOR = "#FEFCF2"
BGCOLOR = "#777474"
ERRCOLOR = "#FF5F66"
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background="#777474")
def calculate_price():
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input * 0.1
answer.config(text=f"Your price is {price:.3f} KWD", fg=FGCOLOR)
except ValueError as ve:
answer.config(text='What you have just entered are not numbers whatsoever, try again!', fg=ERRCOLOR)
# create a frame for price_input and input_field
frame = tk.Frame(window, bg=BGCOLOR)
frame.grid(column=0, row=0, padx=10, pady=10, sticky="w")
price_input = tk.Label(frame, text="Total Pages:", font="Arial", bg=BGCOLOR, fg=FGCOLOR)
price_input.grid(column=0, row=0)
input_field = tk.Entry(frame, font="Arial", bg=FGCOLOR)
input_field.grid(column=1, row=0)
answer = tk.Label(window, bg=BGCOLOR)
answer.grid(column=0, row=1, padx=10, pady=10, sticky="w")
button_return = tk.Button(window, text="Calculate Price", command=calculate_price)
button_return.grid(column=0, row=2, sticky="w", padx=10, pady=10)
# Run the main loop
window.mainloop()

Tkinter Scrollbar inactive untill the window is manually resized

The scrollbar activates only when the window is rezised, despite reconfiguring the scrollregion everytime a widget(Button in this case) is added.
class Editor:
def __init__(self,master):
self.master = master
self.master.resizable(True,False)
self.edit_frame = tk.Frame(self.master)
self.edit_frame.pack(fill="none")
self.elem_frame = tk.Frame(self.master,width=700)
self.elem_frame.pack(fill="y", expand=1)
self.my_canvas = tk.Canvas(self.elem_frame, width = 700)
self.my_canvas.pack(side = "left", fill="both", expand=1)
my_scrollbar = ttk.Scrollbar(self.elem_frame, orient = "vertical", command =self.my_canvas.yview)
my_scrollbar.pack(side = "right",fill="y")
self.my_canvas.configure(yscrollcommand=my_scrollbar.set)
self.my_canvas.bind('<Configure>', self.movescroll )
self.second_frame = tk.Frame(self.my_canvas, bg = "black", width=700)
self.my_canvas.create_window((0,0), window=self.second_frame, anchor="nw")
self.naz = Nazioni()
paesi = [*self.naz.iso3]
print(paesi)
self.comb_paese = ttk.Combobox(self.edit_frame, value = paesi)
self.comb_paese.current(1)
self.kwordvar= tk.StringVar()
entry_keyword = tk.Entry(self.edit_frame, textvariable=self.kwordvar)
entry_keyword.bind("<FocusOut>", self.callback)
writer = tk.Text(self.edit_frame)
self.edit_frame.pack(side="left")
writer.pack()
self.comb_paese.pack()
entry_keyword.pack()
def callback(self, *args):
kword = self.kwordvar.get()
self.colonnarisultati(kword)
def colonnarisultati(self, keyword):
#TROVA IL VALORE CODICE ISO A 3CHAR IN BASE ALLA NAZIONE NEL COMBOBOX
p = self.comb_paese.get()
paese = self.naz.iso3[p]
ricerca = Ricerca(paese, keyword)
"""
for label in self.elem_frame.winfo_children():
label.destroy()
"""
self.count = 0
print("ciao")
for x in ricerca.listaricerca:
tit = str(x['titolo']).lstrip("<h4>").rstrip("</h4>")
print(tit)
self.elementotrovato(tit,self.count)
self.count +=1
self.my_canvas.configure(scrollregion=self.my_canvas.bbox("all"))
def movescroll(self, *args):
self.my_canvas.configure(scrollregion=self.my_canvas.bbox("all"))
def elementotrovato(self, testobottone, conta):
Bott_ecoifound = tk.Button(self.second_frame, text = testobottone,width = 100 ,height = 30, font = ("Helvetica", 12, "bold"), wraplength=200, justify="left")
print("CIAONE")
Bott_ecoifound.pack(fill="both", expand=1)
self.my_canvas.configure(scrollregion=self.my_canvas.bbox("all"))
The last method is the one adding button to the scrollable frame.
After the window is manually resized, no matter if back to its original size, the scrollbar activates and works fine.

Background Image Adjustment on Top Level Window with Tkinter

I have a basic GUI that begins with a main menu of sorts. I have successfully set a background image to that menu and it also scales when I change the dimension of the GUI window.
However when I try to define some top-level windows that are opened by the sub-menu items the background image does not appear (not to mention scale).
Not sure what I'm doing wrong but I'm attaching the code I wrote along with the images of the basic GUI.
from tkinter import *
from tkinter import ttk, font, messagebox
from PIL import ImageTk, Image
import os
root = Tk()
root.title("Decoder of ultrasound images to detect colon tumors")
# Adding window icon
root.iconbitmap('afekaImage.ico')
rootWidth, rootHeight = 600, 600
screenWidth = root.winfo_screenwidth()
screenHeight = root.winfo_screenheight()
topLeftPosition = (screenWidth / 2 - rootWidth / 2, screenHeight / 2 - rootHeight / 2)
# Configure window size
root.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
'''
# Create username & password entry
def entryDialog():
userName = entry1.get()
password = entry2.get()
if ((userName == 'Itzhak.Mamistvalov' and password == '311396832') or
(userName == 'AssafHasky' and password == '308333533')):
messagebox.showinfo('info', 'Correct Login')
else:
messagebox.showinfo('info', 'Invalid Login') '''
# open doc file
def openDocFile():
os.startfile("mid_sub.docx")
# adjusting background image to fit window
def adjustBackgroundImage(event):
# avoid garbage collection option 1
# global resizedBackgroundImage, newBackgroundImage
# ----------
width = event.width
height = event.height
resizedBackgroundImage = copyImage.resize((width, height))
newBackgroundImage = ImageTk.PhotoImage(resizedBackgroundImage)
label.config(image=newBackgroundImage)
# avoid garbage collection option 2
label.image = newBackgroundImage
# ----------
def createUserManualWindow(button_userManual):
global image1
userManualWindow = Toplevel(root)
def activateButtonUserManual():
button_userManual.configure(state="normal")
userManualWindow.destroy()
button_userManual.configure(state="disabled")
button_exit_userManualWindow = Button(userManualWindow, text="Exit", font=fontStyle,
command=lambda: [userManualWindow.destroy(), activateButtonUserManual()])
button_exit_userManualWindow.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.1)
# will occurs only when esc pressed
userManualWindow.protocol("WM_DELETE_WINDOW", activateButtonUserManual)
# ----------
userManualWindow.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
userManualWindow.iconbitmap('afekaImage.ico')
image1 = ImageTk.PhotoImage(Image.open('background.jpg'))
label1 = ttk.Label(userManualWindow, image=image1).pack()
label1.bind('<Configure>', adjustBackgroundImage)
label1.pack(fill=BOTH, expand=YES)
def createOverviewWindow(button_userManual):
overviewWindow = Toplevel(root)
def activateButtonOverview():
button_userManual.configure(state="normal")
overviewWindow.destroy()
button_userManual.configure(state="disabled")
button_exit_OverviewWindow = Button(overviewWindow, text="Exit", font=fontStyle,
command=lambda: [overviewWindow.destroy(), activateButtonOverview()])
button_exit_OverviewWindow.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.1)
# will occurs only when esc pressed
overviewWindow.protocol("WM_DELETE_WINDOW", activateButtonOverview)
# ----------
overviewWindow.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
overviewWindow.iconbitmap('afekaImage.ico')
# Define background image
image = Image.open('background.jpg')
copyImage = image.copy()
backgroundImage = ImageTk.PhotoImage(image)
label = ttk.Label(root, image=backgroundImage)
label.bind('<Configure>', adjustBackgroundImage)
label.pack(fill=BOTH, expand=YES)
# Configure font
fontStyle = font.Font(family="Segoe Script", size=10, weight=font.BOLD)
# Create buttons
button_userManual = Button(root, text="USER MANUAL", command=lambda: createUserManualWindow(button_userManual), font=fontStyle)
button_userManual.place(relx=0.4, rely=0.2, relwidth=0.2, relheight=0.1)
button_overview = Button(root, text="OVERVIEW", command=lambda: createOverviewWindow(button_overview), font=fontStyle)
button_overview.place(relx=0.4, rely=0.4, relwidth=0.2, relheight=0.1)
button_openDocFile = Button(root, text="DOC FILE", font=fontStyle, command=openDocFile)
button_openDocFile.place(relx=0.4, rely=0.6, relwidth=0.2, relheight=0.1)
button_quit = Button(root, text="Exit", font=fontStyle, command=root.destroy)
button_quit.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.1)
root.mainloop()
label1 = ttk.Label(userManualWindow, image=image1).pack() should be changed to:
label1 = ttk.Label(userManualWindow, image=image1)
label1.pack()
You should call label1.pack() before placing the "Exit" button, otherwise it will overlap/hide the "Exit" button. Or call label1.lower() after label1.pack().
label is used inside adjustBackgroundImage(), so even though you bind <configure> on label1 to adjustBackgroundImage(), it would not resize image shown by label1. Use event.widget instead of label inside adjustBackgroundImage():
def adjustBackgroundImage(event):
label = event.widget
# avoid garbage collection option 1
# global resizedBackgroundImage, newBackgroundImage
# ----------
width = event.width
height = event.height
resizedBackgroundImage = copyImage.resize((width, height))
newBackgroundImage = ImageTk.PhotoImage(resizedBackgroundImage)
label.config(image=newBackgroundImage)
# avoid garbage collection option 2
label.image = newBackgroundImage
# ----------

Scrollbar for Dynamically Created Widgets - Python Tkinter [duplicate]

This question already has answers here:
Adding a scrollbar to a group of widgets in Tkinter
(3 answers)
Closed 3 years ago.
I have a GUI that dynamically generates widgets based on the user selected number of systems:
GUI
These widgets are generated using a Callback function like the below sample of code:
class Window():
def __init__(self, master):
master.title('Production Analysis Tool')
# callback function to create entry boxes based on number of systems
self.L0 = Label(root, text="Equipment Parameters:", font = ('TKDefaultFont', 9, 'bold'))
self.L0.grid(row=3,column=0, sticky=W)
inverter_file = r'F:\CORP\PROJECTS\07599-A_Solar Development\Screening\_Production Analysis Tool\User Inputs\Inverter_Data.csv'
module_file = r'F:\CORP\PROJECTS\07599-A_Solar Development\Screening\_Production Analysis Tool\User Inputs\Module_Data.csv'
def update_scroll_region(event):
canvas.configure(scrollregion=canvas.bbox("all"))
def callback(*args):
dynamic_widgets = Frame(canvas)
canvas.create_window(0,0, anchor='nw', window = dynamic_widgets)
self.system_size = int(self.system_size_raw.get())
# Inverter Type
self.Lblank = Label(dynamic_widgets, text = "").grid(row=8, column=1, sticky=W)
self.L3 = Label(dynamic_widgets, text = "Inverter Type")
self.L3.grid(row=9, column=1, sticky=W)
global inverter_types # declare array as global parameter so it can be accessed outside function
inverter_types = []
for i in range(self.system_size):
inverter_list = get_inverter_list(inverter_file)
inverter_list = ["Select"] + inverter_list
self.inverter_types_raw = StringVar()
self.L3a = Label(dynamic_widgets, text = "System {}".format(i+1), font = ('Calibri', 10,'italic'))
self.L3a.grid(row=10+i, column=1, sticky=E)
self.widget = OptionMenu(dynamic_widgets, self.inverter_types_raw, *inverter_list, command = get_values_0)
self.widget.grid(row=10+i, column=2,sticky=EW)
inverter_types.append(self.widget)
dynamic_widgets.bind("<Configure>", update_scroll_region)
global inv_type
inv_type = []
def get_values_0(value):
inv_type.append(value)
button = tk.Button(root, text = "Store Values", font=('Calibri', 10,'italic'), bg = "SlateGray3",command = lambda:[gget_values_0()])
button.grid(row = 61, column = 2, columnspan=8, sticky = 'nesw')
# System Type
self.L1 = Label(root, text = "System Type")
self.L1.grid(row=4, column=1, sticky=W)
self.sys_type_raw = StringVar(root)
types = ['Select', 'Central Inverter', 'String Inverters']
self.popupMenu6 = OptionMenu(root, self.sys_type_raw, *types)
self.popupMenu6.grid(row=4, column=2, sticky=EW)
# Number of Systems
self.L2 = Label(root, text = "Number of Systems")
self.L2.grid(row=6, column=1, sticky=W)
self.system_size_raw = IntVar(root)
choices = list(range(1,50))
self.popupMenu2 = OptionMenu(root, self.system_size_raw, *choices)
self.popupMenu2.grid(row=6, column=2, sticky=EW)
self.system_size_raw.trace("w", callback)
vsb = Scrollbar(root, orient="vertical")
vsb.grid(row=8, column=6, sticky = 'ns')
canvas = Canvas(root, width = 600, height = 200)
vsb.config(command = canvas.yview)
canvas.configure(yscrollcommand=vsb.set)
canvas.grid(row=8,column=0)
# SITE ORIENTATION
self.L12 = Label(root, text="Site Orientation:", font = ('TKDefaultFont', 9, 'bold'))
self.L12.grid(row=66, column=0, sticky=W)
self.L13 = Label(root, text = "Module Tilt Angle (degrees)")
self.L13.grid(row=67, column=1, sticky=W)
self.modtilt_raw = Entry(master)
self.modtilt_raw.grid(row=67, column=2, sticky=EW)
self.L14 = Label(root, text = "Array Azimuth (degrees)")
self.L14.grid(row=68, column=1, sticky=W)
self.arraytilt_raw = Entry(master)
self.arraytilt_raw.grid(row=68, column=2, sticky=EW)
# SUBMIT INFORMATION
self.L27 = Label(root, text=" ").grid(row=84,column=1) # Add row of space
self.cbutton = tk.Button(root, text="SUBMIT",command = self.store_user_inputs, bg = "SlateGray3")
self.cbutton.grid(row=85, column = 0, columnspan=8, sticky = 'ew')
# STORE USER INPUT
def store_user_inputs(self):
self.system_size = np.float(self.system_size_raw.get())
# save all inputs as global parameters so they can be accessed as variables outside of GUI
global params
params = [self.system_type]
root = Tk()
root.configure()
window = Window(root)
root.mainloop()
I would like to place the dynamically generated widgets (Inverter Type, Modules per String, Strings per Inverter, Inverters per System, Module Type, and Max Current per System) into a scrollable frame.
I can post more code if needed.
A scrollable frame can be created by creating a Frame widget on a Canvas. An example is as follows:
vsb = Scrollbar(root, orient = VERTICAL)
vsb.pack(fill=Y, side = RIGHT, expand = FALSE)
canvas = Canvas(root, yscrollcommand=vsb.set)
canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
vsb.config(command = canvas.yview)
canvas.config(scrollregion = canvas.bbox("all"))
InverterType = Frame(canvas)
canvas.create_window(0, 0, anchor = NW, window = InverterType)
Now make sure to add all the widgets created in the callback function to this InverterType frame.
(TIP - replace root with InverterType)

tkinter - grid item won't move beyond column 0 on a scrollable Canvas

I am trying to mass populate items on a scrollable Canvas. When I create a function to create image labels and buttons, everything works fine if they are on column 0.
If I set it to column 1 however, it stays in the same place. I thought it would have something to do with the frame, so I tried changing the size of the frame, the size of the buttons etc. to be bigger and make the frame bigger as well making the canvas_window bigger. Nothing worked!
def onFrameConfigure(canvas):
canvas.configure(scrollregion=canvas.bbox("all"))
root = Tk()
canvas = Canvas(root, background="black", width=230)
frame = Frame(canvas, background="white")
vsb = Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)
canvas.pack(side="left", fill="both")
vsb.pack(side="left", fill="y")
canvas.create_window((0,0), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))
# --- Function that populates the frame
def standard_window(frame):
block_name = ["Ixalan", "Amonkhet", "Kaladesh"]
button_command = [test]
first_set_photo = ["ixalan.png", "amonkhet.png", "kaladesh.png"]
second_set_photo = ["ixalan.png", "hour.png", "aether_revolt.png"]
third_set_photo = []
set_1_count = 1
file_count = 0
count = 0
image_row = 0
while count < len(block_name):
photo = PhotoImage(file="{0}".format(first_set_photo[count]))
label = Label(frame, image=photo, fg="white", bg="black")
label.image = photo
label.grid(row=image_row, column=1)
Button(frame, text="{0} BLOCK".format(block_name[file_count]), font=("Helvetica", 8), fg="white", bg="black", command=test).grid(
row = set_1_count, column=0, columnspan=5)

Resources