Code for buttons or text not working with PySimpleGui - python

import PySimpleGUI as sg
layout = [[sg.Text("Placeholder")], [sg.Button("OK")]]
window = sg.Window('Window Title', layout, location=(0,0), size=(1000,700), keep_on_top=True)
while True:
event, values = window.read()
if event == "OK" or event == sg.WIN_CLOSED:
break
I am new to GUI programming. I tried to use this code to create a simple window with a button but when I do, I only get a blank screen without buttons or text.

Related

Python subprocess.run() not responding on PySimpleGUI

When I run the sample code below and click on the button, the GUI window shows not responding? Maybe because The GUI is waiting for the subprocess.run() to finish, because when I close the browser that is opened by the GUI, it is not responding anymore. How can I use the GUI when using subprocess.run()? Thanks.
Here is my sample code:
import PySimpleGUI as sg
import subprocess
layout = [
[sg.Button('Open Browser', key="ob")]
]
window = sg.Window('Metamask Accounts Opener', layout, element_justification='c', size=(400, 400))
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit': # if user closes window or clicks cancel
break
if event == "ob":
subprocess.run('"C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe" --remote-debugging-port=9222 -- "%1"')
window.close()
subprocess.run waits for the process to finish. You need to use Popen in order to not wait and just run in the background.
Popen(['"C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe"' ,"--remote-debugging-port=9222","--","%1"])

Run code after the window has been initialized

I have a program that has an sg.Output element, and I want a function to run after the window has opened/initialized.
This is a sample of my code:
import PySimpleGUI as sg
import os
layout = [[sg.Output(size=(50, 10))]]
window = sg.Window('SampleCode', layout)
def printAfter():
print('Hello')
while True:
event, values = window.read()
printAfter()
if event == sg.WIN_CLOSED:
break
Problem is it seems to print it before it could initialize the window.
Option finalize=True in Window to let the GUI finalized, then you can run any code about GUI or after GUI initialized.
Method Window.read will wait event from GUI, so it do nothing before any event, like click the button.
Code in While condition loop will be executed repeatedly until the condition is False or break statement.
import PySimpleGUI as sg
import os
def printAfter():
print('Hello')
layout = [[sg.Output(size=(50, 10))]]
window = sg.Window('SampleCode', layout, finalize=True)
printAfter()
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
window.close()

How can I make cross-platform Kivy app with system-tray/taskbar icon which would detect keyboard input even when app is not focused/in taskbar mode

I want to create application with taskbar/system-tray icon. Crossplatform. OSX, Windows, Linux (Ubuntu/Centos/Mint/Manjaro and other popular distros).
This app should detect keyboard input and react to it. Basically do some actions on specific keys. Example: user wants to play some music, presses shift+ctrl+p. Music starts playing.
I know that Kivy capable of detecting
For the "cross-platform system-tray" thingy - I don't think this is entirely possible without some truly cross-platform framework like Elektron or something, which can give ability to use system-tray/taskbar feature.
For the detecting mouse even when window is not focused - use pynput with asyncio (example for kivy + asyncio in their official repository). Basically: you can detect keyboard events even when app is not focused with background working code with asyncio. Then it will detect every keystroke.
import PySimpleGUI as sg
from psgtray import SystemTray
"""
A System Tray Icon courtesy of pystray and your friends at PySimpleGUI
Import the SystemTray object with this line of code:
from psgtray import SystemTray
Key for the system tray icon is:
tray = SystemTray()
tray.key
values[key] contains the menu item chosen.
One trick employed here is to change the window's event to be the event from the System Tray.
Copyright PySimpleGUI 2021
"""
def main():
menu = ['',
['Show Window', 'Hide Window', '---', '!Disabled Item', 'Change Icon', ['Happy', 'Sad', 'Plain'], 'Exit']]
tooltip = 'Tooltip'
layout = [[sg.Text('My PySimpleGUI Celebration Window - X will minimize to tray')],
[sg.T('Double clip icon to restore or right click and choose Show Window')],
[sg.T('Icon Tooltip:'), sg.Input(tooltip, key='-IN-', s=(20, 1)), sg.B('Change Tooltip')],
[sg.Multiline(size=(60, 10), reroute_stdout=False, reroute_cprint=True, write_only=True, key='-OUT-')],
[sg.Button('Go'), sg.B('Hide Icon'), sg.B('Show Icon'), sg.B('Hide Window'), sg.Button('Exit')]]
window = sg.Window('Window Title', layout, finalize=True, enable_close_attempted_event=True)
tray = SystemTray(menu, single_click_events=False, window=window, tooltip=tooltip, icon='cogent_logo.png')
tray.show_message('System Tray', 'System Tray Icon Started!')
sg.cprint(sg.get_versions())
while True:
event, values = window.read()
# IMPORTANT step. It's not required, but convenient. Set event to value from tray
# if it's a tray event, change the event variable to be whatever the tray sent
if event == tray.key:
sg.cprint(f'System Tray Event = ', values[event], c='white on red')
event = values[event] # use the System Tray's event as if was from the window
if event in (sg.WIN_CLOSED, 'Exit'):
break
sg.cprint(event, values)
tray.show_message(title=event, message=values)
if event in ('Show Window', sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED):
window.un_hide()
window.bring_to_front()
elif event in ('Hide Window', sg.WIN_CLOSE_ATTEMPTED_EVENT):
window.hide()
tray.show_icon() # if hiding window, better make sure the icon is visible
# tray.notify('System Tray Item Chosen', f'You chose {event}')
elif event == 'Happy':
tray.change_icon(sg.EMOJI_BASE64_HAPPY_JOY)
elif event == 'Sad':
tray.change_icon(sg.EMOJI_BASE64_FRUSTRATED)
elif event == 'Plain':
tray.change_icon(sg.DEFAULT_BASE64_ICON)
elif event == 'Hide Icon':
tray.hide_icon()
elif event == 'Show Icon':
tray.show_icon()
elif event == 'Change Tooltip':
tray.set_tooltip(values['-IN-'])
tray.close() # optional but without a close, the icon may "linger" until moused over
window.close()
if __name__ == '__main__':
main()
If you're willing to depart from Kivy and use another framework, PySimpleGUI has a System Tray capability (at least for Windows, and perhaps Linux/Mac) when running the tkinter version. The PySimpleGUIQt port has a more "official" System Tray feature.
The GitHub Repo PySimpleHotkey is one example of how to use the psgtray package to make a hotkey program.
https://github.com/PySimpleGUI/PySimpleHotkey

