SwingからProcessingを呼び出す

以前のエントリでも扱った気がするが、前回とは違う。
やりたいのは、Swingアプリのボタンをクリック→Processingアプリがアプレット上で発動(JFrameとAppletが共存?)
アプレットのみを動かしたいわけではなく、あくまでもSwingアプリケーション上でProcessingを動かしたい。
ビジュアライジングデータに載ってる普通の方法だと、PAppletを継承させるので結局アプレットで動いちゃう。
同じ質問してる人を発見。
http://oshiete.goo.ne.jp/qa/5889872.html
どうやらできるらしい。
http://wiki.processing.org/w/Swing_JSliders
まだ詳しくコード読んでないけど、これはかなり期待できそう。
#このmain関数の書き方が気になるんだよなあ

  public static void main(String[] args) {
    // threadsafe way to create a Swing GUI
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createGUI();
      }
    }
    );


KiteController.java

package test;

/*
swing sliders taken from http://wiki.processing.org/index.php?title=Swing_JSliders_with_Processing
@author Ira Greenberg
 
Put ''Kite.java'' and KiteController.java in their own 
files and follow instructions outlined above.
*/
 
/* ******************************
      KiteController class
****************************** */

//import com.iragreenberg.Kite;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.*;
 
public class KiteController extends JPanel {
 
  private int w = 600, h = 422;
  //private int w = 1000, h = 800; 変えてみようとしたけど駄目だった
	private Kite kite;
 
  // constructor
  public KiteController() {
    setBackground(new Color(180, 180, 220));
 
    /* create 2 pane across layout
     left pane holds processing PApplet
     right pane holds user widgets */
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
 
    // Instantiate Kite object
    kite = new Kite(400, 400);
 
    // right tools pane
    JPanel rtPanel = new JPanel();
    rtPanel.setOpaque(false);
    rtPanel.setLayout(new BoxLayout(rtPanel, BoxLayout.PAGE_AXIS));
 
    //無理矢理サイズを変えてやる(Added by me)
    rtPanel.setPreferredSize(new Dimension(400, 800));
    
    JLabel jl = new JLabel("   Drag the Kite String");
 
    // kite radius slider
    JSlider js0 = new JSlider(JSlider.HORIZONTAL, 10, 100, 40);
    js0.setBorder(BorderFactory.createTitledBorder("Kite Radius"));
    js0.setMajorTickSpacing(30);
    js0.setMinorTickSpacing(4);
    js0.setPaintTicks(true);
    js0.setPaintLabels(true);
 
    // handle js0 change events
    js0.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        JSlider slider = (JSlider)evt.getSource();
 
        if (!slider.getValueIsAdjusting()) {
          kite.setRadius(slider.getValue());
        }
      }
    }
    );
 
    // kite sides slider
    JSlider js1 = new JSlider(JSlider.HORIZONTAL, 3, 63, 4);
    js1.setBorder(BorderFactory.createTitledBorder("Kite Sides"));
    js1.setMajorTickSpacing(12);
    js1.setMinorTickSpacing(1);
    js1.setPaintTicks(true);
    js1.setPaintLabels(true);
 
    // handle js1 change events
    js1.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        JSlider slider = (JSlider)evt.getSource();
 
        if (!slider.getValueIsAdjusting()) {
          kite.setFeetCount(slider.getValue());
        }
      }
    }
    );
 
    // spring speed slider
    JSlider js2 = new JSlider(JSlider.HORIZONTAL, 1, 10, 5);
    js2.setBorder(BorderFactory.createTitledBorder("Spring Speed"));
    js2.setMajorTickSpacing(3);
    js2.setMinorTickSpacing(1);
    js2.setPaintTicks(true);
    js2.setPaintLabels(true);
 
    // handle js2 change events
    js2.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        JSlider slider = (JSlider)evt.getSource();
 
        if (!slider.getValueIsAdjusting()) {
          kite.setSpringSpeed(slider.getValue()/20.0f);
        }
      }
    }
    );
 
    // spring damping slider
    JSlider js3 = new JSlider(JSlider.HORIZONTAL, 1, 10, 4);
    js3.setBorder(BorderFactory.createTitledBorder("Spring Damping"));
    js3.setMajorTickSpacing(1);
    js3.setMinorTickSpacing(1);
    js3.setPaintTicks(true);
    js3.setPaintLabels(true);
 
    // handle js3 change events
    js3.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        JSlider slider = (JSlider)evt.getSource();
 
        if (!slider.getValueIsAdjusting()) {
          kite.setSpringDamping(1.0f - slider.getValue()/30.0f);
        }
      }
    }
    );
 
    // assemble tools pane
    rtPanel.add(jl);
    rtPanel.add(Box.createRigidArea(new Dimension(0,10)));
    rtPanel.add(js0);
    rtPanel.add(Box.createRigidArea(new Dimension(0,8)));
    rtPanel.add(js1);
    rtPanel.add(Box.createRigidArea(new Dimension(0,8)));
    rtPanel.add(js2);
    rtPanel.add(Box.createRigidArea(new Dimension(0,8)));
    rtPanel.add(js3);
 
 
    // Next comment taken directly from PApplet class: 
    /* "...ensures that the animation thread is started 
     and that other internal variables are properly set."*/
    kite.init(); 
    //無理矢理大きさを変更(Added by me)
    kite.setPreferredSize(new Dimension(400,800));
 
    // add panes to larger JPanel
    add(kite);
    // create some space between panes
    add(Box.createRigidArea(new Dimension(4,0)));
    add(rtPanel);
    // add a little margin on right of panel
    add(Box.createRigidArea(new Dimension(4,0)));
  }
 
  // create external JFrame
  private static void createGUI() {
    // create new JFrame
    JFrame jf = new JFrame("Kite Swing Application");
 
    // this allows program to exit
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
    // You add things to the contentPane in a JFrame
    jf.getContentPane().add(new KiteController());
 
    // keep window from being resized
    jf.setResizable(false);
 
    // size frame
    jf.pack();
 
    // make frame visible
    jf.setVisible(true);
  }
 
  public static void main(String[] args) {
    // threadsafe way to create a Swing GUI
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createGUI();
      }
    }
    );
  }
}

