RELEASE 3.5.2
This commit is contained in:
parent
50261625a4
commit
7e00dd16fe
|
@ -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')],
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
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)
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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()]])
|
|
@ -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()
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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, <http://www.visi.com/~mdc/>.
|
||||
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 <emamirazavi@gmail.com>
|
||||
- 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
|
||||
|
||||
|
|
|
@ -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 -------------
|
||||
|
|
|
@ -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'])
|
|
@ -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)
|
||||
|
||||
sg.Popup('Results', results)
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# PySimpleGUI
|
||||
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUI_Version-3.5.1-red.svg?longCache=true&style=for-the-badge)
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUI_Version-3.5.2-red.svg?longCache=true&style=for-the-badge)
|
||||
|
||||
|
||||
[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
|
||||
|
||||
|
|
12
readme.md
12
readme.md
|
@ -7,7 +7,7 @@
|
|||
|
||||
# PySimpleGUI
|
||||
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUI_Version-3.5.1-red.svg?longCache=true&style=for-the-badge)
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUI_Version-3.5.2-red.svg?longCache=true&style=for-the-badge)
|
||||
|
||||
|
||||
[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
|
||||
|
||||
|
|
Loading…
Reference in New Issue