Search code examples
pythoncustomtkinter

Is there a way to get "text" or "fg_color" value from custom Tkinter button widget?


I have a customtkinter (CTk) button widget that, when pressed, sends an encoded message to a client depending on the button's "text" value; in this case, if the button's text is "Off", it sends the message "On" and vice versa to the client.

import tkinter as tk
import traceback
import customtkinter as cust
import socket
from threading import Thread
from tkinter import messagebox

class GUI2(cust.CTk): #second window; not the root

    def __init__(self):

        super().__init__()

        self.PORT = 5000
        
        self.SERVER = socket.gethostbyname(socket.gethostname())
        
        self.ADDRESS = (self.SERVER, self.PORT)
       
        self.FORMAT = "utf-8"
        
        self.clients = [] #list to store all client connections
       
        self.server = socket.socket(socket.AF_INET,
                            socket.SOCK_STREAM)
        
        self.server.bind(self.ADDRESS)
        

        self.master2 = cust.CTkToplevel()
        
        self.ecdpower = cust.CTkButton(self.master2, text = "Off", fg_color = "Black", text_color = "White", hover_color = "Silver", command = lambda: Thread(target = self.startstream).start())
        self.ecdpower.grid(row = 0, column = 0) #button to send message to client connections
        
        self.thread = Thread(target = self.startChat)

        self.thread.start() #starts function to accept client connections
        
    def startChat(self): #function to accept client connections

        self.server.listen(30)

        try:

            while True:

                    self.conn, self.addr = self.server.accept()
                    
                    self.clients.append(self.conn) #stores all client connections

        except:

            pass 
            
    def startstream(self):

        
        try:

            if not self.clients: #checks if list is empty

                messagebox.showerror("No Connections!", "No clients connected to host!")

            else:

                for x in self.clients:

                    if self.ecdpower["text"] == "Off": #ecdpower button widget acts like a "power button"

                        self.ecdpower.configure(text = "On", fg_color = "Green")

                        x.send(("On").encode(self.FORMAT))

                    else:
                        
                        self.ecdpower.configure(text = "Off", fg_color = "Red")

                        x.send(("Off").encode(self.FORMAT))

        except:

            print (traceback.format_exc())    

Error is as follows:

Traceback (most recent call last):
  File "f:\project\mainmenu.py", line 390, in startstream
  File "F:\Program Files (x86)\Python\lib\tkinter\__init__.py", line 1681, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-text"

I have also tried if self.ecdpower.cget("text") == "Off: and tried other values like fg_color; both result in the same error. When I removed the if condition, the message sending works correctly so the only problem is how to verify the button "text" value.

Any help to fix this or possible other alternatives is greatly appreciated.


Solution

  • Per @jasonharper's comment above, CTkButton is

    not actually a Tkinter Button at all (it's made from a Frame containing a Canvas and a Label), so the normal Tkinter attribute-getting functions don't apply.

    Instead of using self.ecdpower["text"] or self.ecdpower.cget("text"): I should use

    self.ecdpower.text

    to get the CTKbutton's text value.

    The same can be applied with fg_color; use self.ecdpower.fg_color to get the value.