How to play gif while using pyttsx3 - python

I have an appliaction which asks the user questions which they should answer.
The application uses pyttsx3 (version 2.9) to generate speech and I would like that while it speaks and only then, a gif animation would play for as long as it speaks.
How can this be accomplished?
For example:
import pyttsx3
engine = pyttsx3.init()
engine.say("I will speak this text")
engine.runAndWait()
And i want the gif animation to start running while runAndWait runs and stop when it stops

Ok I've found another program that works with the GIF images I have.
This program speaks for itself and displays a gif image.
I'm using tkinter Text object for output and a Label to hold the image.
It should allow GIF animes to run but it requires specific information about the GIF.
This runs on windows 10 and pyttsx3 - 2.5
"""
Program outputs text while voice is speaking.
This program works on Python 2.6.14 and Python 3.7.3
"""
import tkinter as tk
from tkinter import filedialog as fido
import random, pyttsx3
class chatter:
terminate = False
def showText( self, m ):
"""talk.showText( m )"""
self.main.insert( "insert", m )
self.master.update( )
self.main.edit_separator( )
def Start( self, name ) ->"":
"""talk.Start( name )"""
self.sentence = name.split( )
def Use( self, name, location, length ) ->"":
"""talk.Use( name, location, length )"""
name = self.sentence.pop( 0 )
self.showText( f"{name} " )
def End( self, name, completed ) ->"":
"""talk.End( name, completed )"""
if len( self.sentence ) > 0:
while len( self.sentence ) > 0:
name = self.sentence.pop( 0 )
self.showText( f"{name}\n" )
else:
self.showText( "\n" )
def Error( self, name, exception ) ->"":
"""talk.Error( name, exception )"""
self.terminate = True
self.engine.stop( )
self.showText( f"\n{name}\n{exception}\n" )
def say( self, m ):
"""talk.say( m )"""
self.engine.say( m, m )
self.engine.runAndWait( )
def intro( self ):
for m in [
"This program works on Python 2.6 and Python 3",
"I am PYTTSX version 2.5" ]:
talk.say( m )
self.master.after( 100, self.imageUpdate, 0 )
def displayInCanvas( self ):
"""talk.displayInCanvas( )"""
self.image = fido.askopenfilename( title = 'Pick Gif' )
w, h = self.image.width() + 14, self.image.height() + 46
self.item = self.canvas.create_image( 2,2, anchor = "nw" )
self.canvas.itemconfig( self.item, image = self.image )
self.master.geometry( f"{w}x{h}" )
self.labelframe[ "text" ] = self.image
def getImage( self ):
"""talk.getImage( )"""
self.item = tk.Label( anchor = "nw" )
self.item.grid( row=0, column=1, sticky="nsew" )
self.image = fido.askopenfilename( title = 'Pick Gif' )
# This requires specific knowledge about the GIF image
# n = number of animation frames
# self.frame = [ tk.PhotoImage( master = self.master, file=self.image, format = 'gif -index %i' %( i ) ) for i in range( n ) ]
self.frame = [ tk.PhotoImage(
master = self.master, file = self.image, format = "gif -index 0" ) ]
self.item.configure( image = self.frame[ 0 ] )
def imageUpdate( self, ind ):
"""imageUpdate( ind )"""
frame = self.frame[ ind ]
ind += 1
print( ind )
# Will play gif infinitely
if ind > 0:
ind = 0
self.item.configure( image = frame )
self.master.after( 100, self.imageUpdate, ind )
def closer( self, ev = None ):
self.master.destroy( )
def __init__( self ):
"""talk.init"""
self.engine = pyttsx3.init( )
self.startUtter = self.engine.connect(
"started-utterance", self.Start )
self.wordsUtter = self.engine.connect(
"started-word", self.Use )
self.endsUtter = self.engine.connect(
"finished-utterance", self.End )
self.erraUtter = self.engine.connect(
"error", self.Error )
self.persona = self.engine.getProperty( "voices" )[~0].id
self.engine.setProperty( "voice", self.persona )
for a,b in [ ("rate", 150 ), ( "volume", 0.25 ) ]:
self.engine.setProperty( a,b )
self.engine.runAndWait( )
self.master = tk.Tk()
self.main = tk.Text(
self.master, undo =1, wrap = "word",
block = 1, width = 80, height = 25 )
self.main.grid( row = 0, column = 0, sticky = "nsew" )
self.master.bind( "<Escape>", self.closer )
self.showText( __doc__ + "\n" )
self.main.update_idletasks( )
self.getImage( ) # load and display gif
self.main.focus_set()
self.master.after( 100, self.intro )
if __name__ == "__main__":
talk = chatter( )
tk.mainloop()

