Python Forum
Found buttonstate in tabs
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Found buttonstate in tabs
#1
Is a total beginner when it comes to Python and Tkinter. I have programmed a lot of C # and VB over the years and thought of learning a litle Python for a project. It's progressing slowly and the code can be optimized, I know, but one thing at a time. :)

I want to make an app with 4 tabs. On each side I will have a bunch of buttons, a total of 50 on different tabs. I want the buttons as arrays when they send a UDP command where a group value is changed. So I do not want to build 50 functions that take care of each button, but have a general function. I'am also building a function that collect my buttons information from a Helvar router so they update when we turn on lights from a button outside this "app".

When I use without tabs, it works the way I want with:
     button = buttons [int (i)]
     if button ['relief'] == 'raised':
When I use tabs, I can't find my button. "TypeError: 'NoneType' object is not subscriptable"

I don't need someone that rewrite my code, I only need to knew if it's possible and some hint what to search on net to found a solution. If you get everything served, you do not learn, but it can help to be pushed in any direction. :)

My test code scaled down:
from tkinter import *
from tkinter import ttk
import tkinter as tk

def on_tab_selected(event):
    global selected_tab 
    selected_tab = event.widget.select()
    print(selected_tab)

root = tk.Tk()
root.title("MainWindow")
root.geometry("800x480")
root.configure(bg='black')

tabControl = ttk.Notebook(root)
tabControl.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW')

s = ttk.Style()
s.configure('TNotebook.Tab', font=('Helvetica','15','bold') )

tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)
tab3 = ttk.Frame(tabControl)
tab4 = ttk.Frame(tabControl)

tabControl.bind("<<NotebookTabChanged>>", on_tab_selected)

tabControl.add(tab1, text =' Start ')
tabControl.add(tab2, text =' Arbetsljus ')
tabControl.add(tab3, text =' Blåljus ')
tabControl.add(tab4, text =' Övrigt ')

tabControl.pack(expand = 1, fill ="both")

class buttonFunction():
    def __init__(self,  row, column, groupOn, groupOff, text, onColor, offColor, onlyOff):
        self.row = row
        self.column = column
        self.groupOn = groupOn
        self.groupOff = groupOff
        self.text = text
        self.onColor = onColor
        self.offColor = offColor
        self.onlyOff = onlyOff

