Let's say I have a window that has a button which will open a second window that contains a several Input() and a button that will act as submit. How do I handle the event of the button in the second window? I tried putting it on the same event loop like the rest but when I click on the button it does nothing.
EDIT
Terribly sorry for the title changes, I'm afraid I could not phrase it properly. I hope you still understand what I'm trying to say.
You have to use the event loop of the second window for that.
Op di 18 dec. 2018 om 14:42 schreef OndoyManing notifications@github.com:
Let's say I have a window that has a button which will open a second
window that contains a several Input() and a button that will act as
submit. How do I handle the event of the button in the second window? I
tried putting it on the same event loop like the rest but when I click on
the button it does nothing.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/946, or mute the
thread
https://github.com/notifications/unsubscribe-auth/AFkYZ4vy1OHc0-4ak3E5nxOtyHQSjGx8ks5u6PC9gaJpZM4ZYUyf
.
You have to use the event loop of the second window for that. Op di 18 dec. 2018 om 14:42 schreef OndoyManing notifications@github.com:
…
Let's say I have a window that has a button which will open a second window that contains a several Input() and a button that will act as submit. How do I handle the event of the button in the second window? I tried putting it on the same event loop like the rest but when I click on the button it does nothing. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#946>, or mute the thread https://github.com/notifications/unsubscribe-auth/AFkYZ4vy1OHc0-4ak3E5nxOtyHQSjGx8ks5u6PC9gaJpZM4ZYUyf .
Thanks for the reply! I'm sorry but I'm fairly new to this, how do I specify an event loop for the second window?
After you create the second window, use another while loop like this:
```
while True:
event2, values2 = window2.Read(timeout=20)
if event2 is not None:
etc..
````
There are demo programs that show how to run 2 windows.
There are others as well, but these are the most basic.
After you create the second window, use another while loop like this:
# code to create second window while True: event2, values2 = window2.Read(timeout=20) if event2 is not None: etc..
Thanks @zappfinger ! It's now working, here's my code snippet.
elif event == 'Override':
while True:
event, values = window2.Read(timeout=0)
if event == 'Submit':
userid = values['user2']
passwrd = values['passwrd']
sg.Popup(userid, passwrd) #just to show that the inputs are saved to the variable.
There are demo programs that show how to run 2 windows.
There are others as well, but these are the most basic.
Got the multiple windows working thanks to the demos! Unfortunately the demos don't show how the events are handled on each window, but it's all good now! Thank you so much!
Unfortunately the demos don't show how the events are handled on each window
The demos do show how to handle events. The arrangement of the event loops depends on the interaction between the windows.
In some cases, one window pops up and the first window become inactive. Another is both windows stay active. The demos show the event loops for these situations. You will add your code to handle your events inside of those event loops.
For a "clue" as to where you find each of those event loops, look for an statement like:
if event is None:
break
This is where you will add your code to check for buttons, read values from your window, etc.
The design patterns have all the code you'll need to run multiple windows. If you need more examples, they are in the demo programs section of this github. Have you looked at the documentation too?
Unfortunately the demos don't show how the events are handled on each window
The demos do show how to handle events. The arrangement of the event loops depends on the interaction between the windows.
In some cases, one window pops up and the first window become inactive. Another is both windows stay active. The demos show the event loops for these situations. You will add your code to handle your events inside of those event loops.
For a "clue" as to where you find each of those event loops, look for an statement like:
if event is None: breakThis is where you will add your code to check for buttons, read values from your window, etc.
The design patterns have all the code you'll need to run multiple windows. If you need more examples, they are in the demo programs section of this github. Have you looked at the documentation too?
I am deeply sorry, I can't believe I missed the first demo for multiple windows! That was basically what I was asking for. I changed my code now and it's similar to the first pattern. Thank you so much and sorry for the trouble. Though I have a side question for this matter, the second window is supposed to be the authentication window and will open up a third window if the credentials are correct. How are validations done with PySimpleGUI? Validations such as field must not be left blank, etc. Should I open another issue for this matter?
"Validations" are your responsibility.
When you "Read" a window, you get back a dictionary of all the values. You can test any of the values you want to determine if they are valid or not.
You can use a "Popup" window for simple messages. The design patterns show the multiple windows using Popups as well.
I urge you to read the documentation to get an idea of how this SDK works. http://www.PySimpleGUI.org
I definitely need to read more!
Here's how I handled the blank inputs, would love to hear your opinion on this. Thank you!
if event == 'Submit':
userid = values['user2']
passwrd = values['passwrd']
if userid and passwrd != "":
sg.Popup('Succes!', userid, passwrd)#just to simulate a correct input.
elif userid == "":
sg.Popup('User ID field is required')
elif passwrd == "":
sg.Popup('Password field is required')
There you go! Exactly the kind of thing to do in order to validate fields.
You can also do it "realtime" but that's more complex than you need. You would do something like that for input fields that take only numbers for example.
You've got the right idea.
Try it out, see how it works.
If you are concerned about people interacting with the windows while the Popups are showing, you can hide the window before you show the popup.
You likely want to change:
if userid and passwrd != "":
to
if '' in(userid,passwrd):
so that both userid and passwrd are checked for ''.
Personally I have unique (button, values) for all windows within the same while loop, with variables to set whether to be processing these values. All of the windows are fast, no errors, and don't seem to miss a beat yet..........
# window 1 (main window)
while True:
b, values = mainWindow.Read(timeout=100)
#window 2 (a window that pops up after hitting a button on window 1)
if b == "track_window":
trackWindow_active = True
if trackWindow_active:
track_button, track_values = trackWindow.Read(timeout=0)
# trackWindow will be set to false when trackWindow is closed
And then 2 other windows the same way.
If there are any issues with this style I'd be happy to know them.
Glad to hear it's working! I hold my breath any time I hear someone doing multiple windows stuff. I think I finally got it. The Wx port will be a test.
I think the code you're using is this design pattern:
https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py
And this one too?
https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py
It's short enough to post...
win2_active = False
while True:
ev1, vals1 = win1.Read(timeout=100)
win1.FindElement('_OUTPUT_').Update(vals1[0])
if ev1 is None or ev1 == 'Exit':
break
if not win2_active and ev1 == 'Launch 2':
win2_active = True
layout2 = [[sg.Text('Window 2')],
[sg.Button('Exit')]]
win2 = sg.Window('Window 2').Layout(layout2)
if win2_active:
ev2, vals2 = win2.Read(timeout=100)
if ev2 is None or ev2 == 'Exit':
win2_active = False
win2.Close()
Basically allows you to click a button "Launch 2" that will start up the second window. Then there's an if block to run the window.
For a while I was having some issues with setting both timeouts to a value. I suggested back then that one of the timeout be set to zero like you've got. It seems like a sold feature now.
BTW @eagleEggs , would love to see Panes incorporated into your design.
Yes, you lead me in that direction when I was setting it up :) and ever since it's been smooth sailing.
Regarding Panes, the configuration window (which has a bunch of input boxes for various configs) is expanding as more things need to be configured. I'm thinking the panes option will allow me to keep the window this size, but slide to go to the next options.
Awesome... Create Columns of elements that will represent each pane instead of laying out in one big screen, or instead of using a Tab. I think it would be a really slick interface.
Yep. I'm thinking of something interesting also... a way to just swipe anywhere in the window to move the Pane.
Essentially just a 'button down hold' timer function that hooks onto the pane handle, then any left and right would be considered 'on the handle.'
@MikeTheWatchGuy Could you elaborate more about the "realtime"? Maybe it'll come handy in the future. Thanks!
Okay, so after fiddling around and expanding to 3 windows, the events on the 3rd window are not triggering. I just replicated what I did on the 2nd window to get the 3rd window up and running. Here's my code.
if win2_active:
event2, values2 = window2.Read(timeout=0) #auth Window
if event2 == 'Exit' or event2 is None:
win2_active = False
window2.Close()
window.UnHide()
if event2 == 'Submit':
userid = values2['user2']
passwrd = values2['passwrd']
if userid == userdef and passwrd == passdef and not win3_active:
win3_active = True
sg.Popup('Succes!', userid, passwrd)#just to simulate correct inputs
win2_active = False
window2.Close()
layout3 = [[sg.Text('Plate Number:'), sg.Input(key = 'pNum', size = (8,1))],
[sg.Button('Submit'), sg.Button('Exit')]]
window3 = sg.Window('Third Window', size=(800, 600)).Layout(layout3)
if win3_active:
event3, values3 = window3.Read(timeout=0) #override window
if event3 is None or event3 == 'Exit':
win3_active = False
window3.Close()
window.Unhide() #Reveals main window
if event3 == 'Submit':
pnum = values3['pNum']
sg.Popup(pnum)
Can you post your code somewhere so I can see the entire loop?
Could the problem be that your win3_active check is within the check for win2_active?
The very first line of the code checks for win2_active. It doesn't appear that it will be active when you active win3. I would pull the win3_active code over to the left, outside of the win2_active block.
Here's the code for the entire loop https://paste.ofcode.org/ABEaW85t855d9SjdhW2ehx
I also tried pulling the win3_active code to the left but it gives an error.
EDIT
Just want to clarify that the third window is launched in the second window.
What I mean by checking for "realtime" event is to set enable_events for the input field. Then you will get an event every time a key is entered. If the field is only supposed to get numbers and they type a letter, you can delete the letter from their input.
Here is a Demo Program to show you how to do it:
https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/DemoPrograms/Demo_Input_Validation.py
Window 3 is being launched I assume, you're just not getting events back.... the reason for that is you're not running the code because of line 24.
Pull the code over starting at line 42.
What error do you get when you do this?
That sorted things out. Thanks! I just had to move the win3_active check after the rest of the validations as it gave an unexpected indent if I pulled that block only. Thanks!
EDIT
Thanks for the enable_events demo!
Also, for the future. always make a new layout definition at the same level that you create the window. In other words, you cannot define your layout 3 up above your while loop and try to use it multiple times. Every time you call Window, call with a "freshly made" layout.
If you always have your layout code right above your windows code you won't have a problem.
Closing this one as I believe it's been addressed.
Most helpful comment
What I mean by checking for "realtime" event is to set
enable_eventsfor the input field. Then you will get an event every time a key is entered. If the field is only supposed to get numbers and they type a letter, you can delete the letter from their input.Here is a Demo Program to show you how to do it:
https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/DemoPrograms/Demo_Input_Validation.py