PySimpleGUI, остановка цикла и его возобновление только после определённого события

Mu3aHTpoTT

Новичок
Пользователь
Ноя 16, 2021
5
0
1
1. Windows 10
2. Python 3.6
3.
import PySimpleGUI as sg
import numpy as np
import pandas as pd
import datetime
4. В моей программе существует цикл, который с помощью перебора данных таблицы PySimpleGUI находит выбранную кликом мыши строку:
Python:
for num in values['-TABLE-']:
                row_index = num
Данный цикл хорошо служит для удаления выбранной строки из таблицы(таблица изначально заполнена с помощью DataFrame библиотеки pandas):
Python:
  elif event == '-DELETE-':
            row_index = 0
            for num in values['-TABLE-']:
                row_index = num
            df = df.drop([row_index],axis=0)
            df = df.reset_index(drop=True)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)
однако при использовании его в функции кнопки изменения данных выдаёт ошибку по этому же самому циклу:
Python:
    elif event == '1-ADD-':
            row_index = 0
            for num in values['-TABLE-']:
                row_index = num
            fs = int(values['1-IN-5'])-int(values['1-IN-6'])*int(values['1-IN-5'])//100
            new_line={'Name':values['1-IN-1'],
                      'DateOfBirth':values['1-IN-2'],
                      'PhoneNumber':values['1-IN-3'],
                      'Position':values['1-IN-4'],
                      'Salary':values['1-IN-5'],
                      'RetentionPercentage':values['1-IN-6'],
                      'FinalSalary':fs}
            df1 = df.iloc[row_index]
            df = df.replace(df1, new_line)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)
            window3.close()
Ошибка:
File "C:\Users\Mu3aHTpoTT\Desktop\main.py", line 117, in <module>
for num in values['-TABLE-']:
KeyError: '-TABLE-'
Если присвоить переменной row_index какой-нибудь индекс собственноручно в коде, то всё работает хорошо: он изменяет данные строки по индексу, однако моя цель - чтобы индекс был присвоен выбором строки по клику мыши, что приводит к использованию того самого цикла, создающего ошибку. Мой полный код:
Python:
import PySimpleGUI as sg
import numpy as np
import pandas as pd
import datetime
df = [['              ','                ','                ','                 ','               ','                 ','                    ','                     ']]
df1 = np.array(df).tolist()
headings = ['Name','Date of birth','Phone number','Position','Salary','Retention percentage','Final Salary','Employment date']
sg.theme('darkgrey8')
def make_win1():
    layout = [
        [
         sg.Button('Add employee',size=(20,1),key='-ADD-',button_color='darkgreen'),
         sg.Button('Remove employee',size=(20,1),key='-DELETE-',button_color='darkred'),
         sg.Button('Change employee data',size=(25,1),key='-CHANGE-',button_color='darkorange'),
         sg.Text('                                                                     '),
         sg.Input(key='-FILEBROWSE-'),
         sg.FileBrowse('File browse',button_color='darkorange',file_types=(("csv Files", "*.csv"),)),
         sg.Button('Go', button_color='darkgreen'),       
         ],
        [sg.Table(values=df1,
                    headings=headings,
                    max_col_width=35,            
                    display_row_numbers=True,
                    justification='center',
                    alternating_row_color='grey',
                    key='-TABLE-',
                    size=(150,20),
                    enable_events=True,
                    row_height=30,
                    )],
        [sg.Button('Save',size=(20,1), button_color='darkgreen',key='-SAVE-')]
    ]
    return sg.Window('Employee accounting', layout,finalize=True)
def make_win2():
    l_col = sg.Column(
        [
        [sg.Text('Name'),sg.Input(key='0-IN-1', enable_events=True)],
        [sg.Text('Date of birth'),sg.Input(key='0-IN-2', enable_events=True)],
        [sg.Text('Phone number'),sg.Input(key='0-IN-3', enable_events=True)],
        [sg.Text('Position'),sg.Input(key='0-IN-4', enable_events=True)],
        [sg.Text('Salary'),sg.Input(key='0-IN-5', enable_events=True)],
        [sg.Text('Retention percentage'),sg.Input(key='0-IN-6', enable_events=True)],
        [sg.Button('OK',key='0-ADD-',button_color='darkgreen')]
        ],
        element_justification="right"   
)
    layout = [
        [l_col]
        ]
    return sg.Window('Add employee', layout, finalize=True)
