简体   繁体   中英

Make an editable table in PySimpleGUI?

Hello I am using a Table element from PySimpleGUI. I would like for the user to be able to edit the data inside it.

I have seen some mentions of it . Is it possible? This guy was using PySimpleGUIQt, while I am using the PySimpleGUI on top of tkinter.

It's much difficult for me to build it by pure PySimpleGUI code. If go it with new class inherited from sg.Table, some variables as argument or global variables not required. Here, colors of cell not considered in Entry.

All tkinter code in function edit_cell of following example.

import PySimpleGUI as sg
import random, string

# ------ Some functions to help generate data for the table ------
def word():
    return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
def number(max_val=1000):
    return random.randint(0, max_val)

def make_table(num_rows, num_cols):
    data = [[j for j in range(num_cols)] for i in range(num_rows)]
    data[0] = [word() for _ in range(num_cols)]
    for i in range(0, num_rows):
        data[i] = [i, word(), *[number() for i in range(num_cols - 1)]]
    return data

def edit_cell(window, key, row, col, justify='left'):

    global textvariable, edit

    def callback(event, row, col, text, key):
        global edit
        widget = event.widget
        if key == 'Return':
            text = widget.get()
            print(text)
        widget.destroy()
        widget.master.destroy()
        values = list(table.item(row, 'values'))
        values[col] = text
        table.item(row, values=values)
        edit = False

    if edit or row <= 0:
        return

    edit = True
    root = window.TKroot
    table = window[key].Widget

    text = table.item(row, "values")[col]
    x, y, width, height = table.bbox(row, col)

    frame = sg.tk.Frame(root)
    frame.place(x=x, y=y, anchor="nw", width=width, height=height)
    textvariable = sg.tk.StringVar()
    textvariable.set(text)
    entry = sg.tk.Entry(frame, textvariable=textvariable, justify=justify)
    entry.pack()
    entry.select_range(0, sg.tk.END)
    entry.icursor(sg.tk.END)
    entry.focus_force()
    entry.bind("<Return>", lambda e, r=row, c=col, t=text, k='Return':callback(e, r, c, t, k))
    entry.bind("<Escape>", lambda e, r=row, c=col, t=text, k='Escape':callback(e, r, c, t, k))

def main_example1():
    global edit

    edit = False
    # ------ Make the Table Data ------
    # sg.Print('Creating table...')
    data = make_table(num_rows=1_000, num_cols=6)
    # headings = [str(data[0][x])+'     ..' for x in range(len(data[0]))]
    headings = [f'Col {col}' for col in range(len(data[0]))]
    # sg.Print('Done creating table.  Creating GUI...')
    sg.set_options(dpi_awareness=True)
    layout = [[sg.Table(values=data, headings=headings, max_col_width=25,
                        auto_size_columns=True,
                        # display_row_numbers=True,
                        justification='right',
                        num_rows=20,
                        alternating_row_color=sg.theme_button_color()[1],
                        key='-TABLE-',
                        # selected_row_colors='red on yellow',
                        # enable_events=True,
                        # select_mode=sg.TABLE_SELECT_MODE_BROWSE,
                        expand_x=True,
                        expand_y=True,
                        enable_click_events=True,  # Comment out to not enable header and other clicks
                        )],
              [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')],
              [sg.Text('Cell clicked:'), sg.T(k='-CLICKED-')]]


    window = sg.Window('Table Element - Example 1', layout, resizable=True, finalize=True)

    while True:
        event, values = window.read()
        if event in (sg.WIN_CLOSED, 'Exit'):
            break
        elif isinstance(event, tuple):
            cell = row, col = event[2]
            window['-CLICKED-'].update(cell)
            edit_cell(window, '-TABLE-', row+1, col, justify='right')

    window.close()

main_example1()

在此处输入图像描述

I would strongly suggest use MutiLine for showing table, which is much simpler to manage and can be easily updated etc. The Same table effects can be achieved by less lines of code. Giving a sample code here from my own database program with uses Sqlite3 table.

def ViewTable (TableNme):
try: # LOAD TABLE FROM Sqlite3 Database
    txt2="SELECT * FROM {} ".format(TableNme)
    cursor.execute(txt2)
    ##Include headers###
    txt2='S.No '
    for j in fields: txt2=txt2+j +" "
    txt2=txt2+'\n'
    
    #converts the table into string separated by Comma
           #fine as long as table is not very massive running more than 3 Mbs, having more than 1000 records
    while True:
            h1=cursor.fetchone()
            if not h1: break
            for j in h1:txt2=txt2+str(j)+"   "
            txt2=txt2+'\n'
    #sg.popup('Archieved table', txt2)
    #Define text to load by text= before calling me
    layout2 = [[sg.Multiline(txt2,size=(28,28),key='-Items-'),],[sg.Ok()] ]
    sg.Window('Scroll to see the whole database', layout2,finalize=True).read(close=True)
    
except:
        sg.popup_error('Failed','Access denied or Memory full.')    

sg.Multiline 代替表格视图大大简化了您的代码。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM