Pysimplegui help, I want to rerun my process over and over - python-3.x

I'm still learning python and I am giving myself a project which I am iterating on. I create some random game selectors using CSV files or text files. So I did some research and made a simple gui using pysimplegui and it works. However I want to rerun the script to select a new game with I hit the reload button and I'm just not finding the information I looking for. Maybe I am overthinking it, or underthinking it.
import random
import csv
import PySimpleGUI as sg
#select Random game from CSV file
with open("Retro Games Spreadsheet! - Games!.csv") as f:
reader = csv.reader(f)
chosen_row = random.choice(list(reader))
f.close()
print(chosen_row)
#Create the layout
layout = [[sg.Text(chosen_row)], sg.Button("Reload")],
# Create the window
window = sg.Window("Select Random Game", layout)
# Create an event loop
while True:
event, values = window.read()
# End program if user closes window or
# reloads with the Reload button
if event == sg.WIN_CLOSED:
break
elif event == "Reload":
window[[sg.Text(chosen_row)]]
window.Refresh()
window.close()

Just update all related elements in your layout.
import random
import csv
import PySimpleGUI as sg
#select Random game from CSV file
with open("Retro Games Spreadsheet! - Games!.csv") as f:
reader = csv.reader(f)
rows = list(reader)
chosen_row = random.choice(rows)
#f.close() it will be auto-closed after with statement
print(chosen_row)
#Create the layout
layout = [[sg.Text(chosen_row, key="-ROW-")], sg.Button("Reload")],
# Create the window
window = sg.Window("Select Random Game", layout)
# Create an event loop
while True:
event, values = window.read()
# End program if user closes window or
# reloads with the Reload button
if event == sg.WIN_CLOSED:
break
elif event == "Reload":
chosen_row = random.choice(rows)
window['-ROW-'].update(chosen_row)
window.close()

Related

How to convert user voice input into text and store in the excel sheet?

Dear All,
I wrote a simple program of data entry into excel using python.
But I task is that this manual entry will be performed from user voice input.
Can anybody help me in this regard.
import PySimpleGUI as sg
import pandas as pd
import speech_recognition as sr
# Add some color to the window
sg.theme('Green')
exfile = 'Break Down Report.xlsx'
df = pd.read_excel(exfile)
layout = [ # for input text
[sg.Text('Machines Breakdown Entries Table:')],
[sg.Text('S.No', size=(15,1)), sg.InputText(key='S.No')],
[sg.Text('Fault Desc', size=(15,1)), sg.InputText(key='Fault Desc')],
[sg.Text('Start Time', size=(15,1)), sg.InputText(key='Start Time')],
[sg.Text('End Time', size=(15,1)), sg.InputText(key='End Time')],
[sg.Text('Date', size=(15,1)), sg.InputText(key='Date')],
[sg.Text('Employe Name', size=(15,1)), sg.InputText(key='Employe Name')],
# for buttons
[sg.Button('Speak'), sg.Save(), sg.Button('Clear'), sg.Quit()]
]
# main tool bar Window text
window = sg.Window('Daily Breakdown Report ', layout)
def clear_input():
for key in values:
window[key]('')
return None
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Quit':
break
if event == 'Clear':
clear_input()
if event == 'Save':
df = df.append(values, ignore_index=True)
df.to_excel(exfile, index=False)
sg.popup('Data saved!')
clear_input()
window.close()
I want to develop a program in Python that performs voice activity in an excel sheet, similar to Google Docs.
According to above code. Manual entries will be performed by the user typing. But i want create a voice button in which user will command by voice and input should store into text and save in excel sheet.
Using thread to do the conversion, like the method window.perform_long_operation.
Demo Code
import speech_recognition as sr
import PySimpleGUI as sg
def speak():
while True:
r = sr.Recognizer()
text = '~ Not recongnized ~'
with sr.Microphone() as source:
audio = r.listen(source)
try:
text = r.recognize_google(audio,language="en-IN")
except:
pass
return text
layout = [
[sg.Multiline(size=(80, 10), autoscroll=True, key='-ML-')],
[sg.Push(), sg.Button('Speak')],
]
window = sg.Window('Title', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'Speak':
window['Speak'].update(disabled=True)
window.perform_long_operation(speak, 'Done')
elif event == 'Done':
text = values['Done']
window['Speak'].update(disabled=False)
window['-ML-'].update(text+'\n', append=True)
window.close()

PySimpleGUI - Updating a listbox on a button event

I'm trying to make a Python program with a UI that shows simple widget like a frame, a listbox and a table. I would like to populate the listbox with input from the user. So I create the listbox and "fill it" qith a blank list, then the user type in a name, click the button and the list will have that name in it and the name will be shown in the listbox. I quite manage to do this, but the name in the listbox are in vertical, and the element of the list are every single characters entered bu the user in the Input field. Furthermore, the elements will are overwritten when the user types another name in the inputbox.
This is the code
import PySimpleGUI as sg
from openpyxl import Workbook
from openpyxl import load_workbook
createColony_Layout=[]
firstWindow_Layout=[]
colonyList = []
# Software theme
# FIRST WINDOW
# Layouts
menuBar_Layout = [
['&File', ['&Inserisci file ICM Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
['&Edit', ['Undo']],
['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
['&Help', ['&About...']]
]
createColony_Layout = [
[sg.Text('Insert researcher name', size=20)],
[sg.Input(size=15, key='c')],
[sg.Button(button_text='Create', button_type=7)]
]
createColonyFrame = sg.Frame('Create new colony', createColony_Layout, size=(200, 100))
firstWindow_Layout = [
[sg.MenubarCustom(menuBar_Layout)],
[sg.Push(), sg.Text('Colony management',
justification=('Center'), font=('Helvetica', 30)), sg.Push()],
[createColonyFrame],
[sg.Listbox(colonyList, size =(50, 25), key='lista')]
]
# Create window
window = sg.Window('Colony management', firstWindow_Layout, size=(1300, 700),
auto_size_text= True, resizable=True, finalize=True)
window.TKroot.minsize(500,250)
#window.TKroot.maxsize(600, 700)
# Program loop
while True:
event,values = window.read()
if event == 'Create':
window['list'].update(values['c'])
if event == sg.WINDOW_CLOSED:
break
window.close()
And this is a screen of the window
I hope this is enough for you to help me, thank you.
The call to update for Listbox takes a list/tuple as the first argument. A string looks like a list of single characters in Python. To add a single value, make it a tuple instead of a string.
window['list'].update(values['c'])
becomes
window['lista'].update((values['c'],))
There is also a call to set the minimum size for a window that you can use instead of the TKroot access you've got in your code.
If you want a minimum size of (500, 250), then use this call:
window.set_min_size((500, 250))
import PySimpleGUI as sg
# from openpyxl import Workbook
# from openpyxl import load_workbook
createColony_Layout=[]
firstWindow_Layout=[]
colonyList = []
# Software theme
# FIRST WINDOW
# Layouts
menuBar_Layout = [
['&File', ['&Inserisci file ICM Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
['&Edit', ['Undo']],
['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
['&Help', ['&About...']]
]
createColony_Layout = [
[sg.Text('Insert researcher name', size=20)],
[sg.Input(size=15, key='c')],
[sg.Button(button_text='Create', button_type=7)]
]
createColonyFrame = sg.Frame('Create new colony', createColony_Layout, size=(200, 100))
firstWindow_Layout = [
[sg.MenubarCustom(menuBar_Layout)],
[sg.Push(), sg.Text('Colony management',
justification=('Center'), font=('Helvetica', 30)), sg.Push()],
[createColonyFrame],
[sg.Listbox(colonyList, size =(50, 25), key='lista')]
]
# Create window
window = sg.Window('Colony management', firstWindow_Layout, size=(1300, 700),
auto_size_text= True, resizable=True, finalize=True)
window.set_min_size((500, 250))
# window.TKroot.minsize(500,250)
#window.TKroot.maxsize(600, 700)
# Program loop
while True:
event,values = window.read()
if event == 'Create':
window['lista'].update((values['c'],))
if event == sg.WINDOW_CLOSED:
break
window.close()

display the CMD console in a window in GUI - PySimpleGUI

I'm creating a GUI using PySimpleGUI and want to have a frame that displays the output prints of all the functions in the program (as in the cmd console).
I tried using (relevant code lines):
def hello():
print('hello')
layout = [[sg.Frame("Output console", [[sg.Text(" ", size=(0, 1), key='-OUTPUT-')]])]]
window['-OUTPUT-'].update(hello())
I can see the print in the console but not in the Frame in the GUI.
How can i do that?
To show the output like in CMD console, you should use the sg.Multiline, not the sg.Text which is just a label.
To redirect the output of stdout and stderr, set options reroute_stdout=True and reroute_stderr=True, also set option autoscroll=True to automatically scroll as more data added to the end of element.
Demo Code - GUI will update only back to window.read
import PySimpleGUI as sg
def hello():
print('hello')
frame_layout = [[sg.Multiline("", size=(80, 20), autoscroll=True,
reroute_stdout=True, reroute_stderr=True, key='-OUTPUT-')]]
layout = [
[sg.Frame("Output console", frame_layout)],
[sg.Push(), sg.Button("Say Hello")],
]
window = sg.Window("Title", layout, finalize=True)
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == "Say Hello":
hello()
window.close()
To update GUI in realtime, you can call update(value, append=True) and window.refresh, not to use the print statement, or
Following code show the way to print to sg.multiline immediately. To avoid stop GUI working for long printing, mutlithread required here. It will not work for real time printing during event loop because loop is working on your printing statement, then back to window.read after it done.
It is much complex, not sure if any bug.
import sys
from time import sleep
from datetime import datetime
import threading
import PySimpleGUI as sg
def print_task():
global printing
while printing:
print(datetime.now().strftime("%H-%M-%S"), datetime.now().strftime("%H-%M-%S"))
sleep(0.5)
class Unbuffered(object):
def __init__(self, window):
self.window = window
def write(self, data):
self.window.write_event_value("OUT", data)
def writelines(self, datas):
self.window.write_event_value("OUT", ''.join(datas))
frame_layout = [[sg.Multiline("", size=(80, 20), autoscroll=True, key='-OUTPUT-')]]
layout = [
[sg.Frame("Output console", frame_layout)],
[sg.Push(), sg.Button("Print"), sg.Button('Stop')],
]
window = sg.Window("Title", layout, finalize=True)
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout = Unbuffered(window)
sys.stderr = Unbuffered(window)
printing = False
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == 'Print':
if not printing:
printing = True
threading.Thread(target=print_task, daemon=True).start()
elif event == 'Stop':
printing = False
elif event == "OUT":
window['-OUTPUT-'].update(values["OUT"], append=True)
printing = False
sys.stdout, sys.stderr = old_stdout, old_stderr
window.close()

Python, CrossWord, Gui

I am very beginner on Python and I want to create crossworld template, like this. How can I create gui exactly like this on python ? Are there any tools or libraries ? I made lots of research but ı could not find anything.
Thanks!!!
Since you're a beginner, try out PySimpleGUI.
Here's a little program to get you started...
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import random
BOX_SIZE = 25
layout = [
[sg.Text('Crossword Puzzle Using PySimpleGUI'), sg.Text('', key='_OUTPUT_')],
[sg.Graph((800,800), (0,450), (450,0), key='_GRAPH_')],
[sg.Button('Show'), sg.Button('Exit')]
]
window = sg.Window('Window Title').Layout(layout).Finalize()
g = window.FindElement('_GRAPH_')
for row in range(16):
for i in range(16):
if random.randint(0,100) > 10:
g.DrawRectangle((i*BOX_SIZE+5,row*BOX_SIZE+3), (i*BOX_SIZE+BOX_SIZE+5,row*BOX_SIZE+BOX_SIZE+3), line_color='black')
else:
g.DrawRectangle((i*BOX_SIZE+5,row*BOX_SIZE+3), (i*BOX_SIZE+BOX_SIZE+5,row*BOX_SIZE+BOX_SIZE+3), line_color='black', fill_color='black')
g.DrawText('{}'.format(row*6+i+1),(i*BOX_SIZE+10,row*BOX_SIZE+8))
while True: # Event Loop
event, values = window.Read()
print(event, values)
if event is None or event == 'Exit':
break
window.Close()

PyQt : Manage two MainWindow

i'm trying to manage two MainWindow (MainWindow & AccessWindow) with PyQt for my RFID ACCESS CONTROL Project.
I want to show the first MainWindow all time (Endless Loop).
Then, i want to hide it and show the second MainWindow when the RFID Reader (who's working on "auto-reading mode") read an RFID Tag.
so in the main python program i have a pseudo "do while" loop (while True: and break with a condition) to read on serial port the data provided by the reader. Then i check a DB.. It's not important. So the trigger event is "when the reader read something).
I got some help from another forum and now i have this:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys, pyodbc, serial
import os
import time
#Variables
Code_Zone = "d"
class MainWindow(QtGui.QWidget):
def __init__(self, main):
super(MainWindow, self).__init__()
self.main = main
self.grid = QtGui.QGridLayout(self)
self.welcome = QtGui.QLabel("WELCOME", self)
self.grid.addWidget(self.welcome, 2, 2, 1, 5)
class AccessWindow(QtGui.QWidget):
def __init__(self):
super(AccessWindow, self).__init__()
self.setMinimumSize(150, 50)
self.grid = QtGui.QGridLayout(self)
self.label = QtGui.QLabel(self)
self.grid.addWidget(self.label, 1, 1, 1, 1)
class Main(object):
def __init__(self):
self.accueil = MainWindow(self)
self.accueil.show()
self.access = AccessWindow()
def wait(self):
# RFID READER ENDLESS LOOP
while 1:
global EPC_Code
ser = serial.Serial(port='COM6', baudrate=115200)
a = ser.read(19).encode('hex')
if (len(a)==38):
EPC_Code = a[14:]
print ('EPC is : ' + EPC_Code)
break
else:
continue
ser.close()
self.on_event(EPC_Code)
def on_event(self, data):
def refresh():
self.toggle_widget(False)
self.wait()
# vérification des données
EPC_Code = data
sql_command = "[Get_Access_RFID] #Code_RFID = '"+EPC_Code+"', #Code_Zone = '"+Code_Zone+"'" # STORED PROCEDURE
db_cursor.execute(sql_command)
rows = db_cursor.fetchone()
result= str(rows[0])
print ("result = " + str(result))
if result == "True":
# si OK
self.access.label.setText('ACCESS GRANTED')
else:
# si pas OK
self.access.label.setText('ACCESS DENIED')
self.toggle_widget(True)
QtCore.QTimer.singleShot(2000, refresh)
def toggle_widget(self, b):
self.accueil.setVisible(not b)
self.access.setVisible(b)
if __name__=='__main__':
cnxn = """DRIVER={SQL Server};SERVER=***;PORT=***;UID=***;PWD=***;DATABASE=***"""
db_connection = pyodbc.connect(cnxn)
db_cursor = db_connection.cursor()
print ('Connected TO DB & READY')
app = QtGui.QApplication(sys.argv)
main = Main()
main.wait()
sys.exit(app.exec_())
and now my problem is that the text of the first window doesn't appear when i run the program but the text of the second window appear when i keep my badge near the RFID Reader.
Instead of two MainWindow, create one. As content, create two classes which extend QtGui.QWidget called MainView and AccessView. Instead of replacing the window, just put the correct view into the window. That way, you can swap views without opening/closing windows.
If you use a layout, then the window will resize to fit the view.
The next problem is that you block the UI thread which means Qt can't handle events (like the "paint UI" event). To fix this, you must move the RFID handling code in a background thread. You can emit signals from this background thread to update the UI.
Note: You must not call UI code from a thread!! Just emit signals. PyQt's main loop will see them and process them.
Related:
https://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/
Updating GUI elements in MultiThreaded PyQT, especially the second example using signals. The first example is broken (calling addItem() from a thread) is not allowed)

Resources