了解 PySimpleGUI 中的布局规则
Understanding layout rules in PySimpleGUI
我第一次尝试使用 PySimpleGUI 构建 GUI,并且正在努力解决 布局重用规则。
该脚本的总体目标是让用户更轻松地将数据输入 CSV table。为此,用户将能够在表单中输入数据、提交数据,并决定是要添加另一个数据集还是退出。
我曾尝试使用嵌套函数,但我不断地破坏脚本,因为我应该为每个 window 使用新的布局。到目前为止,我已经定义了 3 个不同的 windows 和它们自己的布局:
window1
= main window 可以添加数据的地方
window2
= window 带有错误通知
window3
= window 在 SUBMIT
之后打开,询问用户是否要继续
此外,如果用户决定添加更多数据 (repeatGUI()
),我将尝试再次调用 window1
的函数,但这是不允许的。
我知道脚本中还有其他问题,但我主要希望能就布局重用问题提供一些意见。 多次window打开一个输入的正确方法是什么?
脚本草稿:
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
的布局,布局 1 中元素的 none 在第一次使用后初始化。
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) 摆脱多次打开相同输入 window 的尝试。
持久性 window 更适合我的情况,因此我使用“清除”按钮来允许输入新数据:
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('')
我第一次尝试使用 PySimpleGUI 构建 GUI,并且正在努力解决 布局重用规则。
该脚本的总体目标是让用户更轻松地将数据输入 CSV table。为此,用户将能够在表单中输入数据、提交数据,并决定是要添加另一个数据集还是退出。
我曾尝试使用嵌套函数,但我不断地破坏脚本,因为我应该为每个 window 使用新的布局。到目前为止,我已经定义了 3 个不同的 windows 和它们自己的布局:
window1
= main window 可以添加数据的地方
window2
= window 带有错误通知
window3
= window 在 SUBMIT
之后打开,询问用户是否要继续
此外,如果用户决定添加更多数据 (repeatGUI()
),我将尝试再次调用 window1
的函数,但这是不允许的。
我知道脚本中还有其他问题,但我主要希望能就布局重用问题提供一些意见。 多次window打开一个输入的正确方法是什么?
脚本草稿:
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
的布局,布局 1 中元素的 none 在第一次使用后初始化。
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) 摆脱多次打开相同输入 window 的尝试。
持久性 window 更适合我的情况,因此我使用“清除”按钮来允许输入新数据:
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('')