def make_win3():
    l_col = sg.Column(
        [
        [sg.Text('Name'),sg.Input(key='1-IN-1', enable_events=True)],
        [sg.Text('Date of birth'),sg.Input(key='1-IN-2', enable_events=True)],
        [sg.Text('Phone number'),sg.Input(key='1-IN-3', enable_events=True)],
        [sg.Text('Position'),sg.Input(key='1-IN-4', enable_events=True)],
        [sg.Text('Salary'),sg.Input(key='1-IN-5', enable_events=True)],
        [sg.Text('Retention percentage'),sg.Input(key='1-IN-6', enable_events=True)],
        [sg.Button('OK',key='1-ADD-',button_color='darkgreen')]
        ],
        element_justification="right"   
)
    layout = [
        [l_col]
        ]
    return sg.Window('Change employee data', layout, finalize=True)
window1, window2, window3 = make_win1(), None, None 
while True:
    #try:
        window, event, values = sg.read_all_windows()
        if event == sg.WIN_CLOSED or event == 'Exit':
            window.close()
            if window == window2:     
                window2 = None
            elif window == window3:      
                window3 = None
            elif window == window1:   
                break
        elif event == 'Go':
            data = values['-FILEBROWSE-']
            df = pd.read_csv(data,delimiter=',')
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)     
        elif event == '-ADD-':
            window2 = make_win2()
        elif event == '0-ADD-':
            now = datetime.datetime.now()
            fs = int(values['0-IN-5'])-int(values['0-IN-6'])*int(values['0-IN-5'])//100
            new_line={'Name':values['0-IN-1'],
                      'DateOfBirth':values['0-IN-2'],
                      'PhoneNumber':values['0-IN-3'],
                      'Position':values['0-IN-4'],
                      'Salary':values['0-IN-5'],
                      'RetentionPercentage':values['0-IN-6'],
                      'FinalSalary':fs,
                      'EmploymentDate':now.date()}
            df = df.append(new_line, ignore_index=True)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)
            window2.close()
        elif event == '-DELETE-':
            row_index = 0
            for num in values['-TABLE-']:
                row_index = num
            df = df.drop([row_index],axis=0)
            df = df.reset_index(drop=True)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1) 
        elif event == '-CHANGE-':
            window3 = make_win3()
        elif event == '1-ADD-':
            row_index = 0
            for num in values['-TABLE-']:
                row_index = num
            fs = int(values['1-IN-5'])-int(values['1-IN-6'])*int(values['1-IN-5'])//100
            new_line={'Name':values['1-IN-1'],
                      'DateOfBirth':values['1-IN-2'],
                      'PhoneNumber':values['1-IN-3'],
                      'Position':values['1-IN-4'],
                      'Salary':values['1-IN-5'],
                      'RetentionPercentage':values['1-IN-6'],
                      'FinalSalary':fs}
            df1 = df.iloc[row_index]
            df = df.replace(df1, new_line)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)
            window3.close()
        elif event == '-SAVE-':
            df.to_csv(data,sep=',',header=True,index=None)
   #except Exception:
    #    print('Error')
window.close()
Используя дебаггер, я пришёл к выводу, что values заполняется введёнными для изменения данными так же, как заполняется при добавлении новой строки. Функция добавления строки:
Python:
  elif event == '0-ADD-':
            now = datetime.datetime.now()
            fs = int(values['0-IN-5'])-int(values['0-IN-6'])*int(values['0-IN-5'])//100
            new_line={'Name':values['0-IN-1'],
                      'DateOfBirth':values['0-IN-2'],
                      'PhoneNumber':values['0-IN-3'],
                      'Position':values['0-IN-4'],
                      'Salary':values['0-IN-5'],
                      'RetentionPercentage':values['0-IN-6'],
                      'FinalSalary':fs,
                      'EmploymentDate':now.date()}
            df = df.append(new_line, ignore_index=True)
            df1 = np.array(df).tolist()
            window1['-TABLE-'].update(df1)
            window2.close()
Однако после заполнения values данными, я уже не могу обратиться к values['-TABLE-'], так как выдаёт ошибку.
Для заполнения таблицы и воспроизведения проблемы прошу использовать таблицу в csv файле, прикреплённым ниже, следующим путём:
При запуске кода выбрать csv файл с помощью кнопки 'File browse'
Нажать кнопку 'Go'
 

Вложения

  • csv файл.zip
    346 байт · Просмотры: 1

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 589
459
83
почему вы выбрали pysimlegui?
и зачем пробелы в df ?

upd
ааа, это так регулируется ширина колонок...
мощно

