import PySimpleGUI as sg
import os
layout = [[sg.Text('Velg mappe som skal tas backup av og hvor du vil plassere backupen')],
[sg.Text('Source folder', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
[sg.Text('Backup destination ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
[sg.Text('Made by Henrik og Thomas™')],
[sg.Submit(), sg.Cancel()]]
window = sg.Window('Backup Runner v2.1')
event, values = window.Layout(layout).Read()
How can I call a function when I press the submit button? or any other button?
The PySimpleGUI documentation discusses how to do this in the section on events / callbacks
https://pysimplegui.readthedocs.io/#the-event-loop-callback-functions
It is not lot the other Python GUI frameworks that use callbacks to signal button presses. Instead all button presses are returned as "events" coming back from a Read call.
To achieve a similar result, you check the event and make the function call yourself.
import PySimpleGUI as sg
def func(message):
print(message)
layout = [[sg.Button('1'), sg.Button('2'), sg.Exit()] ]
window = sg.Window('ORIGINAL').Layout(layout)
while True: # Event Loop
event, values = window.Read()
if event in (None, 'Exit'):
break
if event == '1':
func('Pressed button 1')
elif event == '2':
func('Pressed button 2')
window.Close()
To see this code run online, you can run it here using the web version:
https://repl.it/#PySimpleGUI/Call-Func-When-Button-Pressed
Added 4/5/2019
I should have also stated in my answer that you could add the event checks to right after your call to Read. You don't have to use an Event Loop as I showed. It could look like this:
event, values = window.Layout(layout).Read() # from OP's existing code
if event == '1':
func('Pressed button 1')
elif event == '2':
func('Pressed button 2')
[ Edit Nov 2020 ] - Callable keys
This isn't a new capability, just didn't mention it in the answer previously.
You can set keys to be functions and then call them when the event is generated. Here is an example that uses a few ways of doing this.
import PySimpleGUI as sg
def func(message='Default message'):
print(message)
layout = [[sg.Button('1', key=lambda: func('Button 1 pressed')),
sg.Button('2', key=func),
sg.Button('3'),
sg.Exit()]]
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.read()
if event in (None, 'Exit'):
break
if callable(event):
event()
elif event == '3':
func('Button 3 pressed')
window.close()
Related
I am trying to get the content in the listbox able to be dragged into the workspace as a block. Like scratch. I used OpenAi to give me ideas of how to do it, and it gave me that there is a draggable option I can put into the code as you can see, but when I try to drag the items in the listbox it wont let me.
import PySimpleGUI as sg
from PIL import ImageGrab
# Create a list of Python code to display in the scroller
code_lines = [
"variable",
"loops",
"types of variables"
]
# Create the window layout
layout = [ [sg.Column([[sg.Listbox(values=code_lines, size=(20, 10), key='Python Code', draggable = True)]]),
sg.Column([[sg.Text('Workspace:', size=(20, 1)), sg.Multiline(size=(50, 30), key='workspace', background_color='dark gray')]])],
[sg.Button('Close')] ]
# Create the window
window = sg.Window('PyDrop', layout)
# Event loop to process events
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Close': # if user closes window or clicks close button
break
elif event == 'Python Code': # if user clicks on an item in the listbox
# stores the value of the clicked item in a variable
dragged_item = values['Python Code'][0]
elif event == sg.DRAG: # if user moves the mouse while holding down the button
# updates the value of the drop target
print('Drag event triggered')
window['drop_target'].update(dragged_item)
# Close the window
window.close()
Hello i have a small program that gets input from user, I suddenly noticed that after few uses in the program I cant use CONTROL + A / CONTROL + C /CONTROL + D the inputText doesnt respond.
if I restart the program this buttons events work.
layout = [[sg.Text('WELCOME', justification='center', size=(50))],
[sg.InputText(), sg.Text(': ENTER SOME TEXT ', justification='right')],
[sg.Button('Search', bind_return_key=True)]
window = sg.Window('Client Connection V2.0Beta2', layout, element_justification='c')
while True:
event, values = window.read()
user_text= values[0]
if event == sg.WIN_CLOSED : # if user closes window or clicks cancel
window.close()
break
elif event == 'Search: # First step user search for
#some Code....
It should be fine for following code
import PySimpleGUI as sg
layout = [
[sg.Text('WELCOME', justification='center', expand_x=True)],
[sg.Text('ENTER SOME TEXT: '), sg.InputText()],
[sg.Button('Search', bind_return_key=True)],
]
window = sg.Window('Client Connection V2.0Beta2', layout, element_justification='c')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED: # if user closes window or clicks cancel
break
elif event == 'Search':
user_text = values[0]
print(user_text)
window.close()
In your description, it didn't show how about the other keyboard input.
It maybe caused by the focus not on the input element, maybe you press the TAB key by accidentally, then the focus shift to next element, 'Search` button here, then all the keyboard input will not be responded in the input element.
In following figure, button Search focused and with a dash box on it, and then the keyboard input to input element will be not responded.
Try to press TAB key to move focus to input element.
I saw a sample demo code from PySimpleGUI and I'm still not sure if how the window variable
The window was passed as an argument to the_thread() function and somehow it managed to do some operations for window variable like window.write_event_value which is inside the main function.
I have a cp(values) inside the main that proves that it was added.
Can anyone explain to me how is that possible?
The
import threading
import time
import PySimpleGUI as sg
THREAD_EVENT = '-THREAD-'
cp = sg.cprint
def the_thread(window):
i = 0
while True:
time.sleep(1)
cp('This keeps on running')
window.write_event_value('-THREAD-', (threading.current_thread().name, i)) # Data sent is a tuple of thread name and counter
cp('This is cheating from the thread', c='white on green')
i += 1
def main():
layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
[sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
[sg.T('Input so you can see data in your dictionary')],
[sg.Input(key='-IN-', size=(30,1))],
[sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event.startswith('Start'):
threading.Thread(target=the_thread, args=(window,), daemon=True).start()
if event == THREAD_EVENT:
cp(f'Data from the thread ', colors='white on purple', end='')
cp(f'{values[THREAD_EVENT]}', colors='white on red')
cp(values)
window.close()
if __name__ == '__main__':
main()
Sorry for being noob, looks like the reason it gets modified on a separate function is because it's a mutable object.
Still not sure what the question is.
Try to explain this script.
Define the layout of window
layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
[sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
[sg.T('Input so you can see data in your dictionary')],
[sg.Input(key='-IN-', size=(30,1))],
[sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ]
Define a window by
window = sg.Window('Window Title', layout)
While loop to handle events generated by action of mouse or keyboard inputs on window. Here, window.read() will create the GUI of the window before update if GUI not yet finalized, then update the GUI of the window
while True: # Event Loop
event, values = window.read()
...
Break from while loop if event of close button of window clicked, or event of 'Exit' button clicked.
if event == sg.WIN_CLOSED or event == 'Exit':
break
Start a new thread by call function the_thread(window) if button 'Start A Thread' clicked.
if event.startswith('Start'):
threading.Thread(target=the_thread, args=(window,), daemon=True).start()
Thread function send one event '-THREAD-' every sleep one second with value (threading.current_thread().name, i). In general, you should not update GUI of window not in main thread for you may get troubles when your code running, send a event to main thread to handle GUI update, so I removed all cp calls here.
def the_thread(window):
i = 0
while True:
time.sleep(1)
window.write_event_value('-THREAD-', (threading.current_thread().name, i)) # Data sent is a tuple of thread name and counter
i += 1
Update elements or window, and print messages to sg.Multiline when event -THREAD- generated from thread.
if event == THREAD_EVENT:
cp(f'Data from the thread ', colors='white on purple', end='')
cp(f'{values[THREAD_EVENT]}', colors='white on red')
After break from while loop, close window and exit.
window.close()
I'm currently trying to create a custom button in python using PySimpleGUI that allows me to browse for files. I am able to do this successfully for a button that submits my entries and one that cancels the process, but am unable to figure out how to do so without having to use sg.FilesBrowse(), which doesn't allow me to customize the button.
I have the current code for my window.
#select theme for GUI
sg.theme('Light Blue 2')
#create custom buttons
submit_button = sg.Button('', image_data=submit_base64,button_color=(sg.theme_background_color(),sg.theme_background_color()),border_width=0, key='Sumbit')
cancel_button = sg.Button('', image_data=cancel_base64,button_color=(sg.theme_background_color(),sg.theme_background_color()),border_width=0, key='Cancel')
#create GUI layout
layout = [[sg.Text('Please select the following files:', font = ('bold', 14))],
[sg.Text('Page Names', size=(15, 1)), sg.Input(),sg.FileBrowse()],
[sg.Text('Files to Replicate', size=(15, 1)), sg.Input(), sg.FilesBrowse()],
[submit_button, cancel_button]]
In place of sg.FileBrowse() and sg.FilesBrowse() I would like to have my custom buttons similarly to how I created submit_button and cancel_button. I tried to follow the same format but am unsure what key I would have to use to have the button behave just like sg.FileBrowse() and sg.FilesBrowse().
Thanks.
Try this.
Create a button
When button pressed call popup_get_file
Take results from popup and fill in the Input element
import PySimpleGUI as sg
def main():
layout = [ [sg.Text('My Window')],
[sg.Input(key='-IN-'), sg.Button('MyBrowse', key='-BROWSE-')],
[sg.Button('Go'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.read()
print(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == '-BROWSE-':
file = sg.popup_get_file('', no_window=True)
window['-IN-'].update(file)
window.close()
if __name__ == '__main__':
main()
I'm creating a textbox as follows:
sg.Text(size=(57, 10), background_color='white', text_color='red',
key='_console')
And it works fine, except the text isn't selectable!
I want the user to be able to copy the message to clipboard (by mouse selection and "copy").
How can it be done?
thx
According to the git hub issue related to this, the way to go about doing this is to create a read-only input and format it to look like the normal text elements:
https://github.com/PySimpleGUI/PySimpleGUI/issues/2928
import PySimpleGUI as sg
sg.theme('Dark Red')
layout = [ [sg.Text('My Window')],
[sg.InputText('You can select this text', use_readonly_for_disable=True, disabled=True, key='-IN-')],
[sg.Button('Go'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout, finalize=True)
window['-IN-'].Widget.config(readonlybackground=sg.theme_background_color())
window['-IN-'].Widget.config(borderwidth=0)
while True: # Event Loop
event, values = window.read()
print(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
window.close()