def setButtonInfo():
    # light(text, row, column, Grupp Tänd, Grupp släck, onColor, offColor, onlyOff)
    myButton.append(buttonFunction(0,0,801,701,"Plan 12\nMaskinrum",onWorkLight, offWorkLight, 1))
    myButton.append(buttonFunction(1,0,802,702,"Plan 12\nTågvind",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(2,0,801,701,"Plan 11\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(3,0,801,701,"Plan 10\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(4,0,801,701,"Plan 9\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(5,0,801,701,"Scen",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(6,0,801,701,"Scenkällare",onWorkLight, offWorkLight, 0))

# Colorvariable for buttons
markedLight = "#ff4040"
onWorkLight = "#FFFFE0"
offWorkLight = "#FF9030"
onBlueLight = "#E0FFFF"
offBlueLight = "#3090FF"

# Button-array
buttons = []

# Function-array
myButton = []

# STARTUP ORDER
setButtonInfo()

# Add button to table
for i in range(0, len(myButton)):
    buttons.append(None)
    buttons[i] = Button(tab1,
    text = myButton[i].text,
        command = lambda c = i: do_something(c),
        font="Helvetica, 12",
        bg=myButton[i].offColor,
        width="10", height="2",
        highlightthickness="2",
        highlightbackground=myButton[i].offColor ).place(x=int(myButton[i].row*100+200), y=int(myButton[i].column*100+200))

# When button is puched
def do_something(i):
    button = buttons[int(i)]
    if button['relief'] == 'raised' :
        if int(myButton[i].onlyOff) < 1 :
            button.configure(relief='sunken', bg=markedLight)
    else:
        button.configure(relief='raised', bg=myButton[i].offColor)


root = Root()
root.mainloop()
Reply
#2
Couple of hour later... Big Grin

This is what I'am looking for...

    button = buttons[int(i)]
    
    print(buttons[int(i)].cget('relief'))

    if buttons[int(i)].cget('relief') == 'raised' :
        if int(myButton[i].onlyOff) < 1 :
            button.configure(relief='sunken', bg=markedLight)
    else:
        button.configure(relief='raised', bg=myButton[i].offColor)
Reply
#3
When I run this:
import tkinter as tk

root = tk.Tk()
b1 = tk.Button(text='Button 1').pack()
b2 = tk.Button(text='Button 2')
b2.pack()
print('b1', b1)
print('b2', b2)
root.mainloop()
it prints:
Output:
b1 None b2 .!button2
b1 is None because .pack() (and .place() and .grid()) is a function that returns None. So when you create buttons like this:
    buttons[i] = Button(tab1,
    text = myButton[i].text,
        command = lambda c = i: do_something(c),
        font="Helvetica, 12",
        bg=myButton[i].offColor,
        width="10", height="2",
        highlightthickness="2",
        highlightbackground=myButton[i].offColor ).place(x=int(myButton[i].row*100+200), y=int(myButton[i].column*100+200))
You are putting None in myButton[i].

What you report as a fix does nothing to fix your code. if your code is working now you must have split up making your buttons and placing your buttons.

As an aside, you should avoid using .place(). Using .place() results in windows that cannot be resized and layouts that are difficult to modify.
Learn how the geometry managers work (.pack() and .grid()).

As another aside, this makes no sense at all:
def setButtonInfo():
    # light(text, row, column, Grupp Tänd, Grupp släck, onColor, offColor, onlyOff)
    myButton.append(buttonFunction(0,0,801,701,"Plan 12\nMaskinrum",onWorkLight, offWorkLight, 1))
    myButton.append(buttonFunction(1,0,802,702,"Plan 12\nTågvind",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(2,0,801,701,"Plan 11\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(3,0,801,701,"Plan 10\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(4,0,801,701,"Plan 9\nBalkong",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(5,0,801,701,"Scen",onWorkLight, offWorkLight, 0))
    myButton.append(buttonFunction(6,0,801,701,"Scenkällare",onWorkLight, offWorkLight, 0))
Something like this makes sense if you are using a designer that creates a configuration file that you load into program to make the GUI. In your code it only creates extra (and confusing) variables and steps. if you want to add information to a button you should make your own button class. In this example I add your on and off colors and group information to tk.Button.
from tkinter import ttk
import tkinter as tk

# Colors for buttons
MARKEDLIGHT  = "#ff4040"
ONWORKLIGHT  = "#FFFFE0"
OFFWORKLIGHT = "#FF9030"
ONBLUELIGHT  = "#E0FFFF"
OFFBLUELIGHT = "#3090FF"

class MyTab(tk.Frame):
    def __init__(self, parent, text):
        super().__init__(parent)
        parent.add(self, text=text)

class MyButton(tk.Button):
    def __init__(
            self,
            parent,
            text='',
            row=0,
            column=0,
            groupOn=801,
            groupOff=701,
            onColor=ONWORKLIGHT,
            offColor=OFFWORKLIGHT,
            onlyOff=False,
            **kwargs):
        super().__init__(
            parent,
            text=text,
            width=10,
            height=2,
            bg=offColor,
            highlightthickness=2,
            highlightbackground=offColor,
            command=self.toggle_relief,
            **kwargs)
        self.place(x=row*100+200, y=column*100+200)
        self.onColor = onColor
        self.offColor = offColor
        self.groupOn = groupOn
        self.groupOff = groupOff
        self.onlyOff = onlyOff

    def toggle_relief(self):
        if self['relief'] != 'raised':
            self.configure(relief='raised', bg=self.offColor)
        elif not self.onlyOff:
            self.configure(relief='sunken', bg=MARKEDLIGHT)

root = tk.Tk()
root.title("MainWindow")
root.geometry("800x480")
root.configure(bg='black')

tabControl = ttk.Notebook(root)
tabControl.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW')

s = ttk.Style()
s.configure('TNotebook.Tab', font=('Helvetica','15','bold') )
tabs = [
    MyTab(tabControl, ' Start '),
    MyTab(tabControl, ' Arbetsljus '),
    MyTab(tabControl, ' Blåljus '),
    MyTab(tabControl, ' Övrigt ')
]
tabControl.pack(expand = 1, fill ="both")

MyButton(tabs[0], "Plan 12\nMaskinrum", row=0)
MyButton(tabs[0], "Plan 12\nTågvind", row=1, groupOn=802, groupOff=702)
MyButton(tabs[0], "Plan 11\nBalkong", row=2)
MyButton(tabs[0], "Plan 10\nBalkong", row=3)
MyButton(tabs[0], "Plan 9\nBalkong", row=4)
MyButton(tabs[0], "Scen", row=5)
MyButton(tabs[0], "Scenkällare", row=6)

root.mainloop()
I also made my own tab class that makes tabs a little easier to work with.

If you want to write Python GUI code you should start with learning about classes and inheritance.
Reply
#4
As I wrote, i'am totaly newbee on Python. :)

The code I am working on is an experiment and will be rewritten when I have found all the functions I need to put together my project. I have a lot to learn and I need to rethink, both once and twice, both to get the code clear for others and more effective. The code may have a certain strange structure, but some things I do so that my editor can hide a lot of lines quickly so that I do not have to see things at the moment. :)

My way of thinking is that I should find a way that will make it easy for me to modify certain pieces and where I can experiment with colors etc. and that I should be able to add endless buttons. The button info is just dummy information but the content allows me to quickly move a button in the grid. I probably use some strange and unnecessary variables, but it is currently only to be able to easily change certain parameters. The code is far from complete. :)

It started with building the buttons around a grid (), but since I did not get it to work with certain bits when I added TABS, I had to throw out the buttons with ".place (x = row * 100 + 200, y = column * 100 + 200) "so that everyone would be visible. It's solved now and maybe that's why I was able to find my "buttons" even though I did not present a solution to the actual problem so that was what allowed me to move on and not get stuck.

When I solved the next thing I'am going to dive into your code and see what I can learn about it. :)
Reply
#5
If you are new to Python now is a great time to learn about classes. Spending a week learning about object oriented concepts will provide a greater return than toying with tkinter for a year.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  TabError: inconsistent use of tabs and spaces in indentation hobbyist 3 5,054 Jun-15-2021, 10:38 PM
Last Post: davide73_italy
  [Tkinter] Vertical Tabs Alignment in Tkinter muhammadasim 2 6,309 Oct-05-2020, 08:40 AM
Last Post: Larz60+
  [Tkinter] Need help please properly putting tabs within a PanedWindow JackMack118 2 3,501 Dec-08-2019, 03:02 PM
Last Post: balenaucigasa
  [PyQt] Drag items across tabs Alfalfa 5 4,977 Sep-01-2019, 11:58 PM
Last Post: Alfalfa
  [Tkinter] Adding space between Notebook tabs Columbo 4 4,718 Jul-10-2019, 10:46 PM
Last Post: Columbo
  [Tkinter] How to get a tabs works exactly same as google chrome sarthak260 0 3,900 Mar-07-2019, 10:45 AM
Last Post: sarthak260
  [Tkinter] How to create multilple tabs in tkinter from different classes Rishav 5 18,590 Jul-11-2018, 11:59 AM
Last Post: CCChris91
  How to create mutiple tabs in tkinter using oops Rishav 2 6,994 Jul-12-2017, 04:43 PM
Last Post: Rishav

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020