0

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

  • [This](https://stackoverflow.com/q/16424091/11106801) is the reason for the arrows not showing when you have a function. Also rn you are creating a new `PhotoImage` for each arrow. Instead create only 3 images and let the function just return one of those 3. – TheLizzard Feb 01 '23 at 12:56
  • quick note on `from tkinter import *` avoid wildcard imports: https://stackoverflow.com/questions/73698351/is-anyone-know-how-to-connect-tkinter-webcam-to-yolov5/73712541#73712541 – D.L Feb 01 '23 at 13:41

1 Answers1

1

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

acw1668
  • 40,144
  • 5
  • 22
  • 34
  • Thank you. I read comments here and other related questions, as well as answers of peers but it was difficult to understand without seeing example. Marking it as good answer. – Jawad Mansoor Feb 01 '23 at 17:50