我第一次尝试使用PySimpleGUI构建GUI,并且正在与布局重用规则作斗争。
该脚本的总体目标是让用户更容易将数据输入CSV表。为此,用户将能够在表单中输入数据,提交数据,并决定是添加另一个数据集还是退出。
我尝试过使用嵌套函数,但一直在破坏脚本,因为我应该为每个窗口使用新的布局。到目前为止,我已经定义了3个不同的窗口,它们有自己的布局:
window1
=可以添加数据的主窗口window2
=带有错误通知的窗口window3
=在SUBMIT
之后打开窗口,询问用户是否要继续
此外,如果用户决定添加更多数据(repeatGUI()
(,我将尝试再次调用window1
的函数,但这是不允许的。
我知道脚本中也有其他问题,但我主要希望能就布局重用问题提供一些意见。多次打开输入窗口的正确方法是什么?
草稿:
import csv
import PySimpleGUI as sg
sg.main_get_debug_data()
myfile="C:\######\File.csv"
counter=0
def buildGUI(): # defining GUI frame, title, fields and buttons
sg.ChangeLookAndFeel('GreenTan')
window1 = sg.FlexForm('MY DB', size = (900,700), resizable=True)
layout1 = [
[sg.Text('Please enter a new factoid:')],
[sg.Text('Factoid ID', size=(15, 1), key="-FACTOID-")],
[sg.Text('Person ID', size=(15, 1), key="-PERSON-")],
[sg.Text('Exact Date', size=(10, 1)), sg.InputText()],
[sg.Text('Event Before', size=(10, 1)), sg.InputText()],
[sg.Text('Event After', size=(10, 1)), sg.InputText()],
[sg.Text('Event Start', size=(10, 1)), sg.InputText()],
[sg.Text('Event End', size=(10, 1)), sg.InputText()],
[sg.Text('Event Type', size=(15, 1)), sg.InputText()],
[sg.Text('Person Name', size=(15, 1)), sg.InputText()],
[sg.Text('Person Title', size=(15, 1)), sg.InputText()],
[sg.Text('Person Function', size=(15, 1)), sg.InputText()],
[sg.Text('Place Name', size=(15, 1)), sg.InputText()],
[sg.Text('Institution Name', size=(15, 1)), sg.InputText()],
[sg.Text('Related Persons', size=(15, 1)), sg.InputText()],
[sg.Text('Alternative Names', size=(15, 1)), sg.InputText()],
[sg.Text('Source Quote', size=(10, 1)), sg.InputText()],
[sg.Text('Additional Info', size=(10, 1)), sg.InputText()],
[sg.Text('Comment', size=(10, 1)), sg.InputText()],
[sg.Text('Source', size=(10, 1)), sg.InputText()],
[sg.Text('Source URL', size=(10, 1)), sg.InputText()],
[sg.Text('Info Dump', size=(10, 1)), sg.InputText()],
[sg.Text(size=(70,1), key='-MESSAGE1-')],
[sg.Submit(), sg.Button('Clear Input')]
]
while True: # The Event Loop
event1, values1 = window1.Layout(layout1).Read()
print(layout1)
def startGUI(event1, values1): # start GUI and get data
# interact with user to get input
if event1 == 'Submit': # user clicked "Submit"
def submitGUI(values1): # submitting new data via GUI
fact_id=("#") # place holder: to be calculated later
pers_id=("#") # place holder: to be calculated later
entries=[fact_id, pers_id]
for v in values1.values():
entries.append(v)
try:
with open(myfile, 'a', encoding="utf-8") as f:
w=csv.writer(f)
w.writerow(entries) # write list items to CSV file
f.close()
try:
window3 = sg.FlexForm('NEW DATA?', size = (500,100))
layout3 = [
[sg.Text("Your input has been saved! Do you want to add a new factoid?")],
[sg.Text(size=(70,1), key='-MESSAGE2-')],
[sg.Button("YES"), sg.Button("NO"), sg.Exit()]
]
while True:
event3, values3 = window3.Layout(layout3).Read()
if event3 == 'YES': # user clicked YES
window1.close()
try:
repeatGUI() # this breaks layout rules!
except:
print("Not allowed!")
pass
elif event3 == 'NO':
window3['-MESSAGE2-'].update("See you again soon!")
window1.close()
elif event3 in (sg.WINDOW_CLOSE_ATTEMPTED_EVENT, 'Exit'):
window3.close()
except:
pass
except PermissionError:
window2 = sg.FlexForm('DB ERROR', size = (500,100))
layout2 = [
[sg.Text("Someone else is using the file! Please try again later.")],
[sg.Exit()]
]
event2, values2 = window2.Layout(layout2).Read()
if event2 in (sg.WINDOW_CLOSE_ATTEMPTED_EVENT, 'Exit'):
window2.close() # user clicked "Exit"
submitGUI(values1)
elif event1 == 'Clear Input': # user clicked "Cancel"
window1.Refresh()
elif event1 == sg.WINDOW_CLOSE_ATTEMPTED_EVENT: # user closed window
window1.close() # AttributeError: module 'PySimpleGUI' has no attribute 'WIN_CLOSED'
startGUI(event1, values1)
buildGUI()
def repeatGUI():
counter+=1
print(counter)
buildGUI()
下面的方法显示您一次又一次地使用变量layout1
作为sg.Window
的布局,layout1中的元素在第一次使用后都没有初始化。
while True: # The Event Loop
event1, values1 = window1.Layout(layout1).Read()
...
以下代码为首选,
window1 = sg.Window('Title1', layout1, finalize=True)
while True:
event1, values1 = window1.read()
...
或
def make_window1():
layout = [
[sg.Text('Please enter a new factoid:')],
....
]
return sg.Window('Title1', layout, finalized=True)
window1 = make_window1()
while True:
event1, values1 = window1.read()
...
根据@jason-yang的回答,我解决了布局问题,并将整个脚本修改为
a( 在启动GUI的功能之外定义布局和b( 取消多次打开同一输入窗口的尝试。
在我的情况下,具有持久窗口要合适得多,所以我使用"持久窗口";清除";允许输入新数据的按钮:
elif event1 == 'Clear to add new data': # user clicked "Clear"
window1['-MESSAGE1-'].update("Ready for your next data set!")
# update all input fields
window1['-DATE-'].update('')
window1['-BEFORE-'].update('')
window1['-AFTER-'].update('')
window1['-START-'].update('')
window1['-END-'].update('')
window1['-EVENT-'].update('')
window1['-PERSNAME-'].update('')