upd2
так происходит потому что он читает данные из окна (как я понял, до этого с этим гуи я не работал, это изврат), то есть он делает словарь с ключами отсюда, тут нет ключа тейбл
Python:
l_col = sg.Column(
        [
        [sg.Text('Name'),sg.Input(key='1-IN-1', enable_events=True)],
        [sg.Text('Date of birth'),sg.Input(key='1-IN-2', enable_events=True)],
        [sg.Text('Phone number'),sg.Input(key='1-IN-3', enable_events=True)],
        [sg.Text('Position'),sg.Input(key='1-IN-4', enable_events=True)],
        [sg.Text('Salary'),sg.Input(key='1-IN-5', enable_events=True)],
        [sg.Text('Retention percentage'),sg.Input(key='1-IN-6', enable_events=True)],
        [sg.Button('OK',key='1-ADD-',button_color='darkgreen')]
        ],
        element_justification="right"
)
вам нужно сделать основное окно, и из него читать, а при нажатии на кнопку добавить читать уже из дочернего окна...
и с добавлением так же...

upd3
короче вам нужно чтобы в этом окне был ключ тейбл, если вы завязались на него...

мне надоело разбираться, простите
 
Последнее редактирование:

Mu3aHTpoTT

Новичок
Пользователь
Ноя 16, 2021
5
0
1
почему вы выбрали pysimlegui?
и зачем пробелы в df ?

upd
ааа, это так регулируется ширина колонок...
мощно

upd2
так происходит потому что он читает данные из окна (как я понял, до этого с этим гуи я не работал, это изврат), то есть он делает словарь с ключами отсюда, тут нет ключа тейбл
Python:
l_col = sg.Column(
        [
        [sg.Text('Name'),sg.Input(key='1-IN-1', enable_events=True)],
        [sg.Text('Date of birth'),sg.Input(key='1-IN-2', enable_events=True)],
        [sg.Text('Phone number'),sg.Input(key='1-IN-3', enable_events=True)],
        [sg.Text('Position'),sg.Input(key='1-IN-4', enable_events=True)],
        [sg.Text('Salary'),sg.Input(key='1-IN-5', enable_events=True)],
        [sg.Text('Retention percentage'),sg.Input(key='1-IN-6', enable_events=True)],
        [sg.Button('OK',key='1-ADD-',button_color='darkgreen')]
        ],
        element_justification="right"
)
вам нужно сделать основное окно, и из него читать, а при нажатии на кнопку добавить читать уже из дочернего окна...
и с добавлением так же...
PySimpleGUI показался мне довольно простым в понимании и написании, поэтому я его и выбрал.
А что насчёт словаря с ключами - указанный вами кусок является конструктором формы, которая открывается по нажатию кнопки создания новой строки, то есть таблица там находиться не должна, она уже находится в главном окне:
Python:
def make_win1():
    layout = [
        [
         sg.Button('Add employee',size=(20,1),key='-ADD-',button_color='darkgreen'),
         sg.Button('Remove employee',size=(20,1),key='-DELETE-',button_color='darkred'),
         sg.Button('Change employee data',size=(25,1),key='-CHANGE-',button_color='darkorange'),
         sg.Text('                                                                     '),
         sg.Input(key='-FILEBROWSE-'),
         sg.FileBrowse('File browse',button_color='darkorange',file_types=(("csv Files", "*.csv"),)),
         sg.Button('Go', button_color='darkgreen'),       
         ],
        [sg.Table(values=df1,
                    headings=headings,
                    max_col_width=35,           
                    display_row_numbers=True,
                    justification='center',
                    alternating_row_color='grey',
                    key='-TABLE-',
                    size=(150,20),
                    enable_events=True,
                    row_height=30,
                    )],
        [sg.Button('Save',size=(20,1), button_color='darkgreen',key='-SAVE-')]
    ]
В условии добавления новой строки, я могу обратиться к ключу из основного окна без всяких проблем:
Python:
 window1['-TABLE-'].update(df1)
Но при обращении к тому же самому ключу основного окна, но только уже в условии изменения информации строки, похоже на то, что значения, которые я хочу поместить в новую строку для её замены вместо старой, как-то конфликтуют со значениями таблицы, и дело не в некорректном заполнении информации по форме, а как я указал ещё в вопросе, при собственноручной установке индекса строки для замены информации всё работает хорошо, но в цикле, точнее даже будет сказать - в одной строчке, где я обращаюсь к значениям таблицы, происходит какая-то ошибка
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 589
459
83
при нажатии на кнопку ок в окне изменения в values пишется словарь с ключами из формы где я показал, и значениями из полей это формы, там нет ключа тейбл...

В условии добавления новой строки, я могу обратиться к ключу из основного окна без всяких проблем:
values перезаписывается
это пример values после нажатия ок, в первое поле где имя я написал asdasd
{'1-IN-1': 'asdasd', '1-IN-2': '', '1-IN-3': '', '1-IN-4': '', '1-IN-5': '', '1-IN-6': ''}


upd
Вы что то не так делаете, советую документацию почитать...
 
Последнее редактирование:

Форум IT Специалистов