diff --git a/Demo_All_Widgets.py b/Demo_All_Widgets.py
index 6a83153e..bf81163d 100644
--- a/Demo_All_Widgets.py
+++ b/Demo_All_Widgets.py
@@ -3,13 +3,11 @@ import PySimpleGUI as sg
sg.ChangeLookAndFeel('GreenTan')
-
# ------ Menu Definition ------ #
menu_def = [['File', ['Open', 'Save', 'Exit', 'Properties']],
['Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
['Help', 'About...'], ]
-
# ------ Column Definition ------ #
column1 = [[sg.Text('Column 1', background_color='#F7F3EC', justification='center', size=(10, 1))],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')],
diff --git a/Demo_Button_Click.py b/Demo_Button_Click.py
index 4a4ba306..2dfa029c 100644
--- a/Demo_Button_Click.py
+++ b/Demo_Button_Click.py
@@ -12,10 +12,7 @@ layout = [
sg.ReadFormButton('Submit', button_color=('white', 'springgreen4'), key='submit')]
]
-form = sg.FlexForm("Button Click", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False,
- default_button_element_size=(12,1))
-form.Layout(layout)
-form.Finalize() # only needed if want to diable elements prior to showing form
+form = sg.FlexForm("Button Click", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, default_button_element_size=(12,1)).Layout(layout).Finalize()
form.FindElement('submit').Update(disabled=True)
diff --git a/Demo_Button_States.py b/Demo_Button_States.py
index e0198d82..e3a9cfb7 100644
--- a/Demo_Button_States.py
+++ b/Demo_Button_States.py
@@ -1,58 +1,31 @@
import PySimpleGUI as sg
-"""
-Demonstrates using a "tight" layout with a Dark theme.
-Shows how button states can be controlled by a user application. The program manages the disabled/enabled
-states for buttons and changes the text color to show greyed-out (disabled) buttons
-"""
-sg.ChangeLookAndFeel('Dark')
-sg.SetOptions(element_padding=(0,0))
+sg.ChangeLookAndFeel('LightGreen')
+sg.SetOptions(element_padding=(0, 0))
-layout = [[sg.T('User:', pad=((3,0),0)), sg.OptionMenu(values = ('User 1', 'User 2'), size=(20,1)), sg.T('0', size=(8,1))],
- [sg.T('Customer:', pad=((3,0),0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20,1)), sg.T('1', size=(8,1))],
- [sg.T('Notes:', pad=((3,0),0)), sg.In(size=(44,1), background_color='white', text_color='black')],
- [sg.ReadFormButton('Start', button_color=('white', 'black'), key='Start'),
- sg.ReadFormButton('Stop', button_color=('white', 'black'), key='Stop'),
- sg.ReadFormButton('Reset', button_color=('white', 'firebrick3'), key='Reset'),
- sg.ReadFormButton('Submit', button_color=('white', 'springgreen4'), key='Submit')]
- ]
+# ------ Menu Definition ------ #
+menu_def = [['File', ['Open', 'Save', 'Exit' ]],
+ ['Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
+ ['Help', 'About...'], ]
-form = sg.FlexForm("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False,
- default_button_element_size=(12,1))
-form.Layout(layout)
-form.Finalize()
-form.FindElement('Stop').Update(disabled=True)
-form.FindElement('Reset').Update(disabled=True)
-form.FindElement('Submit').Update(disabled=True)
-recording = have_data = False
+# ------ GUI Defintion ------ #
+layout = [
+ [sg.Menu(menu_def)],
+ [sg.Output(size=(60, 20))]
+]
+
+form = sg.FlexForm("Windows-like program", default_element_size=(12, 1), auto_size_text=False, auto_size_buttons=False,
+ default_button_element_size=(12, 1)).Layout(layout)
+
+# ------ Loop & Process button menu choices ------ #
while True:
button, values = form.Read()
- print(button)
- if button is None:
- exit(69)
- if button is 'Start':
- form.FindElement('Start').Update(disabled=True)
- form.FindElement('Stop').Update(disabled=False)
- form.FindElement('Reset').Update(disabled=False)
- form.FindElement('Submit').Update(disabled=True)
- recording = True
- elif button is 'Stop' and recording:
- form.FindElement('Stop').Update(disabled=True)
- form.FindElement('Start').Update(disabled=False)
- form.FindElement('Submit').Update(disabled=False)
- recording = False
- have_data = True
- elif button is 'Reset':
- form.FindElement('Stop').Update(disabled=True)
- form.FindElement('Start').Update(disabled=False)
- form.FindElement('Submit').Update(disabled=True)
- form.FindElement('Reset').Update(disabled=False)
- recording = False
- have_data = False
- elif button is 'Submit' and have_data:
- form.FindElement('Stop').Update(disabled=True)
- form.FindElement('Start').Update(disabled=False)
- form.FindElement('Submit').Update(disabled=True)
- form.FindElement('Reset').Update(disabled=False)
- recording = False
-
+ if button == None or button == 'Exit':
+ break
+ print('Button = ', button)
+ # ------ Process menu choices ------ #
+ if button == 'About...':
+ sg.Popup('About this program', 'Version 1.0', 'PySimpleGUI rocks...')
+ elif button == 'Open':
+ filename = sg.PopupGetFile('file to open', no_window=True)
+ print(filename)
\ No newline at end of file
diff --git a/Demo_Canvas.py b/Demo_Canvas.py
index 05156c7e..cbe01caa 100644
--- a/Demo_Canvas.py
+++ b/Demo_Canvas.py
@@ -6,9 +6,7 @@ layout = [
[sg.T('Change circle color to:'), sg.ReadFormButton('Red'), sg.ReadFormButton('Blue')]
]
-form = sg.FlexForm('Canvas test')
-form.Layout(layout)
-form.Finalize()
+form = sg.FlexForm('Canvas test').Layout(layout).Finalize()
cir = form.FindElement('canvas').TKCanvas.create_oval(50, 50, 100, 100)
diff --git a/Demo_Chatterbot.py b/Demo_Chatterbot.py
index f7936482..12832a46 100644
--- a/Demo_Chatterbot.py
+++ b/Demo_Chatterbot.py
@@ -12,6 +12,7 @@ to collect user input that is sent to the chatbot. The reply is displayed in th
# Create the 'Trainer GUI'
# The Trainer GUI consists of a lot of progress bars stacked on top of each other
sg.ChangeLookAndFeel('GreenTan')
+sg.DebugWin()
MAX_PROG_BARS = 20 # number of training sessions
bars = []
texts = []
@@ -21,8 +22,7 @@ for i in range(MAX_PROG_BARS):
texts.append(sg.T(' ' * 20, size=(20, 1), justification='right'))
training_layout += [[texts[i], bars[i]],] # add a single row
-training_form = sg.FlexForm('Training')
-training_form.Layout(training_layout)
+training_form = sg.FlexForm('Training').Layout(training_layout)
current_bar = 0
# callback function for training runs
@@ -50,19 +50,20 @@ chatbot = ChatBot('Ron Obvious', trainer='chatterbot.trainers.ChatterBotCorpusTr
chatbot.train("chatterbot.corpus.english")
################# GUI #################
-with sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2)) as form:
- layout = [[sg.Output(size=(80, 20))],
- [sg.Multiline(size=(70, 5), enter_submits=True),
- sg.ReadFormButton('SEND', bind_return_key=True), sg.ReadFormButton('EXIT')]]
- form.Layout(layout)
- # ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
- while True:
- button, (value,) = form.Read()
- if button is not 'SEND':
- break
- string = value.rstrip()
- print(' '+string)
- # send the user input to chatbot to get a response
- response = chatbot.get_response(value.rstrip())
- print(response)
\ No newline at end of file
+layout = [[sg.Output(size=(80, 20))],
+ [sg.Multiline(size=(70, 5), enter_submits=True),
+ sg.ReadFormButton('SEND', bind_return_key=True), sg.ReadFormButton('EXIT')]]
+
+form = sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2)).Layout(layout)
+
+# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
+while True:
+ button, (value,) = form.Read()
+ if button is not 'SEND':
+ break
+ string = value.rstrip()
+ print(' '+string)
+ # send the user input to chatbot to get a response
+ response = chatbot.get_response(value.rstrip())
+ print(response)
\ No newline at end of file
diff --git a/Demo_Desktop_Widget_CPU_Graph.py b/Demo_Desktop_Widget_CPU_Graph.py
index ddc6663a..3456ce3e 100644
--- a/Demo_Desktop_Widget_CPU_Graph.py
+++ b/Demo_Desktop_Widget_CPU_Graph.py
@@ -36,8 +36,7 @@ def main():
layout = [ [sg.Quit( button_color=('white','black')), sg.T('', pad=((100,0),0), font='Any 15', key='output')],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
- form = sg.FlexForm('CPU Graph', grab_anywhere=True, keep_on_top=True, background_color='black', no_titlebar=True, use_default_focus=False)
- form.Layout(layout)
+ form = sg.FlexForm('CPU Graph', grab_anywhere=True, keep_on_top=True, background_color='black', no_titlebar=True, use_default_focus=False).Layout(layout)
graph = form.FindElement('graph')
output = form.FindElement('output')
diff --git a/Demo_Disable_Elements.py b/Demo_Disable_Elements.py
index cf351a8f..aed84807 100644
--- a/Demo_Disable_Elements.py
+++ b/Demo_Disable_Elements.py
@@ -20,13 +20,9 @@ layout = [
sg.ReadFormButton('Values', button_color=('white', 'springgreen4')),
sg.SimpleButton('Exit', button_color=('white', '#00406B'))]]
-form = sg.FlexForm("Time Tracker", default_element_size=(12, 1), text_justification='r', auto_size_text=False,
+form = sg.FlexForm("Disable Elements Demo", default_element_size=(12, 1), text_justification='r', auto_size_text=False,
auto_size_buttons=False, keep_on_top=True, grab_anywhere=False,
- default_button_element_size=(12, 1))
-
-form.Layout(layout)
-
-form.Finalize()
+ default_button_element_size=(12, 1)).Layout(layout).Finalize()
form.FindElement('cbox').Update(disabled=True)
form.FindElement('listbox').Update(disabled=True)
diff --git a/Demo_Font_Sizer.py b/Demo_Font_Sizer.py
index e79e686e..d030af93 100644
--- a/Demo_Font_Sizer.py
+++ b/Demo_Font_Sizer.py
@@ -11,7 +11,7 @@ form = sg.FlexForm("Font size selector", grab_anywhere=False)
form.Layout(layout)
while True:
button, values= form.Read()
- if button is None:
+ if button is None or button == 'Quit':
break
sz_spin = int(values['spin'])
sz_slider = int(values['slider'])
diff --git a/Demo_Func_Callback_Simulation.py b/Demo_Func_Callback_Simulation.py
index 198337c3..a3f5df84 100644
--- a/Demo_Func_Callback_Simulation.py
+++ b/Demo_Func_Callback_Simulation.py
@@ -1,36 +1,14 @@
import PySimpleGUI as sg
-# This design pattern simulates button callbacks
-# Note that callbacks are NOT a part of the package's interface to the
-# caller intentionally. The underlying implementation actually does use
-# tkinter callbacks. They are simply hidden from the user.
+layout = [[sg.Text('Filename', )],
+ [sg.Input(), sg.FileBrowse()],
+ [sg.OK(), sg.Cancel()]]
-# The callback functions
-def button1():
- print('Button 1 callback')
+button, (number,) = sg.FlexForm('Get filename example').LayoutAndRead(layout)
-def button2():
- print('Button 2 callback')
-# Create a standard form
-form = sg.FlexForm('Button callback example')
-# Layout the design of the GUI
-layout = [[sg.Text('Please click a button', auto_size_text=True)],
- [sg.ReadFormButton('1'), sg.ReadFormButton('2'), sg.Quit()]]
-# Show the form to the user
-form.Layout(layout)
-# Event loop. Read buttons, make callbacks
-while True:
- # Read the form
- button, value = form.Read()
- # Take appropriate action based on button
- if button == '1':
- button1()
- elif button == '2':
- button2()
- elif button =='Quit' or button is None:
- break
+import PySimpleGUI as sg
-# All done!
-sg.PopupOK('Done')
+button, (filename,) = sg.FlexForm('Get filename example').LayoutAndRead(
+ [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()]])
\ No newline at end of file
diff --git a/Demo_Graph_Drawing.py b/Demo_Graph_Drawing.py
index fc4ca3c8..de8a82f7 100644
--- a/Demo_Graph_Drawing.py
+++ b/Demo_Graph_Drawing.py
@@ -5,15 +5,14 @@ layout = [
[sg.T('Change circle color to:'), sg.ReadFormButton('Red'), sg.ReadFormButton('Blue'), sg.ReadFormButton('Move')]
]
-form = sg.FlexForm('Canvas test')
-form.Layout(layout)
-form.Finalize()
+form = sg.FlexForm('Graph test').Layout(layout).Finalize()
graph = form.FindElement('graph')
circle = graph.DrawCircle((75,75), 25, fill_color='black',line_color='white')
point = graph.DrawPoint((75,75), 10, color='green')
oval = graph.DrawOval((25,300), (100,280), fill_color='purple', line_color='purple' )
rectangle = graph.DrawRectangle((25,300), (100,280), line_color='purple' )
+line = graph.DrawLine((0,0), (100,100))
while True:
button, values = form.Read()
diff --git a/Demo_Graph_Element_Sine_Wave.py b/Demo_Graph_Element_Sine_Wave.py
index 0d451067..5d922fde 100644
--- a/Demo_Graph_Element_Sine_Wave.py
+++ b/Demo_Graph_Element_Sine_Wave.py
@@ -1,10 +1,9 @@
import math
import PySimpleGUI as sg
-layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(-100,-100), graph_top_right=(100,100), background_color='white', key='graph')],]
+layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(-100,-100), graph_top_right=(100,100), background_color='white', key='graph', tooltip='This is a cool graph!')],]
-form = sg.FlexForm('Graph of Sine Function').Layout(layout)
-form.Finalize()
+form = sg.FlexForm('Graph of Sine Function', grab_anywhere=True).Layout(layout).Finalize()
graph = form.FindElement('graph')
graph.DrawLine((-100,0), (100,0))
diff --git a/Demo_Graph_Noise.py b/Demo_Graph_Noise.py
index da52464d..fbef4bc4 100644
--- a/Demo_Graph_Noise.py
+++ b/Demo_Graph_Noise.py
@@ -31,10 +31,7 @@ def main():
layout = [ [sg.Quit( button_color=('white','black'))],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
- form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False)
- form.Layout(layout)
-
- form.Finalize()
+ form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False).Layout(layout).Finalize()
graph = form.FindElement('graph')
prev_response_time = None
diff --git a/Demo_Matplotlib.py b/Demo_Matplotlib.py
index 8b5d334d..7b2553f7 100644
--- a/Demo_Matplotlib.py
+++ b/Demo_Matplotlib.py
@@ -107,19 +107,16 @@ fig = plt.gcf() # if using Pyplot then get the figure from the plot
# information to display. #
# --------------------------------------------------------------------------------#
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
-canvas_elem = sg.Canvas(size=(figure_w, figure_h)) # get the canvas we'll be drawing on
# define the form layout
layout = [[sg.Text('Plot test')],
- [canvas_elem],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
# create the form and show it without the plot
-form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI')
-form.Layout(layout)
-form.ReadNonBlocking()
+form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
# add the plot to the window
-fig_photo = draw_figure(canvas_elem.TKCanvas, fig)
+fig_photo = draw_figure(form.FindElement('canvas').TKCanvas, fig)
# show it all again and get buttons
button, values = form.Read()
diff --git a/Demo_Ping_Line_Graph.py b/Demo_Ping_Line_Graph.py
index 1faa9754..ef6e2f4d 100644
--- a/Demo_Ping_Line_Graph.py
+++ b/Demo_Ping_Line_Graph.py
@@ -1,8 +1,587 @@
-import ping
from threading import Thread
import time
import PySimpleGUI as sg
+# !/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+# =============================================================================#
+import argparse
+import os, sys, socket, struct, select, time, signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+# =============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+
+# =============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string) / 2)) * 2
+ sum = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum = sum + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum = sum + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string) - 1]
+ try: # For Python3
+ sum += loByte
+ except: # For Python2
+ sum += ord(loByte)
+
+ sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
+ sum += (sum >> 16) # Add carry from above (if any)
+ answer = ~sum & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+
+# =============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime - sentTime) * 1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+
+# =============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ # destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size - 8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ # data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+
+# =============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout / 1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ # print (len(recPacket.encode()))
+ return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+
+# =============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+
+# =============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+
+# =============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ dump_stats(myStats)
+
+
+# =============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return False
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+
+# =============================================================================#
+def main():
+ parser = argparse.ArgumentParser(description=__description__)
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='quiet output')
+ parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS,
+ help=('number of packets to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT,
+ help=('time to wait for a response in seoncds '
+ '(default: %(default)s)'))
+ parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE,
+ help=('number of data bytes to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('destination')
+ # args = parser.parse_args()
+
+ ping = verbose_ping
+ # if args.quiet:
+ # ping = quiet_ping
+ ping('Google.com', timeout=1000)
+ # ping(args.destination, timeout=args.timeout*1000, count=args.count,
+ # packet_size=args.packet_size)
+
+
# set coordinate system
canvas_right = 300
canvas_left = 0
@@ -22,7 +601,7 @@ def ping_thread(args):
global g_exit, g_response_time
while not g_exit:
- g_response_time = ping.quiet_ping('google.com', timeout=1000)
+ g_response_time = quiet_ping('google.com', timeout=1000)
def convert_xy_to_canvas_xy(x_in,y_in):
@@ -43,9 +622,7 @@ layout = [ [sg.T('Ping times to Google.com', font='Any 18')],
[sg.Quit()]
]
-form = sg.FlexForm('Canvas test', grab_anywhere=True)
-form.Layout(layout)
-form.Finalize()
+form = sg.FlexForm('Ping Times To Google.com', grab_anywhere=True).Layout(layout).Finalize()
canvas = form.FindElement('canvas').TKCanvas
diff --git a/Demo_Pong.py b/Demo_Pong.py
index 0e883804..3aef52c7 100644
--- a/Demo_Pong.py
+++ b/Demo_Pong.py
@@ -128,9 +128,8 @@ def pong():
layout = [[sg.Canvas(size=(700, 400), background_color='black', key='canvas')],
[sg.T(''), sg.ReadFormButton('Quit')]]
# ------------- Create window -------------
- form = sg.FlexForm('Canvas test', return_keyboard_events=True)
- form.Layout(layout)
- form.Finalize() # TODO Replace with call to form.Finalize once code released
+ form = sg.FlexForm('The Classic Game of Pong', return_keyboard_events=True).Layout(layout).Finalize()
+ # form.Finalize() # TODO Replace with call to form.Finalize once code released
# ------------- Get the tkinter Canvas we're drawing on -------------
canvas = form.FindElement('canvas').TKCanvas
@@ -150,7 +149,6 @@ def pong():
# ------------- Read the form, get keypresses -------------
button, values = form.ReadNonBlocking()
-
# ------------- If quit -------------
if button is None and values is None or button == 'Quit':
exit(69)
@@ -167,6 +165,7 @@ def pong():
if ball1.checkwin():
sg.Popup('Game Over', ball1.checkwin() + ' won!!')
+ break
# ------------- Bottom of loop, delay between animations -------------
diff --git a/Demo_Super_Simple_Form.py b/Demo_Super_Simple_Form.py
index a1039249..80c229a4 100644
--- a/Demo_Super_Simple_Form.py
+++ b/Demo_Super_Simple_Form.py
@@ -1,16 +1,14 @@
import PySimpleGUI as sg
-# Very basic form. Return values as a dictionary
-form = sg.FlexForm('Simple data entry form') # begin with a blank form
-
+form = sg.FlexForm('Simple data entry form')
layout = [
- [sg.Text('Please enter your Name, Address, Phone')],
- [sg.Text('Name', size=(15, 1)), sg.InputText('name', key='name')],
- [sg.Text('Address', size=(15, 1)), sg.InputText('address', key='address')],
- [sg.Text('Phone', size=(15, 1)), sg.InputText('phone', key='phone')],
- [sg.Ok(), sg.Cancel()]
- ]
+ [sg.Text('Please enter your Name, Address, Phone')],
+ [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='name')],
+ [sg.Text('Address', size=(15, 1)), sg.InputText('2', key='address')],
+ [sg.Text('Phone', size=(15, 1)), sg.InputText('3', key='phone')],
+ [sg.Submit(), sg.Cancel()]
+]
button, values = form.LayoutAndRead(layout)
-sg.Popup(button, values, values['name'], values['address'], values['phone'])
+sg.Popup(button, values, values['name'], values['address'], values['phone'])
\ No newline at end of file
diff --git a/Demo_Tabbed_Form.py b/Demo_Tabbed_Form.py
index d63d1205..21b640e1 100644
--- a/Demo_Tabbed_Form.py
+++ b/Demo_Tabbed_Form.py
@@ -1,87 +1,83 @@
import PySimpleGUI as sg
-def eBaySuperSearcherGUI():
- # Drop Down list of options
- configs = ('0 - Gruen - Started 2 days ago in Watches',
- '1 - Gruen - Currently Active in Watches',
- '2 - Alpina - Currently Active in Jewelry',
- '3 - Gruen - Ends in 1 day in Watches',
- '4 - Gruen - Completed in Watches',
- '5 - Gruen - Advertising',
- '6 - Gruen - Currently Active in Jewelry',
- '7 - Gruen - Price Test',
- '8 - Gruen - No brand name specified')
+# Drop Down list of options
+configs = ('0 - Gruen - Started 2 days ago in Watches',
+ '1 - Gruen - Currently Active in Watches',
+ '2 - Alpina - Currently Active in Jewelry',
+ '3 - Gruen - Ends in 1 day in Watches',
+ '4 - Gruen - Completed in Watches',
+ '5 - Gruen - Advertising',
+ '6 - Gruen - Currently Active in Jewelry',
+ '7 - Gruen - Price Test',
+ '8 - Gruen - No brand name specified')
- us_categories = ('Use Default with no change',
- 'All - 1',
- 'Jewelry - 281',
- ' Watches - 14324',
- ' Wristwatches - 31387',
- ' Pocket Watches - 3937',
- 'Advertising - 34',
- ' Watch Ads - 165254'
- )
+us_categories = ('Use Default with no change',
+ 'All - 1',
+ 'Jewelry - 281',
+ ' Watches - 14324',
+ ' Wristwatches - 31387',
+ ' Pocket Watches - 3937',
+ 'Advertising - 34',
+ ' Watch Ads - 165254'
+ )
- german_categories =('Use Default with no change',
- 'All - 1',
- 'Jewelry - 281',
- ' Watches - 14324',
- ' Wristwatches - 31387',
- ' Pocket Watches - 3937',
- 'Advertising - 1',
- ' Watch Ads - 19823'
- )
+german_categories =('Use Default with no change',
+ 'All - 1',
+ 'Jewelry - 281',
+ ' Watches - 14324',
+ ' Wristwatches - 31387',
+ ' Pocket Watches - 3937',
+ 'Advertising - 1',
+ ' Watch Ads - 19823'
+ )
- # the form layout
- with sg.FlexForm('EBay Super Searcher', auto_size_text=True) as form:
- with sg.FlexForm('EBay Super Searcher', auto_size_text=False) as form2:
- layout_tab_1 = [[sg.Text('eBay Super Searcher!', size=(60,1), font=('helvetica', 15))],
- [sg.Text('Choose base configuration to run')],
- [sg.InputCombo(configs)],
- [sg.Text('_'*100, size=(80,1))],
- [sg.InputText(),sg.Text('Choose Destination Folder'), sg.FolderBrowse(target=(sg.ThisRow,0))],
- [sg.InputText(),sg.Text('Custom text to add to folder name')],
- [sg.Text('_'*100, size=(80,1))],
- [sg.Checkbox('US', default=True, size=(15, 1)), sg.Checkbox('German', size=(15, 1), default=True, )],
- [sg.Radio('Active Listings','ActiveComplete', default = True,size=(15, 1)), sg.Radio('Completed Listings', 'ActiveComplete', size=(15, 1))],
- [sg.Text('_'*100, size=(80,1))],
- [sg.Checkbox('Save Images', size=(15,1)),sg.Checkbox('Save PDFs', size=(15,1)), sg.Checkbox('Extract PDFs', size=(15,1))],
- [sg.Text('_'*100, size=(80,1))],
- [sg.Text('Time Filters')],
- [sg.Radio('No change','time', default=True),sg.Radio('ALL listings','time'),sg.Radio('Started 1 day ago','time', size=(15,1)),sg.Radio('Started 2 days ago','time', size=(15,1)), sg.Radio('Ends in 1 day','time', size=(15,1))],
- [sg.Text('_'*100, size=(80,1))],
- [sg.Text('Price Range'), sg.InputText(size=(10,1)),sg.Text('To'), sg.InputText(size=(10,1))],
- [sg.Text('_'*100, size=(80,1))],
- [sg.Submit(button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue'))]]
+# the form layout
+form = sg.FlexForm('EBay Super Searcher', auto_size_text=True)
+
+form2 = sg.FlexForm('EBay Super Searcher', auto_size_text=False)
+
+layout_tab_1 = [[sg.Text('eBay Super Searcher!', size=(60,1), font=('helvetica', 15))],
+ [sg.Text('Choose base configuration to run')],
+ [sg.InputCombo(configs)],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.InputText(),sg.Text('Choose Destination Folder'), sg.FolderBrowse(target=(sg.ThisRow,0))],
+ [sg.InputText(),sg.Text('Custom text to add to folder name')],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.Checkbox('US', default=True, size=(15, 1)), sg.Checkbox('German', size=(15, 1), default=True, )],
+ [sg.Radio('Active Listings','ActiveComplete', default = True,size=(15, 1)), sg.Radio('Completed Listings', 'ActiveComplete', size=(15, 1))],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.Checkbox('Save Images', size=(15,1)),sg.Checkbox('Save PDFs', size=(15,1)), sg.Checkbox('Extract PDFs', size=(15,1))],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.Text('Time Filters')],
+ [sg.Radio('No change','time', default=True),sg.Radio('ALL listings','time'),sg.Radio('Started 1 day ago','time', size=(15,1)),sg.Radio('Started 2 days ago','time', size=(15,1)), sg.Radio('Ends in 1 day','time', size=(15,1))],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.Text('Price Range'), sg.InputText(size=(10,1)),sg.Text('To'), sg.InputText(size=(10,1))],
+ [sg.Text('_'*100, size=(80,1))],
+ [sg.Submit(button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue'))]]
- # First category is default (need to special case this)
- layout_tab_2 = [[sg.Text('Choose Category')],
- [sg.Text('US Categories'),sg.Text('German Categories')],
- [sg.Radio(us_categories[0],'CATUS', default=True), sg.Radio(german_categories[0], 'CATDE', default=True)]]
+# First category is default (need to special case this)
+layout_tab_2 = [[sg.Text('Choose Category')],
+ [sg.Text('US Categories'),sg.Text('German Categories')],
+ [sg.Radio(us_categories[0],'CATUS', default=True), sg.Radio(german_categories[0], 'CATDE', default=True)]]
- for i,cat in enumerate(us_categories):
- if i == 0: continue # skip first one
- layout_tab_2.append([sg.Radio(cat,'CATUS'), sg.Radio(german_categories[i],'CATDE')])
+for i,cat in enumerate(us_categories):
+ if i == 0: continue # skip first one
+ layout_tab_2.append([sg.Radio(cat,'CATUS'), sg.Radio(german_categories[i],'CATDE')])
- layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
- layout_tab_2.append([sg.Text('US Search String Override')])
- layout_tab_2.append([sg.InputText(size=(100,1))])
- layout_tab_2.append([sg.Text('German Search String Override')])
- layout_tab_2.append([sg.InputText(size=(100,1))])
- layout_tab_2.append([sg.Text('Typical US Search String')])
- layout_tab_2.append([sg.InputText(size=(100,1), default_text='gruen -sara -quarz -quartz -embassy -bob -robert -elephants -adidas -LED ')])
- layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
- layout_tab_2.append([sg.ReadButton('Submit', button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue'))])
+layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
+layout_tab_2.append([sg.Text('US Search String Override')])
+layout_tab_2.append([sg.InputText(size=(100,1))])
+layout_tab_2.append([sg.Text('German Search String Override')])
+layout_tab_2.append([sg.InputText(size=(100,1))])
+layout_tab_2.append([sg.Text('Typical US Search String')])
+layout_tab_2.append([sg.InputText(size=(100,1), default_text='gruen -sara -quarz -quartz -embassy -bob -robert -elephants -adidas -LED ')])
+layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
+layout_tab_2.append([sg.ReadButton('Submit', button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue'))])
- results = sg.ShowTabbedForm('eBay Super Searcher', (form,layout_tab_1,'Where To Save'), (form2, layout_tab_2, 'Categories & Search String'))
-
- return results
+results = sg.ShowTabbedForm('eBay Super Searcher', (form,layout_tab_1,'Where To Save'), (form2, layout_tab_2, 'Categories & Search String'))
-if __name__ == '__main__':
- # sg.SetOptions(background_color='white')
- results = eBaySuperSearcherGUI()
- print(results)
- sg.Popup('Results', results)
\ No newline at end of file
+
+sg.Popup('Results', results)
\ No newline at end of file
diff --git a/PySimpleGUI.py b/PySimpleGUI.py
index d1f7b02c..4d9fab53 100644
--- a/PySimpleGUI.py
+++ b/PySimpleGUI.py
@@ -2001,9 +2001,23 @@ class FlexForm:
# return None, None
return BuildResults(self, False, self)
+
+ def Finalize(self):
+ if self.TKrootDestroyed:
+ return self
+ if not self.Shown:
+ self.Show(non_blocking=True)
+ try:
+ rc = self.TKroot.update()
+ except:
+ self.TKrootDestroyed = True
+ _my_windows.Decrement()
+ # return None, None
+ return self
+
# Another name for ReadNonBlocking.
PrepareForUpdate = ReadNonBlocking
- Finalize = ReadNonBlocking
+ # Finalize = ReadNonBlocking
PreRead = ReadNonBlocking
diff --git a/docs/index.md b/docs/index.md
index 578ced22..0a835cd5 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -7,7 +7,7 @@
# PySimpleGUI
-
+
[Wiki for the latest news](https://github.com/MikeTheWatchGuy/PySimpleGUI/wiki)
@@ -1846,8 +1846,8 @@ The order of operations to obtain a tkinter Canvas Widget is:
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
# create the form and show it without the plot
- form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout)
- form.Finalize()
+ form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
+
# add the plot to the window
fig_photo = draw_figure(form.FindElement('canvas').TKCanvas, fig)
@@ -2518,6 +2518,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 03.04.01 | Sept 18, 2018 - See release notes
| 03.05.00 | Sept 20, 2018 - See release notes
| 03.05.01 | Sept 22, 2018 - See release notes
+| 03.05.02 | Sept 23, 2018 - See release notes
### Release Notes
2.3 - Sliders, Listbox's and Image elements (oh my!)
@@ -2600,6 +2601,11 @@ OneLineProgressMeter function added which gives you not only a one-line solution
* Bug fix for broken PySimpleGUI if Python version < 3.6 (sorry!)
* LOTS of Readme changes
+#### 3.5.2
+* Made `Finalize()` in a way that it can be chained
+* Fixed bug in return values from Frame Element contents
+
+
### Upcoming
Make suggestions people! Future release features
diff --git a/readme.md b/readme.md
index 578ced22..0a835cd5 100644
--- a/readme.md
+++ b/readme.md
@@ -7,7 +7,7 @@
# PySimpleGUI
-
+
[Wiki for the latest news](https://github.com/MikeTheWatchGuy/PySimpleGUI/wiki)
@@ -1846,8 +1846,8 @@ The order of operations to obtain a tkinter Canvas Widget is:
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
# create the form and show it without the plot
- form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout)
- form.Finalize()
+ form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
+
# add the plot to the window
fig_photo = draw_figure(form.FindElement('canvas').TKCanvas, fig)
@@ -2518,6 +2518,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 03.04.01 | Sept 18, 2018 - See release notes
| 03.05.00 | Sept 20, 2018 - See release notes
| 03.05.01 | Sept 22, 2018 - See release notes
+| 03.05.02 | Sept 23, 2018 - See release notes
### Release Notes
2.3 - Sliders, Listbox's and Image elements (oh my!)
@@ -2600,6 +2601,11 @@ OneLineProgressMeter function added which gives you not only a one-line solution
* Bug fix for broken PySimpleGUI if Python version < 3.6 (sorry!)
* LOTS of Readme changes
+#### 3.5.2
+* Made `Finalize()` in a way that it can be chained
+* Fixed bug in return values from Frame Element contents
+
+
### Upcoming
Make suggestions people! Future release features