Home > Mobile >  Efficient code for custom color formatting in tkinter python
Efficient code for custom color formatting in tkinter python

Time:12-29

So , I was trying to create a Periodic Table and its almost done from the exterior efficiently . However , I couldn't understand if there's any way I could fill in colors in individual buttons in the same fashion . Can anyone please help me regarding this ?

Below here is my code :

from tkinter import *

period_1 = ['H','','','','','','','','','','','','','','','','','He']
period_2 = ['Li','Be','','','','','','','','','','','B','C','N','O','F','Ne']
period_3 = ['Na','Mg','','','','','','','','','','','Al','Si','P','S','Cl','Ar']
period_4 = """K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr""".split(" ")
period_5 = """Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe""".split(" ")
period_6 = """Cs Ba * Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn""".split(" ")
period_6a = """La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu""".split(" ")
period_7 = """Fr Ra ** Rf D Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og""".split(" ")
period_7a = """Ac Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr""".split(" ")

root = Tk()
root.attributes('-fullscreen', True)
root.config(bg='black')

Button(root, text='EXIT', bg='red', fg='white', command=root.destroy).place(x=0, y=0)

canvas_a = Canvas(root, bg='black', width=350, height=50)
canvas_a.place(relx=0.15, rely=0.3)

canvas1 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas1.pack()

canvas2 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas2.pack()

canvas3 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas3.pack()

canvas4 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas4.pack()

canvas5 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas5.pack()

canvas6 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas6.pack()

canvas7 = Canvas(canvas_a, bg='black', width=350, height=50)
canvas7.pack()

canvas_b = Canvas(root, bg='black', width=350, height=50)
canvas_b.place(relx=0.265, rely=0.8)

canvas8 = Canvas(canvas_b, bg='black', width=350, height=50)
canvas8.pack()

canvas9 = Canvas(canvas_b, bg='black', width=350, height=50)
canvas9.pack()

class Table:
    def __init__(self):     
        for i in range(0,18):
            Button(canvas1, text=period_1[i], width=6, height=2).pack(side=LEFT)
            Button(canvas2, text=period_2[i], width=6, height=2).pack(side=LEFT)
            Button(canvas3, text=period_3[i], width=6, height=2).pack(side=LEFT)
            Button(canvas4, text=period_4[i], width=6, height=2).pack(side=LEFT)
            Button(canvas5, text=period_5[i], width=6, height=2).pack(side=LEFT)
            Button(canvas6, text=period_6[i], width=6, height=2).pack(side=LEFT)
            Button(canvas7, text=period_7[i], width=6, height=2).pack(side=LEFT)
        for i in range(0,15):
            Button(canvas8, text=period_6a[i], width=6, height=2).pack(side=LEFT)
            Button(canvas9, text=period_7a[i], width=6, height=2).pack(side=LEFT)
                
table1 = Table()

root.mainloop()

Further Notes : If anyone could tell me how I can color individual buttons (like green to halogens and blue to metals and red to hydrogen) and also to create toplevels for each button command , I would be grateful to him/her .

CodePudding user response:

I've rewrote your code with some better ways to create table. My idea was to pick out the buttons that fell onto a range of type and then loop through those buttons and change its color to those type.

from tkinter import *

period_1 = ['H' ,'','','','','','','','','','','','','','','','','He']
period_2 = ['Li','Be','','','','','','','','','','','B','C','N','O','F','Ne']
period_3 = ['Na','Mg','','','','','','','','','','','Al','Si','P','S','Cl','Ar']
period_4 = """K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr""".split(" ")
period_5 = """Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe""".split(" ")
period_6 = """Cs Ba * Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn""".split(" ")
period_7 = """Fr Ra ** Rf D Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og""".split(" ")

period_6a = """La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu""".split(" ")
period_7a = """Ac Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr""".split(" ")

# Making a list of main elements and secondary elements
main = period_1   period_2   period_3   period_4   period_5   period_6   period_7
sec  = period_6a   period_7a

# Colors for each group
non_m_col   = '#feab90'
alk_m_col   = '#ffe0b2'
alk_ea_col  = '#fecc81'
trans_m_col = '#d2c4e8'
halogen_col = '#a4d7a7'
metals_col  = '#feab90'
noble_g_col = '#fefffe'
act_col     = '#b2e5fd'
rare_m_col  = '#e7ee9a' 

root = Tk()

# Frame for the entire table
period_tab = Frame(root)
period_tab.pack()

# Frame for the main elements only
main_elem = Frame(period_tab)
main_elem.pack()

# Frame for the secondary elements only
sec_elem = Frame(period_tab)
sec_elem.pack(pady=10)

# Creating a 7x18 table of buttons and appending it to a 2D python list for main elements
buttons = []
for i in range(7):
    temp = []
    for j in range(18):
        but = Button(main_elem,text=main[18*i j],width=10,bg='#f0f0f0')
        but.grid(row=i,column=j)
        temp.append(but)
    buttons.append(temp)

# Creating a 2x14 table of buttons for secondary elements
for i in range(2):
    for j in range(14):
        if i == 0: # If row 1 then different color
            Button(sec_elem,text=sec[14*i j],width=10,bg=rare_m_col).grid(row=i,column=j)
        else:
            Button(sec_elem,text=sec[14*i j],width=10,bg=act_col).grid(row=i,column=j)
            
# Manually pick out main elements from the table
non_metals     = buttons[0][0],buttons[1][12:16],buttons[2][13:16],buttons[3][14:16],buttons[4][15]
alk_metals     = [row[0] for row in buttons[1:]]
alk_ea_metals  = [row[1] for row in buttons[1:]]
halogens       = [row[16] for row in buttons[1:]]
noble_gases    = [row[-1] for row in buttons[:]]
transition_met = [buttons[x][3:12] for x in range(3,7)]
metals         = buttons[6][12:16],buttons[5][12:16],buttons[4][12:15],buttons[3][12:14],buttons[2][12]
rare_metals    = [row[2] for row in buttons[3:6]]
actinoid       = buttons[-1][2]
plain_but      = buttons[0][1:-1],buttons[1][2:12],buttons[2][2:12]

# Change colors for those main element buttons
actinoid['bg'] = act_col
for i in alk_metals:    i['bg'] = alk_m_col
for i in alk_ea_metals: i['bg'] = alk_ea_col
for i in halogens:      i['bg'] = halogen_col
for i in noble_gases:   i['bg'] = noble_g_col
for i in rare_metals:   i['bg'] = rare_m_col

for i in transition_met:
    for j in i:
        j['bg'] = trans_m_col

for i in non_metals:
    if isinstance(i,list):
        for j in i:
            j.config(bg=non_m_col)
    else:
        i.config(bg=non_m_col)

for i in metals:
    if isinstance(i,list):
        for j in i:
            j.config(bg=metals_col)
    else:
        i.config(bg=metals_col)
 
for i in plain_but:
    for j in i:
        j['relief'] = 'flat'

Button(root,text='EXIT',command=root.destroy).pack(pady=10)

root.mainloop()

I've commented the code to make it more understandable. The slicing part might seem a bit complicated because python list does not support 2D slicing. One way is to create a numpy array and store the coordinates onto it and then retrieve the respective button object based on coordinate, might be longer code but it would make the slicing more easier and understandable as numpy supports 2D slicing.

  • Related