Kite.java

package test;

	/*******************************
    Kite class
*******************************/
/* By extending PApplet you can use your sweet old P5
calls in a regular Java App. Pretty nice indeed! */


import processing.core.*;
import java.awt.*;

public class Kite extends PApplet {
// instance properties
private Point2D dummy;
private Vect2D dummyVel;
private int feetCount = 4;
private Point2D[] feet = new Point2D[feetCount];
private Vect2D[] feetDelta = new Vect2D[feetCount];
private Vect2D[] feetVel = new Vect2D[feetCount];
private Vect2D[] feetAccel = new Vect2D[feetCount];
private float botRadius = 45.0f;
private float[] springSpeed = new float[feetCount];
private float springSpdMin = .05f, springSpdMax = .1f;
private float damping = .9f;
private Point2D lead;
private Vect2D leadVel;
private int w, h;
private int stringBaseX;
private int stringBaseY;
private float theta = 0;

// constructor
public Kite(int w, int h){
this.w = w;
this.h = h;

}

// Yes, this is the P5 setup()
public void setup(){
/* account for height of frame title bar,
when sizing applet. getBounds() returns a Java
Rectangle object that has 4 public properties:
(x, y, width and height) */
int titleBarHt = getBounds().y;
size(w, h-titleBarHt);
smooth();
frameRate(30);

dummy = new Point2D(width/2, height/4);
dummyVel = new Vect2D(3.65f, 2.0f);
lead = new Point2D(width/2, height/2);
leadVel = new Vect2D(.04f, .05f);

stringBaseX = width/2;
stringBaseY = height;

// set legs with some trig
for (int i=0; i<feet.length; i++){
 feet[i] = new Point2D(dummy.x + cos(theta)*botRadius, 
        dummy.y + sin(theta)*botRadius);
 feetDelta[i] = new Vect2D(feet[i].x-dummy.x, feet[i].y-dummy.y);
 feetVel[i] = new Vect2D(0, 0);
 feetAccel[i] = new Vect2D(0, 0);
 theta += TWO_PI/feet.length;
 springSpeed[i] = random(springSpdMin, springSpdMax);
}
}

// A huh, this is the P5 draw()
public void draw(){
background(255);
drawBot();
moveBot();
}

public void drawBot(){
rectMode(CENTER);
fill(0);
for (int i=0; i<feet.length; i++){
 line(dummy.x, dummy.y, feet[i].x, feet[i].y);
 if (i<feet.length-1){
   line(feet[i].x, feet[i].y, feet[i+1].x, feet[i+1].y);
 }
 else {
   line(feet[i].x, feet[i].y, feet[0].x, feet[0].y);
 }
}
line(stringBaseX, stringBaseY, dummy.x, dummy.y);

if (mousePressed){
 stringBaseX = mouseX;
 stringBaseY = mouseY;
}
fill(255);
}

public void moveBot(){
Vect2D[] feetMotionDelta = new Vect2D[feetCount];

for (int i=0; i<feet.length; i++){
 feetMotionDelta[i] = new Vect2D((dummy.x-feet[i].x+ 
        feetDelta[i].vx)*springSpeed[i],
 (dummy.y-feet[i].y+feetDelta[i].vy)*springSpeed[i]);

 feetAccel[i].vx+= feetMotionDelta[i].vx;
 feetAccel[i].vy+= feetMotionDelta[i].vy;

 feetVel[i].vx += feetAccel[i].vx;
 feetVel[i].vy += feetAccel[i].vy;

 feet[i].x = feetVel[i].vx ;
 feet[i].y = feetVel[i].vy ;

 feetAccel[i].vx *= damping;
 feetAccel[i].vy *= damping;

 float rotAng = atan2(mouseY-(height+100), mouseX-width/2);
 if (mousePressed){
   dummy.x = mouseX + cos(rotAng)*200;
   dummy.y = mouseY + sin(rotAng)*200;
 }
}
}

// dynamically change kite parameters
public void setFeetCount(int val){
// reinitialize arrays
feetCount = val;
feet = new Point2D[feetCount];
feetDelta = new Vect2D[feetCount];
feetVel = new Vect2D[feetCount];
feetAccel = new Vect2D[feetCount];
springSpeed = new float[feetCount];

// reset values
float theta = 0;
for (int i=0; i<feet.length; i++){
 feet[i] = new Point2D(dummy.x + cos(theta)*botRadius, 
        dummy.y + sin(theta)*botRadius);
 feetDelta[i] = new Vect2D(feet[i].x-dummy.x, feet[i].y-dummy.y);
 feetVel[i] = new Vect2D(0, 0);
 feetAccel[i] = new Vect2D(0, 0);
 theta += TWO_PI/feet.length;
 springSpeed[i] = random(springSpdMin, springSpdMax);
}
}

public void setRadius(int val){
botRadius = val;
for (int i=0; i<feet.length; i++){
 feet[i].x = dummy.x + cos(theta)*botRadius;
 feet[i].y = dummy.y + sin(theta)*botRadius;
 feetDelta[i].vx = feet[i].x-dummy.x;
 feetDelta[i].vy = feet[i].y-dummy.y;
 theta += TWO_PI/feet.length;
}
}

public void setSpringSpeed(float val){
for (int i=0; i<feet.length; i++){
 springSpeed[i] = random(springSpdMin, val);
}
}

public void setSpringDamping(float val){
damping = val;
}

/* two simple inner classes to make
things a little easier */
class Point2D{
float x, y;

Point2D(float x, float y){
 this.x = x;
 this.y = y;
}
}

class Vect2D{
float vx, vy;

Vect2D(float vx, float vy){
 this.vx = vx;
 this.vy = vy;
}
}
}

動作テスト

#Scalaに興味がでてきた。。。