Related

How to create a brightness toggle on Python Tkinter

I am creating a brightness toggle on Python. I am using the Tkinter module to create a sider function. I have successfully created a slider to increase/decrease the volume. However, I want to translate this into one where I can increase/decrease the screen's brightness. Here is my volume code and output.
I am currently using macOS Monterey Version 12.2.1.
#The GUI player
import pygame
from pygame import mixer
from tkinter import *
# Makes a new window and stores it inside the root variable.
root = Tk()
mixer.init() # initialising the mixer
# Coding the background music
def play_music():
pygame.mixer.music.load("ArcadeMusic copy.mp3")
pygame.mixer.music.play(-1)
def set_vol(val):
volume = int(val) / 100
mixer.music.set_volume(volume)
root.geometry('300x70')
root.title("Volume")
text = Label(root, text = "Drag the slider to adjust volume")
text.pack()
scale = Scale(root,from_=0,to=100 , orient=HORIZONTAL, command=set_vol)
scale.pack()
play_music()
root.mainloop()
Are you trying to achieve something like this? Or do you want to control desktop brightness?
import tkinter
def find( obj ):
name = f"{type(obj).__name__}:n "
try:
return name + "n ".join( [ f"{x} = '{obj.cget(x)}'" for x in obj.keys() ] )
except:
return f"'{obj}' has no keys attribute"
class brightness:
def __init__( self ):
self.master = tkinter.Tk()
self.master.update_idletasks()
self.color = 15790320 # #f0f0f0 = SystemButtonFace
self.var = tkinter.IntVar( self.master, value = self.color )
self.flexx( self.master )
self.label = tkinter.LabelFrame(
self.master, labelanchor = 'n', text = self.master['background'] )
self.label.grid( row=0, column=0, columnspan=2, sticky='nsew' )
self.flexx( self.label, r=None )
self.flexx( self.label, r=None , c=1 )
self.scroll = tkinter.Scale(
self.label, orient = 'horizontal',
resolution = 65793, label = 'Brightness Control',
from_ = 0, to = 16777215, variable = self.var,
command = self.control )
self.scroll.grid( row = 1, column=0, columnspan=2, sticky='ew' )
self.master.geometry( '200x200' )
self.master.minsize( 334, 113 )
def flexx( self, o, r = 0, c = 0, rw = 1, cw = 1 ):
if r != None:
o.rowconfigure( r, weight = rw )
if c != None:
o.columnconfigure( c, weight = cw )
def convert( self ):
col = '#' + ( '000000' + hex( self.color )[2:])[~5:]
self.var.set( self.color )
self.label['text'] = col
self.master.tk_setPalette( col )
def control_up( self ):
self.color += 65793
if self.color > 16777215:
self.color = 15790320
col = self.convert( )
def control_down( self ):
self.color -= 65793
if self.color < 0: # 15790320:
self.color = 16777215
col = self.convert( )
def control( self, n ):
self.color = int( n )
col = self.convert( )
if __name__ == '__main__':
bright = brightness( )
tkinter.mainloop()

Tkinter name "delete" not defined

