Home > Software engineering >  tkinter Highlight a row of a label table
tkinter Highlight a row of a label table

Time:02-20

I am trying to highlight an entire row of a table created with buttons.

The code already highlights the button the mouse is over, but I need to highlight not only this button, but also the entire row to emulate a real table.

I know this is easier to do with a tree view, but for multiple reasons in my GUI, I am forced to use a button based table instead of a tree view.

from tkinter import *

root = Tk()

class HoverButton(Button):
    def __init__(self, master, **kw):
        Button.__init__(self,master=master,**kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        self['background'] = self['activebackground']

    def on_leave(self, e):
        self['background'] = self.defaultBackground

columns = ("column 1","column 2","column 3", "column 4")
first_row = ("data 1", "data 2", "data 3", "data 4")

for columns_headings in range(len(columns)):
    l = HoverButton(root, text=columns[columns_headings], relief=RIDGE, activebackground="yellow")
    l.grid(row=0, column=columns_headings, sticky=NSEW)    

for first_row_data in range(len(first_row)):
    g = HoverButton(root, text=first_row[first_row_data], relief=RIDGE, activebackground="yellow")
    g.grid(row=1, column=first_row_data, sticky=NSEW)  

mainloop()

CodePudding user response:

If you will keep buttons on 2D list with rows and columns then you can simply access other buttons in the same row. Every button need also variable to keep its row number.

from tkinter import *

root = Tk()

class HoverButton(Button):
    
    def __init__(self, master, **kw):
        Button.__init__(self,master=master,**kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        #self['background'] = self['activebackground']
        for b in buttons[self.row_number]:
            b['background'] = self['activebackground']

    def on_leave(self, e):
        #self['background'] = self.defaultBackground
        for b in buttons[self.row_number]:
            b['background'] = self.defaultBackground

columns = ("column 1","column 2","column 3", "column 4")
first_row = ("data 1", "data 2", "data 3", "data 4")

buttons = []  # list 2D for all buttons

row = []
for columns_headings in range(len(columns)):
    l = HoverButton(root, text=columns[columns_headings], relief=RIDGE, activebackground="yellow")
    l.row_number = 0
    l.grid(row=0, column=columns_headings, sticky=NSEW)    
    row.append(l)
buttons.append(row)    
    
row = []
for first_row_data in range(len(first_row)):
    g = HoverButton(root, text=first_row[first_row_data], relief=RIDGE, activebackground="yellow")
    g.row_number = 1
    g.grid(row=1, column=first_row_data, sticky=NSEW)  
    row.append(g)
buttons.append(row)    

mainloop()

EDIT:

Version with more rows - which need extra for-loop.

import tkinter as tk  # PEP8: `import *` is not preferred

# --- classes ---  # PEP8: all classes directly after imports

class HoverButton(tk.Button):
    
    def __init__(self, master, **kw):
        super().__init__(master=master, **kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        #self['background'] = self['activebackground']
        for b in buttons[self.row_number]:
            b['background'] = self['activebackground']

    def on_leave(self, e):
        #self['background'] = self.defaultBackground
        for b in buttons[self.row_number]:
            b['background'] = self.defaultBackground

# --- main ---

root = tk.Tk()


columns = ("column 1","column 2","column 3", "column 4")
rows = [
    ("data A1", "data A2", "data A3", "data A4"),
    ("data B1", "data B2", "data B3", "data B4"),
    ("data C1", "data C2", "data C3", "data C4"),
]

buttons = []

row = []
for col_number, text in enumerate(columns):
    l = HoverButton(root, text=text, relief='ridge', activebackground="yellow")
    l.row_number = 0
    #l.col_number = col_number
    l.grid(row=0, column=col_number, sticky='nsew')    
    row.append(l)
buttons.append(row)    
    
for row_number, row_data in enumerate(rows, 1):
    row = []
    for col_number, text in enumerate(row_data):
        g = HoverButton(root, text=text, relief='ridge', activebackground="yellow")
        g.row_number = row_number
        #g.col_number = col_number
        g.grid(row=row_number, column=col_number, sticky='nsew')  
        row.append(g)
    buttons.append(row)    

root.mainloop()

enter image description here

CodePudding user response:

You can do it by setting all the Labels in the same row as the one the mouse is over. I've added several rows of data to make things clearer.

Note that the header row highlights normally.

from tkinter import *

root = Tk()

class HoverButton(Button):
    def __init__(self, master, **kw):
        Button.__init__(self, master=master, **kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        row = e.widget.grid_info()['row']
        if not row:  # Header row?
            self['background'] = self['activebackground']
        else:
            for lbl in row_labels[row]:
                lbl['background'] = lbl['activebackground']

    def on_leave(self, e):
        row = e.widget.grid_info()['row']
        if not row:  # Header row?
            self['background'] = self.defaultBackground
        else:
            for lbl in row_labels[row]:
                lbl['background'] = lbl.defaultBackground


columns = ("column 1","column 2","column 3", "column 4")
rows = [("data 1A", "data 2A", "data 3A", "data 4A"),
        ("data 1B", "data 2B", "data 3B", "data 4B"),
        ("data 1C", "data 2C", "data 3C", "data 4C")]


# Create table of Labels.
row_labels = []  # List of lists of Labels.

labels = []
for j, column_heading in enumerate(columns):
    l = HoverButton(root, text=column_heading, relief=RIDGE, activebackground="yellow")
    l.grid(row=0, column=j, sticky=NSEW)
    labels.append(l)
row_labels.append(labels)

for i, row in enumerate(rows, start=1):
    labels = []
    for j, item in enumerate(row):
        g = HoverButton(root, text=item, relief=RIDGE, activebackground="yellow")
        g.grid(row=i, column=j, sticky=NSEW)
        labels.append(g)
    row_labels.append(labels)

root.mainloop()

Here's a screenshot:

screenshot

  • Related