How to display a label after another in same row using for loop with grid in tkinter in python?

Question:

What I want:
enter image description here and I can get it from long code my long code. However, I am trying to make it shorter through a loop (or anything suitable).

But I get enter image description here using the code below.

Also, why do arrows disappear when I try to encapsulate all code in a function. code with long function enter image description here

What I did trying to obtain desired output as above (image 1) but failed is several attempts:

from tkinter import *
import tkinter as tk
from tkinter import ttk

from PIL import Image, ImageTk
import pandas as pd
import numpy as np

tabel = pd.read_excel('testdata.xlsx', sheet_name='denied', index_col='Region')
print(tabel)
root = tk.Tk()
root.option_add("*Label*sticky", 'ew')

redDown = r"arrows/small-red-down.png"
redUp = r"arrows/small-red-up.png"
greenDown = r"arrows/small-green-down.png"
greenUp = r"arrows/small-green-up.png"
grayArrow = r"arrows/small-gray-right.png"

def arrowDenied(value=-0):
    if value < -0.5:
        arrow = ImageTk.PhotoImage(Image.open(greenDown))
    elif value > 0.5:
        arrow = ImageTk.PhotoImage(Image.open(redUp))
    else: arrow = ImageTk.PhotoImage(Image.open(grayArrow))
    return arrow

for i in range(4):
    counter     = 0
    for j in range(4):
        label = tk.Label(root, text=tabel.iloc[i][j]).grid(row=i,column=counter, sticky='news')
        counter+=1
        myimg1 = arrowDenied(tabel.iloc[i][j])
        panel12 = tk.Label(root, image = myimg1).grid(row=i, column=counter)
        counter+=1
        

root.mainloop()

I also tried replaced ‘counter’ with ‘j+1’, but that does not work. I realize the reason is when some widget is placed on ‘j’ the next widget will replace it because it was on the same place. I just could not figure out how to increment counter or j so that I can place arrows besides the values.

The testing data is as on this link excel file

Asked By: Jawad Mansoor

||

Answers:

You need to create those images (instances of PhotoImage()) only once instead of inside arrowDenied() function:

import tkinter as tk
import pandas as pd

tabel = pd.read_excel('testdata.xlsx', sheet_name='denied', index_col='Region')
print(tabel)

root = tk.Tk()
root.config(padx=10, pady=10)

#redDown = tk.PhotoImage(file="arrows/small-red-down.png")
redUp = tk.PhotoImage(file="arrows/small-red-up.png")
greenDown = tk.PhotoImage(file="arrows/small-green-down.png")
#greenUp = tk.PhotoImage(file="arrows/small-green-up.png")
grayArrow = tk.PhotoImage(file="arrows/small-gray-right.png")

def arrowDenied(value=0):
    return greenDown if value < -0.5 else redUp if value > 0.5 else grayArrow

# row labels
for i, txt in enumerate(tabel.index.values):
    lbl = tk.Label(root, text=txt, bg="pink", width=10, bd=1, relief="raised")
    lbl.grid(row=i+1, column=0, sticky="nsew")

# column headings
for i, col in enumerate(tabel.columns.values):
    lbl = tk.Label(root, text=col, bg="yellow", width=10, bd=1, relief="raised")
    lbl.grid(row=0, column=i*2+1, columnspan=2, sticky="nsew")

for i in range(4):
    for j in range(4):
        value = tabel.iloc[i][j]
        tk.Label(root, text=value).grid(row=i+1, column=j*2+1, sticky='e')
        myimg1 = arrowDenied(value)
        tk.Label(root, image=myimg1).grid(row=i+1, column=j*2+2, sticky='w')

root.mainloop()

Result:

enter image description here

Answered By: acw1668