You need to synchronize your data to the world's interaction cycle.
A fairly simple way of doing this is the following:
plotMorph := PlotMorph new.
plotMorph extent: 400@400.
plotMorph openInWorld.
[
0 to: 1000 do: [ :index |
WorldState addDeferredUIMessage:[
plotMorph series: #a addPoint: index@(index cos)
].
(Delay forMilliseconds: 10) wait.
]
] fork.
The block passed to WorldState>>addDeferredUIMessage: will be evaluate
in sync with the rest of the system.
A more complex (but much better structured) way is to use a
SharedQueue for the interaction, e.g., you'd do something like:
PlotMorph subclass: #MyPlotMorph
instanceVariableNames: 'queue'
classVariableNames: ''
poolDictionaries: ''
category: 'My-Plot-Morph'
MyPlotMorph>>initialize
"Initialize the receiver"
super initialize.
queue := SharedQueue new.
MyPlotMorph>>queue
"answer the receiver's point queue"
^queue
MyPlotMorph>>wantsSteps
"Answer whether I want to see steps"
^true
MyPlotMorph>>stepTime
"Answer the refresh interval for the receiver. Here,
this means how often do we want to redraw any incoming points?"
^20 "50/sec"
MyPlotMorph>>step
"Read all the points so far"
| point |
[point := queue nextOrNil.
point isNil] whileFalse:[
self series: #a addPoint:point
].
And then you'd use it like this:
plotMorph := MyPlotMorph new.
plotMorph extent: 400@400.
plotMorph openInWorld.
queue := plotMorph queue.
[
0 to: 1000 do: [ :index |
queue nextPut: index@(index cos).
(Delay forMilliseconds: 10) wait.
]
] fork.
The latter way gives you much better control about how precisely you'd
want the system to behave (in terms of trading off speed for the
updating of the plot vs. speed of reading points) and allows for
pretty easy integration of other data sources (just add another
queue). Etc.