以前のエントリでも扱った気がするが、前回とは違う。
やりたいのは、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に興味がでてきた。。。