I am trying to create a simple drawing programme with a button that clears the canvas by deleting all shapes on it, however i am trying to use the delete() command that is built into tkinter but when i try and run it it says that delete is not defined.`What am I doing wrong?
from Tkinter import *
import Tkinter
root = Tk()
class PaintBox( Frame ):
def __init__( self ):
Frame.__init__( self )
self.pack( expand = YES, fill = BOTH )
self.master.title( "Color Draw v0.2.63.23 open closed beta (Still in Alpha) greenlight edition" )
self.master.geometry( "600x600" )
self.message = Label( self, text = "Drag the mouse SLOWLY to draw" )
self.message.pack( side = TOP )
self.myCanvas = Canvas( self )
self.myCanvas.pack( expand = YES, fill = BOTH )
self.bd = (2)
self.myCanvas.bind( "<B1-Motion>", self.paint )
def paint( self, event ):
x1, y1 = ( event.x - 4 ), ( event.y - 4 )
x2, y2 = ( event.x + 4 ), ( event.y + 4 )
self.myCanvas.create_rectangle( x1, y1, x2, y2, fill = "black", tags="box")
button = Button(root, text = "Clear", command = delete(box))
button.grid(row = 1, column = 0)
PaintBox().mainloop()
Here is the full traceback #mgilson:
ERROR: execution aborted
In [2]: %run C:/Users/en58522/Downloads/paintcolor.txt---------------------------------------------------------------------------
NameError Traceback (most recent call last)
C:\Program Files\Enthought\Canopy\App\appdata\canopy-1.4.1.1975.win-x86_64\lib\site-packages\IPython\utils\py3compat.pyc in execfile(fname, glob, loc)
195 else:
196 filename = fname
--> 197 exec compile(scripttext, filename, 'exec') in glob, loc
198 else:
199 def execfile(fname, *where):
C:\Users\en58522\Downloads\paintcolor.txt in <module>()
3 root = Tk()
4
----> 5 class PaintBox( Frame ):
6 def __init__( self ):
7 Frame.__init__( self )
C:\Users\en58522\Downloads\paintcolor.txt in PaintBox()
24 self.myCanvas.create_rectangle( x1, y1, x2, y2, fill = "black", tags="box")
25
---> 26 button = Button(root, text = "Clear", command = delete(box))
27 button.grid(row = 1, column = 0)
28
NameError: name 'delete' is not defined
Here is some working code to get you started:
from Tkinter import *
import Tkinter
root = Tk()
class PaintBox( Frame ):
def __init__( self, root ):
Frame.__init__( self, root )
self.pack( expand = YES, fill = BOTH )
self.master.title( "Color Draw v0.2.63.23 open closed beta (Still in Alpha) greenlight edition" )
self.master.geometry( "600x600" )
self.message = Label( self, text = "Drag the mouse SLOWLY to draw" )
self.message.pack( side = TOP )
self.myCanvas = Canvas( self )
self.myCanvas.pack( expand = YES, fill = BOTH )
self.bd = (2)
self.myCanvas.bind( "<B1-Motion>", self.paint )
button = Button(root, text = "Clear", command = self.delete)
button.pack()
def paint( self, event ):
x1, y1 = ( event.x - 4 ), ( event.y - 4 )
x2, y2 = ( event.x + 4 ), ( event.y + 4 )
self.myCanvas.create_rectangle( x1, y1, x2, y2, fill = "black", tags="box")
def delete(self):
items = self.myCanvas.find_all()
for item in items:
self.myCanvas.delete(item)
PaintBox(root).mainloop()
I've tried to stay true to your original code as much as possible.
A few things to notice...
I .pack the button because using .grid and .pack in the same widget doesn't work.
I defined a delete function that clears the grid of the box that you input. I defined it in the class's __init__.
The command = ... should be a function. Your original code attempted to make a function call in the command = ... bit. This is a common mistake and leads to the function being executed when you create the button and then never again. I used a bound method because bound methods get self passed implicitly.

tkinter and matplotlib: windows not showing until program closes under Linux

I've written a program that basically plots different data upon pressing different buttons. The program works as intended under Windows, but when I tried to port it to Linux (Red Hat v6) I'm getting a strange issue: the window that I want to plot does not appear until after I close the main program. This happens regardless of the figure (figure 1,2 etc.) I'm trying to plot to, or if I try to type plt.show() etc.
The program I've written is almost 1000 lines of code, but I created an abbreviated program that has the same problem. It works under Windows, but under Linux I have to close the root window for the matplotlib window to appear.
Working code:
import matplotlib.pyplot as plt
from tkinter import *
def click():
x=['0','1','2']
plt.plot(x,x)
plotGUI=Tk()
butt1=Button(plotGUI,text="Test", command=click).grid()
plotGUI.mainloop()
If the reduced code still does not show up a Tk-toplevel window, add a line of:
plotGUI.lift() # force WM to raise Tk() window
plotGUI.mainloop()
If the reduced code has problems with a matplotlib-wrapper, would be necessary to be more specific on what wrapping method you use to get matplitlib-output into a Tkinter Canvas et al.
If the code attempts to rely on default matplotlib tools alike plt.show() then the code will suffer from having two adjacent .mainloop()-s -- first the Tk()'s -- second one hidden in default matplotlib-s .show() -- and thus your code would become hardly controllable of the two adjacent UI-s.
co-integrated UI
For having non-adjacent UI-controllers and more benefits of the co-integrated UI,
try to re-use backends factories to plot directly on Tkinter.Canvas and other plausible widgets of your choice and control.
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
and proceed to a fully integrated GUI-MVC layers on both your code & matplotlib Model-state / inputs-Controller / Visual-output.
a bit of more code for co-integrated UI sample:
class SuperShapeFrame( Frame ): # The user interface:
def __init__( self, master = None ):
Frame.__init__( self, master )
self.grid()
self.m = 3
self.n1 = 2
self.n1_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.n2 = 18
self.n2_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.n3 = 18
self.n3_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.fig = Figure( ( 6, 6 ), dpi = 100 )
canvas = FigureCanvasTkAgg( self.fig, master = self )
canvas.get_tk_widget().grid( row = 0, column = 0, columnspan = 4 )
label = Label( self, text = 'M' )
label.grid( row = 1, column = 1 )
self.m_slider = Scale( self, from_ = 1, to = 20, \
orient = HORIZONTAL, command = lambda i : self.update_m() \
)
self.m_slider.grid( row = 1, column = 2 )
label = Label( self, text = 'N1' )
label.grid( row = 2, column = 1 )
self.n1_slider = Scale( self, from_ = 0, to = 200, \
orient = HORIZONTAL, command = lambda i : self.update_n1() \
)
self.n1_slider.grid( row = 2, column = 2 )
label = Label( self, text = 'N2' )
label.grid( row = 3, column = 1 )
self.n2_slider = Scale( self, from_ = 0, to = 200, \
orient = HORIZONTAL, command = lambda i : self.update_n2() \
)
self.n2_slider.grid( row = 3, column = 2 )
label = Label( self, text = 'N3' )
label.grid( row = 4, column = 1 )
self.n3_slider = Scale( self, from_ = 0, to = 200,
orient = HORIZONTAL, command = lambda i : self.update_n3() \
)
self.n3_slider.grid( row = 4, column = 2 )
self.draw_figure() # >>> ================================================================ DRAW FIRST APPEARANCE OF THE INSTANCE
def update_m( self ):
self.m = self.m_slider.get()
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n1( self ):
self.n1 = self.n1_scaling.dst_to_src( self.n1_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n2( self ):
self.n2 = self.n2_scaling.dst_to_src( self.n2_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n3(self):
self.n3 = self.n3_scaling.dst_to_src( self.n3_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def refresh_figure( self ): # <<< .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE ACTUAL APPEARANCE OF THE INSTANCE
r = supershape_radius( self.phi, 1, 1, self.m, self.n1, self.n2, self.n3 ) # .CALC new polar values in radius dimension
self.lines.set_ydata( r ) # .MOD <lines>, selectively just their <lines>.set_ydata() coordinates
self.fig.canvas.draw_idle() # .GUI MVC-Visual part UPDATE via <self>.<fig>.<canvas>.draw_idle()
def draw_figure( self ): # <<< =============================================================== DRAW FIRST APPEARANCE OF THE INSTANCE
self.phi = np.linspace( 0, 2 * np.pi, 1024 ) # .STO <phi> a np.array with static fi-coordinates
r = supershape_radius( self.phi, 1, 1, self.m, self.n1, self.n2, self.n3 )
ax = self.fig.add_subplot( 111, polar = True ) #
self.lines, = ax.plot( self.phi, r, lw = 3. ) # .STO <lines> aListOfLINEs from .plot() function
self.fig.canvas.draw() # .GUI MVC-Visual part, enforce first visual output via <self>.<fig>.<canvas>.draw()
def TkDemo(): # Finally, we set up and start our user interface:
""" HELP: CookBook: Tk-GUI-MVC via SuperShape example
TESTS: TkDemo()
"""
root = Tk()
root.lift()
root.protocol( 'WM_DELETE_WINDOW', root.quit() ) # [X]-overide ---------------------------
app = SuperShapeFrame( root ) # <<<--- pass <root>
app.master.title( 'CookBook: Tk-GUI-MVC via SuperShape' )
app.mainloop()
pass
Full-code for [Halldinz0r] copy/paste re-testing as-is:
####################################################################### #
###
### TkDemo()
###
### KCA_plot_inTk ##################################################### # Tk() GUI ###################################################################################################### _plot_inTk TkDemo() #################
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
def supershape_radius( phi, a, b, m, n1, n2, n3 ): # define the function for the SuperShape curve using the following code:
theta = .25 * m * phi
cos = np.fabs( np.cos( theta ) / a ) ** n2
sin = np.fabs( np.sin( theta ) / b ) ** n3
r = ( cos + sin ) ** ( -1. / n1 )
r /= np.max( r )
return r
class LinearScaling( object ): # define a utility object to linearly scale a range into another as follows:
def __init__( self, src_range, dst_range ):
self.src_start, src_diff = src_range[0], src_range[1] - src_range[0]
self.dst_start, dst_diff = dst_range[0], dst_range[1] - dst_range[0]
self.src_to_dst_coeff = dst_diff / src_diff
self.dst_to_src_coeff = src_diff / dst_diff
def src_to_dst( self, X ):
return ( X - self.src_start ) * self.src_to_dst_coeff + self.dst_start
def dst_to_src( self, X ):
return ( X - self.dst_start) * self.dst_to_src_coeff + self.src_start
class SuperShapeFrame( Frame ): # The user interface:
def __init__( self, master = None ):
Frame.__init__( self, master )
self.grid()
self.m = 3
self.n1 = 2
self.n1_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.n2 = 18
self.n2_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.n3 = 18
self.n3_scaling = LinearScaling( ( .1, 20 ), ( 0, 200 ) )
self.fig = Figure( ( 6, 6 ), dpi = 100 )
canvas = FigureCanvasTkAgg( self.fig, master = self )
canvas.get_tk_widget().grid( row = 0, column = 0, columnspan = 4 )
label = Label( self, text = 'M' )
label.grid( row = 1, column = 1 )
self.m_slider = Scale( self, from_ = 1, to = 20, \
orient = HORIZONTAL, command = lambda i : self.update_m() \
)
self.m_slider.grid( row = 1, column = 2 )
label = Label( self, text = 'N1' )
label.grid( row = 2, column = 1 )
self.n1_slider = Scale( self, from_ = 0, to = 200, \
orient = HORIZONTAL, command = lambda i : self.update_n1() \
)
self.n1_slider.grid( row = 2, column = 2 )
label = Label( self, text = 'N2' )
label.grid( row = 3, column = 1 )
self.n2_slider = Scale( self, from_ = 0, to = 200, \
orient = HORIZONTAL, command = lambda i : self.update_n2() \
)
self.n2_slider.grid( row = 3, column = 2 )
label = Label( self, text = 'N3' )
label.grid( row = 4, column = 1 )
self.n3_slider = Scale( self, from_ = 0, to = 200,
orient = HORIZONTAL, command = lambda i : self.update_n3() \
)
self.n3_slider.grid( row = 4, column = 2 )
self.draw_figure() # >>> ================================================================ DRAW FIRST APPEARANCE OF THE INSTANCE
def update_m( self ):
self.m = self.m_slider.get()
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n1( self ):
self.n1 = self.n1_scaling.dst_to_src( self.n1_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n2( self ):
self.n2 = self.n2_scaling.dst_to_src( self.n2_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def update_n3(self):
self.n3 = self.n3_scaling.dst_to_src( self.n3_slider.get() )
self.refresh_figure() # >>> .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE
def refresh_figure( self ): # <<< .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. UPDATE ACTUAL APPEARANCE OF THE INSTANCE
r = supershape_radius( self.phi, 1, 1, self.m, self.n1, self.n2, self.n3 ) # .CALC new polar values in radius dimension
self.lines.set_ydata( r ) # .MOD <lines>, selectively just their <lines>.set_ydata() coordinates
self.fig.canvas.draw_idle() # .GUI MVC-Visual part UPDATE via <self>.<fig>.<canvas>.draw_idle()
def draw_figure( self ): # <<< =============================================================== DRAW FIRST APPEARANCE OF THE INSTANCE
self.phi = np.linspace( 0, 2 * np.pi, 1024 ) # .STO <phi> a np.array with static fi-coordinates
r = supershape_radius( self.phi, 1, 1, self.m, self.n1, self.n2, self.n3 )
ax = self.fig.add_subplot( 111, polar = True ) #
self.lines, = ax.plot( self.phi, r, lw = 3. ) # .STO <lines> aListOfLINEs from .plot() function
self.fig.canvas.draw() # .GUI MVC-Visual part, enforce first visual output via <self>.<fig>.<canvas>.draw()
def TkDemo(): # Finally, set up and start our user interface:
""" HELP: CookBook: Tk-GUI-MVC via SuperShape example
TESTS: TkDemo()
"""
root = Tk()
root.lift()
root.protocol( 'WM_DELETE_WINDOW', root.quit() ) # [X]-overide ---------------------------
app = SuperShapeFrame( root ) # <<<--- pass <root>
app.master.title( 'CookBook: Tk-GUI-MVC via SuperShape' )
app.mainloop()
pass
### ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _plot_inTk TkDemo() ^^^^^^^^^^^^^^^^^^
I was able to make it work simply by adding:
matplotlib.use('TkAgg')
This made the program work just as in Windows, without any other modifications necessary. I really need to learn the concepts posted by user3666197 for future projects though.

graphing in wxpython using matplotlib

I'd like to create a live graph within a split-window in wxPython (using matplotlib?) --
So far I have the code that deals with logic: I'm creating a PID controller, and I'm looking to add a live graph (lets say 1 second delay between samples, with pseudo/random samples for now)
my code is here so far (below) - please advise
import wx
import matplotlib as mpl
mpl.use('WXAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
# global constants
Kp = 10
Ki = 2
Kd = 1
# functions used
def AttentionBox( self, message ):
dialog = wx.MessageDialog(self, message, 'Attention!', wx.ICON_ERROR)
dialog.ShowModal()
dialog.Destroy()
def StatusBar( self, message=None):
statusMessage = "PID constants( " + str(Kp)+","+str(Ki)+","+str(Kd)+" ): "
self.statusbar.SetStatusText( statusMessage + message )
class PIDFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title="PID Flow Controller", size=(1000,550))
# split the screen
self.sp = wx.SplitterWindow(self)
self.p1 = wx.Panel(self.sp, style = wx.SUNKEN_BORDER)
self.p2 = wx.Panel(self.sp, style = wx.SUNKEN_BORDER)
self.sp.SplitVertically(self.p1, self.p2, 860)
self.statusbar = self.CreateStatusBar()
StatusBar(self, "System Idle")
# define Temperature and Flow Control
wx.StaticBox(self.p2, -1, "System Control", pos=(5, 5), size=(100, 240))
wx.StaticText(self.p2, -1,"Target (litres/min):", pos=(15, 100))
self.Heater = wx.CheckBox(self.p2, -1 , "Heater", pos=(20,35))
self.Chiller = wx.CheckBox(self.p2, -1 , "Chiller", pos=(20,65))
self.TargetFlow = wx.SpinCtrl(self.p2, -1, "100", pos=(15,120), size=(80, 20), min=0, max=350)
self.ActivateButton = wx.Button(self.p2, -1, "Activate",pos=(20,180))
self.ActivateButton.Bind(wx.EVT_BUTTON, self.ActivateSystem)
self.StopButton = wx.Button(self.p2, -1, "Stop", pos=(20,215))
self.StopButton.Bind(wx.EVT_BUTTON, self.StopSystem)
############################################ BUTTONS ######################################################
def ActivateSystem(self, event):
if( self.Heater.GetValue() and self.Chiller.GetValue() ):
StatusBar(self,"Target Flow: " + str(self.TargetFlow.GetValue()) + " litres/min" )
self.Heater.SetValue(0)
self.Chiller.SetValue(0)
AttentionBox( self, "Heater and Chiller? Not Possible - Neither Activated" )
elif( self.Heater.GetValue() ):
StatusBar(self,"Heater Active. Target Flow: " + str(self.TargetFlow.GetValue()) + " litres/min" )
elif( self.Chiller.GetValue() ):
StatusBar(self,"Chiller Active. Target Flow: " + str(self.TargetFlow.GetValue()) + " litres/min" )
else:
StatusBar(self,"Target Flow: " + str(self.TargetFlow.GetValue()) + " litres/min" )
def StopSystem(self, event):
StatusBar(self, "System Idle" )
self.Heater.SetValue(0)
self.Chiller.SetValue(0)
self.TargetFlow.SetValue(0)
############################################ GRAPHING ######################################################
app = wx.App(redirect=False)
frame = PIDFrame(None, -1)
frame.Show()
app.MainLoop()

wxPython Geometry problem

I'm trying to get the button to be right of the label. I set the tuple and am still not sure why it covers the label.
Also is there a good tutorial available on wxpython geometry?
import wx
import wx.lib.agw.gradientbutton as GB
def GetRoundBitmap( w, h, r ):
maskColor = wx.Color(0,0,0)
shownColor = wx.Color(5,5,5)
b = wx.EmptyBitmap(w,h)
dc = wx.MemoryDC(b)
dc.SetBrush(wx.Brush(maskColor))
dc.DrawRectangle(0,0,w,h)
dc.SetBrush(wx.Brush(shownColor))
dc.SetPen(wx.Pen(shownColor))
dc.DrawRoundedRectangle(0,0,w,h,r)
dc.SelectObject(wx.NullBitmap)
b.SetMaskColour(maskColor)
return b
def GetRoundShape( w, h, r ):
return wx.RegionFromBitmap( GetRoundBitmap(w,h,r) )
class FancyFrame(wx.Frame):
def __init__(self):
style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR |
wx.NO_BORDER | wx.FRAME_SHAPED )
wx.Frame.__init__(self, None, title='Fancy', style = style)
self.SetSize( (250, 40) )
self.SetPosition( (500,500) )
self.SetTransparent( 160 )
self.Bind(wx.EVT_KEY_UP, self.On_Esc)
self.Bind(wx.EVT_MOTION, self.OnMouse)
self.Bind(wx.EVT_PAINT, self.OnPaint)
if wx.Platform == '__WXGTK__':
self.Bind(wx.EVT_WINDOW_CREATE, self.SetRoundShape)
else:
self.SetRoundShape()
self.Show(True)
geo = wx.GridBagSizer()
self.label = wx.StaticText(self,-1,label=u'Hello !')
self.label.SetBackgroundColour("#000000")
self.label.SetForegroundColour(wx.WHITE)
self.label.SetSize( (50, 10) )
geo.Add(self.label, (0,0))
self.button = GB.GradientButton(self,label="button")
self.label.SetBackgroundColour("#9e9e9e")
geo.Add(self.button, (0,1))
def SetRoundShape(self, event=None):
w, h = self.GetSizeTuple()
self.SetShape(GetRoundShape( w,h, 10 ) )
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc = wx.GCDC(dc)
w, h = self.GetSizeTuple()
r = 10
dc.SetPen( wx.Pen("#000000", width = 4 ) )
dc.SetBrush( wx.Brush("#9e9e9e") )
dc.DrawRoundedRectangle( 0,0,w,h,r )
def On_Esc(self, event):
"""quit if user press Esc"""
if event.GetKeyCode() == 27 : #27 is Esc
self.Close(force=True)
else:
event.Skip()
def OnMouse(self, event):
"""implement dragging"""
if not event.Dragging():
self._dragPos = None
return
self.CaptureMouse()
if not self._dragPos:
self._dragPos = event.GetPosition()
else:
pos = event.GetPosition()
displacement = self._dragPos - pos
self.SetPosition( self.GetPosition() - displacement )
app = wx.App()
f = FancyFrame()
app.MainLoop()
You forgot to set FancyFrame to have the given layout sizer.
In other words you need to add one line to the end of your FancyFrame's __init__ method.
self.SetSizerAndFit(geo)

Categories

Resources