Force overlay a PySimpleGUI window

I just want that if someone tries to close the GUI window using close button instead of clicking "OK", the window reappears... In simple words, they cannot close this one or access any other window without clicking "OK".
import PySimpleGUI as sg
layout = [[sg.Text("Click OK to start the unlock process using Face Verification")],
[sg.Button("OK")]]
# Create the window
window = sg.Window("Demo", layout)
# Create an event loop
while True:
event, values = window.read()
# End program if user closes window or
# presses the OK button
if event == "OK" or event == sg.WIN_CLOSED:
break
window.close()
It is defined in source code of PySimpleGUI.
You can change it to generate an event "WIN_CLOSE", like this
import PySimpleGUI as sg
layout = [[sg.Text("Click OK to start the unlock process using Face Verification")], [sg.Button("OK")]]
window = sg.Window("Title", layout, finalize=True)
window.TKroot.protocol("WM_DESTROY_WINDOW", lambda:window.write_event_value("WIN_CLOSE", ()))
window.TKroot.protocol("WM_DELETE_WINDOW", lambda:window.write_event_value("WIN_CLOSE", ()))
while True:
event, values = window.read()
print(event)
if event in ("OK", sg.WIN_CLOSED):
break
elif event == "WIN_CLOSE":
print("Close Button 'X' clicked !")
window.close()
WIN_CLOSE
Close Button 'X' clicked !
WIN_CLOSE
Close Button 'X' clicked !
WIN_CLOSE
Close Button 'X' clicked !
OK

Detect cancel events of FileBrowse in PySimpleGUI

I am trying to build a user interface using PySimpleGui. Below is a minimal example of a file browser button. If you click on the button, it opens an Open file dialog.
import PySimpleGUI as sg
file_browse_button = sg.FileBrowse(enable_events=True)
layout = [[file_browse_button]]
window = sg.Window('My window', layout)
while True:
event, values = window.read()
print(event, '##', values)
if event is None or event == 'Cancel':
break
window.close()
When selecting a file, this produces (for example):
Browse ## {'Browse': '/path/to/file.txt'}
The problem is that if the user selects "Cancel" or just the previously selected file in the browser window, it will still produce the same event, not changing the value. Is there a way to differentiate the two cases?
My understanding is that the FileBrowse button best operates with its target parameter. That's how I use it anyway. The target parameter is the key for another PySimpleGUI element in the window where the button will store its value when the user clicks "ok". If the user clicks "Cancel" in the FileBrowse button, any selected value will not be inserted into the target.
import PySimpleGUI as sg
file_browse_button = sg.FileBrowse(target='filebrowse_field')
filebrowse_field = sg.Input(key='filebrowse_field')
ok_cancel = [ [sg.Button('OK'), sg.Button('Cancel')]]
layout = [[filebrowse_field, file_browse_button],
ok_cancel]
window = sg.Window('My window', layout)
while True:
event, values = window.read()
print(event, '##', values)
if event is None or event == 'Cancel':
break
window.close()
Note also that I don't have the enable-events option set for the FileBrowse element. I believe the intention is that your window has in it ok, cancel button to manage those events explicitly.

Categories

Resources