''' ComputeImagesFromGUI.py This program combines Jython and Swing to control PixelMath from a separate window. There are a bunch of advanced features and tricky details here, such as defining object-oriented classes in Python, and setting up separate Swing "worker threads" to process images in the background, without stopping the user interface. However, this might be able to serve as a starting point for some project graphical user interfaces by intrepid programmers. S. Tanimoto, May 13, 2009 ''' from java.lang import Runnable from java.util import Random from java.util.concurrent import ExecutionException from javax.swing import JButton, JFrame, JLabel, JPanel from javax.swing import SwingWorker, SwingUtilities from java.awt import GridLayout as awtGridLayout # The following Python class is defined as a subclass of the # Java Swing JFrame class, which represents a window on the screen. class ControlPanel(JFrame): def __init__(self): JFrame.__init__(self, "A Control Window for PixelMath Operations", defaultCloseOperation=JFrame.HIDE_ON_CLOSE) # Set the layout scheme to "grid layout". self.contentPane.setLayout(awtGridLayout(1, 2)) # create a panel to hold four buttons. panel = JPanel(awtGridLayout(0, 1)) computeButton1 = JButton("Compute a ringing paraboloid") computeButton2 = JButton("Compute a pattern of colors") self.BeginRandomButton = JButton("Start a stream of random colors") self.EndRandomButton = JButton("Stop the stream of random colors") computeButton1.actionPerformed = lambda e: self.doCompute1() computeButton2.actionPerformed = lambda e: self.doCompute2() self.BeginRandomButton.actionPerformed = lambda e: self.startRandom() self.BeginRandomButton.enabled = True self.EndRandomButton.actionPerformed = lambda e: self.stopRandom() self.EndRandomButton.enabled = False panel.add(computeButton1) panel.add(computeButton2) panel.add(self.BeginRandomButton) panel.add(self.EndRandomButton) self.contentPane.add(panel) label = JLabel('This is the control panel', JLabel.CENTER) self.contentPane.add(label) self.formulaLabel = JLabel('formula normally is shown here') self.contentPane.add(self.formulaLabel) self.pack() self.setVisible(1) # Makes the window appear def doCompute(self, formula): self.formulaLabel.setText(formula) # create worker thread to create one PixelMath image. pi = ProcessImage(formula) pi.execute() # start up this thread def doCompute1(self): print "You pressed Button 1" self.doCompute("(sqr(x)+sqr(y))mod 256") def doCompute2(self): self.doCompute("RGB(x,y,0)") def startRandom(self): self.BeginRandomButton.enabled = False self.EndRandomButton.enabled = True # create worker thread to run an unlimited sequence of # PixelMath operations. self.randomColorProcess = ColorStream() self.randomColorProcess.execute() # start up this thread def stopRandom(self): # respond to the stop button by cancelling the worker process. self.BeginRandomButton.enabled = True self.EndRandomButton.enabled = False self.randomColorProcess.cancel(True) self.randomColorProcess = None class ProcessImage(SwingWorker): def __init__(self, formula): self.formula = formula print "Creating the ProcessImage instance" SwingWorker.__init__(self) def doInBackground(self): print "Beginning ProcessImage.doInBackground" pmNewComputedImage("Nice picture", 256, 256, self.formula) def done(self): try: self.get() #close frame if abnormal completion except ExecutionException, e: hide(0) print e.getCause() class ColorStream(SwingWorker): def __init__(self): print "Creating the ColorStream instance" SwingWorker.__init__(self) def doInBackground(self): print "Beginning ColorStream.doInBackground" wn = pmNewComputedImage("Nice picture", 256, 256, "RGB(255,0,0)") pmSetDestination(wn) random_gen = Random() while not self.isCancelled(): red = random_gen.nextInt() % 256 green = random_gen.nextInt() % 256 blue = random_gen.nextInt() % 256 pmSetFormula("RGB("+str(red)+","+str(green)+","+str(blue)+")") pmCompute() def done(self): try: self.get() #close frame if abnormal completion except ExecutionException, e: hide(0) print e.getCause() class Runnable(Runnable): def __init__(self, runMethod): self._runMethod = runMethod def run(self): self._runMethod() SwingUtilities.invokeLater(Runnable(ControlPanel))