Posts: 4
Threads: 1
Joined: Dec 2020
Dec-07-2020, 08:47 PM
Hello,
I'm currently experimenting with my first GUI in Python (or in any other programming language) using PySimpleGUI and I'm stumbling on some issues I cannot resolve.
This is the code I've written so far:
Import PySimpleGUI as sg
sg.theme('DarkAmber')
layout = [[sg.Text('Reverse complement:'), sg.Text(size=(15,1), key='-OUTPUT-')],
[sg.Input(key='-IN-')],
[sg.Button('Convert'), sg.Button('Exit'), sg.Button('Help')]]
layout_help = [[sg.Text("This program requires a DNA sequence as an input and returns the reverse complement")],[sg.Button("Cancel")]]
window = sg.Window('Reverse Complement Converter', layout)
window_help = sg.Window("Help", layout_help)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Convert':
seq=values['-IN-']
rc= reverseComplement(seq)
window['-OUTPUT-'].update(rc)
if event == "Help":
window_help.read()
if event == "Cancel" or event == sg.WIN_CLOSED:
window_help.close()
window.close() If I run the script, the appropriate window opens:
The "Convert" button, linked to my custom reverseComplement() function actually functions. So the general functionality of my GUI works.
However, I experience following issues:
1) when I press the button "Help", I get the correct new windows pops up. However, I cannot close this help window by pressing the "Cancel" button. Pressing Cancel, does not do anything at the moment. I can, however, close it by pressing "X" in the top right corner. Why is this? Both the Cancel and X buttons should close the window right?
I also tried the following code without succes:
if event == "Help":
window_help.read()
if event == "Cancel" or event == sg.WIN_CLOSED:
break 2) Also regarding the "Help" window: When I press "Help" and thereafter close the help window by pressing "X", nothing happens when I press te "Help" button again. Why is this? If the program stays in the event loop, it should be able to process "Help" more than once?
Any help would be much appreciated.
Posts: 6,779
Threads: 20
Joined: Feb 2020
I don't see how this could work.
if event == "Help":
window_help.read()
if event == "Cancel" or event == sg.WIN_CLOSED:
break To get to the "break" event has to equal "Help" and at the same time equal "Cancel" or sg.WIN_CLOSED. In you while loop you read one event at a time and process one event at a time.
You should also use elif to limit the code executed for each loop.
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Convert': # Don't need elif here because of break
seq=values['-IN-']
rc= reverseComplement(seq)
window['-OUTPUT-'].update(rc)
elif event == "Help":
window_help.read()
elif event == "Cancel" or event == sg.WIN_CLOSED:
window_help.close()
Posts: 4
Threads: 1
Joined: Dec 2020
(Dec-07-2020, 09:35 PM)deanhystad Wrote: I don't see how this could work.
if event == "Help":
window_help.read()
if event == "Cancel" or event == sg.WIN_CLOSED:
break To get to the "break" event has to equal "Help" and at the same time equal "Cancel" or sg.WIN_CLOSED. In you while loop you read one event at a time and process one event at a time.
You should also use elif to limit the code executed for each loop.
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Convert': # Don't need elif here because of break
seq=values['-IN-']
rc= reverseComplement(seq)
window['-OUTPUT-'].update(rc)
elif event == "Help":
window_help.read()
elif event == "Cancel" or event == sg.WIN_CLOSED:
window_help.close()
Thank you for your reply. I added the second if statement (below) with the reasoning that it would only apply to the "Help" window. So if "Help" is pressed, then a new window pop ups, with its own new event and if statement. That's how I used nested if statements before, so I thought it also worked like that in an event loop?
if event == "Help":
window_help.read()
if event == "Cancel" or event == sg.WIN_CLOSED:
break Thanks for rewriting the code. However, I still cannot close the Help window using the "Cancel" button. Also it is not possible to press Help twice. Any ideas how to solve this?
Posts: 101
Threads: 0
Joined: Jan 2021
Jan-09-2021, 10:27 PM
(This post was last modified: Jan-09-2021, 10:27 PM by Serafim.)
As you use windows and not popups you have to catch signals from all windows.
Your code works with minor changes (I changed the "rc= reverseComplement(seq)" as I don't know what it does)
import PySimpleGUI as sg
sg.theme('DarkAmber')
layout = [[sg.Text('Reverse complement:', size=(15,1), key='-OUTPUT-')],
[sg.Input(key='-IN-')],
[sg.Button('Convert'), sg.Button('Exit'), sg.Button('Help')]]
window= sg.Window('Reverse Complement Converter', layout, finalize = True)
window_help = None
while True:
win, event, values = sg.read_all_windows() # Read all signals from all windows
if event in (sg.WIN_CLOSED, 'Exit', 'Cancel'):
if win == window:
break
elif window_help and win == window_help:
window_help.close()
window_help = None
elif event == 'Convert':
seq=values['-IN-']
rc= "YES!" #reverseComplement(seq)
window['-OUTPUT-'].update(rc)
elif event == "Help":
layout_help = [[sg.Text("This program requires a DNA sequence as an input and returns the reverse complement")],[sg.Button("Cancel")]]
window_help = sg.Window("Help", layout_help, finalize = True)
window.close()
Posts: 4
Threads: 1
Joined: Dec 2020
(Jan-09-2021, 10:27 PM)Serafim Wrote: As you use windows and not popups you have to catch signals from all windows.
Your code works with minor changes (I changed the "rc= reverseComplement(seq)" as I don't know what it does)
import PySimpleGUI as sg
sg.theme('DarkAmber')
layout = [[sg.Text('Reverse complement:', size=(15,1), key='-OUTPUT-')],
[sg.Input(key='-IN-')],
[sg.Button('Convert'), sg.Button('Exit'), sg.Button('Help')]]
window= sg.Window('Reverse Complement Converter', layout, finalize = True)
window_help = None
while True:
win, event, values = sg.read_all_windows() # Read all signals from all windows
if event in (sg.WIN_CLOSED, 'Exit', 'Cancel'):
if win == window:
break
elif window_help and win == window_help:
window_help.close()
window_help = None
elif event == 'Convert':
seq=values['-IN-']
rc= "YES!" #reverseComplement(seq)
window['-OUTPUT-'].update(rc)
elif event == "Help":
layout_help = [[sg.Text("This program requires a DNA sequence as an input and returns the reverse complement")],[sg.Button("Cancel")]]
window_help = sg.Window("Help", layout_help, finalize = True)
window.close()
Thanks for your reply Serafim. Indeed, with your changes I can open and close the help window. Thank you! FYI: reverseComplement is a custom function which processes a string and outputs a string.
I have a few questions though:
1) In line 19 of your code, why did you write elif window_help and win == window_help: and not just elif win == window_help ? I removed the "window_help" in this statement, and the GUI appears to work fine.
2)In the same elif statement as question 1. Why did you add window_help=None (line 21). Again, if I delete this line, it seems to work fine.
3)When I click the "Convert" button, the string processed by the reverseComplement function (i.e. "rc" value), should appear to the right of "Reverse complement:" as it is the "key" of this Text. This happend in my initial script. However, when I now press "Convert", the "rc" value replaces the "Reverse complement:" string. Any idea why this happens and how I could fix this? When I look at the code, I fail to understand why it replaces the whole string.
Thanks!
Posts: 101
Threads: 0
Joined: Jan 2021
In a GUI there are a lot of signals telling the application what is going on and some of these signals are a bit confusing, e.g. "sg.WIN_CLOSED" which only tells you that a window has given "None" as signal, not telling which window. Thus, I note that to start with there is no help window by declaring window_help=None and that means that if window_help and win == window_help ensures that the part win == window_help is tested only if window_help has a value (is referring to a window). If not you may have a crash when trying to close the window_help window (error: 'NoneType' object has no attribute 'close'). The python construct "if A and B" calculates B only if A is True (sort of a shortcut of the whole expression).
It might be that I am overly careful, but in my experience (50+ years of programming in a multitude of languages and in a large range of applications, the biggest counting millions of lines of code. I am 75 and still active as a programmer), if you are not careful with these matters, sooner or later there is a crash.
And, when that occurs, you want to be able to find the bug quickly. The more careful you are, the more precautions you take, the simpler to locate the error.
So far your application is small but it will grow. Being careful is a good basis for application development.
Posts: 101
Threads: 0
Joined: Jan 2021
Jan-10-2021, 10:34 PM
(This post was last modified: Jan-10-2021, 10:35 PM by Serafim.)
I didn't answer the last question.
When you update a Text element you replace the text in it. If you want to add text you will have to supply the original text + the addition:
rc = reverseComplement(seq)
window['-OUTPUT-'].update('Reverse complement: ' + rc) but then you also need to expand it's size. Another option is of course to use the text as a label and add another text as output:
layout = [[sg.Text('Reverse complement:', size=(19,1)), sg.Text('',size=(15,1), key='-OUTPUT-')],
[sg.Input(key='-IN-')],
[sg.Button('Convert'), sg.Button('Exit'), sg.Button('Help')]] I also want to add that I neither meant to be patronizing in my previous answer (it does look like it), nor did I mean to boast. In the mentioned multimillion line applications I contributed but did of course not write all of it. My latest project was with PySimpleGUI and just 1000 lines of code but had I used another GUI framework it would have been several times that. What I appreciate in PySimpleGui is the simplicity. You get a lot of GUI with very few lines of code.
Posts: 4
Threads: 1
Joined: Dec 2020
Thank you for your replies! Your clarification really helped in understanding the code.
Regarding the updating of a Text element: I understand what you mean. However, it is weird then that only the -OUTPUT- key was updated in my original code.
No worries, it didn't feel like patronizing or boasting to me!
(Jan-10-2021, 10:34 PM)Serafim Wrote: I didn't answer the last question.
When you update a Text element you replace the text in it. If you want to add text you will have to supply the original text + the addition:
rc = reverseComplement(seq)
window['-OUTPUT-'].update('Reverse complement: ' + rc) but then you also need to expand it's size. Another option is of course to use the text as a label and add another text as output:
layout = [[sg.Text('Reverse complement:', size=(19,1)), sg.Text('',size=(15,1), key='-OUTPUT-')],
[sg.Input(key='-IN-')],
[sg.Button('Convert'), sg.Button('Exit'), sg.Button('Help')]] I also want to add that I neither meant to be patronizing in my previous answer (it does look like it), nor did I mean to boast. In the mentioned multimillion line applications I contributed but did of course not write all of it. My latest project was with PySimpleGUI and just 1000 lines of code but had I used another GUI framework it would have been several times that. What I appreciate in PySimpleGui is the simplicity. You get a lot of GUI with very few lines of code.
Posts: 6,779
Threads: 20
Joined: Feb 2020
From every example I've seen I think the "Simple" in PySimpleGUI refers to the design of the package instead of it's use.
Posts: 101
Threads: 0
Joined: Jan 2021
(Jan-18-2021, 06:19 PM)deanhystad Wrote: From every example I've seen I think the "Simple" in PySimpleGUI refers to the design of the package instead of it's use.
If I compare my GUI programs over the years, PySimpleGUI is the one that gave me the most GUI-functionality by the smallest amount of code. It is not the most versatile but good enough for many cases. So it might refer both to the design and the ease of use. I used it in my two latest projects and it was actually pretty easy (after some reading before starting the first project) to get the GUIs up and running. For my next project I will have to find something else as I want to do things PySimpleGUI cannot deliver.
|