Created
December 25, 2011 15:28
-
-
Save aoetk/1519410 to your computer and use it in GitHub Desktop.
Swing + JavaFXで作ったxeyesのソース
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package javafxeyes; | |
import javafx.scene.Parent; | |
import javafx.scene.paint.Color; | |
import javafx.scene.shape.Circle; | |
import javafx.scene.shape.Ellipse; | |
/** | |
* 目玉コンポーネント | |
* @author AOE Takashi | |
*/ | |
public class Eye extends Parent { | |
private static final double CENTER_X = 42.5; | |
private static final double CENTER_Y = 62.5; | |
private static final double ELLIPSE_RADIUS_X = 40d; | |
private static final double ELLIPSE_RADIUS_Y = 60d; | |
/** 目玉 */ | |
private Circle eye; | |
public Eye() { | |
super(); | |
createChildren(); | |
} | |
private void createChildren() { | |
final Ellipse ellipse = new Ellipse(CENTER_X, CENTER_Y, ELLIPSE_RADIUS_X, ELLIPSE_RADIUS_Y); | |
ellipse.setStrokeWidth(5.0); | |
ellipse.setStroke(Color.BLACK); | |
ellipse.setFill(Color.WHITE); | |
eye = new Circle(CENTER_X, CENTER_Y, 10d, Color.BLACK); | |
this.getChildren().addAll(ellipse, eye); | |
} | |
/** | |
* 自分の位置からの相対的なマウス位置を受け取り、自身のステータス (つまり目玉の位置) を更新する。 | |
* @param mouseX マウスのx座標 | |
* @param mouseY マウスのy座標 | |
*/ | |
public void updateMousePosition(double mouseX, double mouseY) { | |
// マウスの自コンポーネントの中心からの相対座標を算出 | |
double localMouseX = mouseX - CENTER_X; | |
double localMouseY = mouseY - CENTER_Y; | |
computeEyePosition(localMouseX, localMouseY); | |
} | |
/** | |
* 目玉の位置を算出する。 | |
* @param mouseX 自コンポーネントの中心からのマウスのx座標 | |
* @param mouseY 自コンポーネントの中心からのマウスのy座標 | |
*/ | |
private void computeEyePosition(double mouseX, double mouseY) { | |
double parameter = Math.atan2(mouseY, mouseX); | |
double eyeX = (ELLIPSE_RADIUS_X - 7.5) * Math.cos(parameter); | |
if (Math.abs(mouseX) < Math.abs(eyeX)) { | |
eyeX = mouseX; | |
} | |
double eyeY = (ELLIPSE_RADIUS_Y - 7.5) * Math.sin(parameter); | |
if (Math.abs(mouseY) < Math.abs(eyeY)) { | |
eyeY = mouseY; | |
} | |
eye.setCenterX(eyeX + CENTER_X); | |
eye.setCenterY(eyeY + CENTER_Y); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package javafxeyes; | |
import com.sun.awt.AWTUtilities; | |
import java.awt.HeadlessException; | |
import java.awt.MouseInfo; | |
import java.awt.Point; | |
import java.awt.event.*; | |
import javafx.application.Platform; | |
import javafx.embed.swing.JFXPanel; | |
import javafx.event.EventHandler; | |
import javafx.scene.Group; | |
import javafx.scene.Scene; | |
import javafx.scene.control.ContextMenu; | |
import javafx.scene.control.MenuItem; | |
import javafx.scene.input.MouseButton; | |
import javax.swing.JFrame; | |
import javax.swing.SwingUtilities; | |
import javax.swing.Timer; | |
import javax.swing.WindowConstants; | |
/** | |
* Swing + JavaFXで作ったXEyes | |
* @author AOE Takashi | |
*/ | |
public class SwingFXEyes extends JFrame { | |
private JFXPanel jfxPanel; | |
private Eye leftEye; | |
private Eye rightEye; | |
private ContextMenu menu; | |
private Timer timer; | |
private int diffMouseX; | |
private int diffMouseY; | |
public SwingFXEyes() throws HeadlessException { | |
initComponents(); | |
} | |
public static void main(String[] args) { | |
SwingUtilities.invokeLater(new Runnable() { | |
public void run() { | |
new SwingFXEyes().setVisible(true); | |
} | |
}); | |
} | |
/** | |
* Swingのコンポーネントを初期化する。 | |
* JFXPanelを作成し、JavaFXのアプリケーションスレッドでJavaFXのコンポーネントを初期化する。 | |
*/ | |
private void initComponents() { | |
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | |
jfxPanel = new JFXPanel(); | |
add(jfxPanel); | |
addWindowListener(new WindowAdapter() { | |
@Override | |
public void windowClosing(WindowEvent e) { | |
timer.stop(); | |
} | |
}); | |
jfxPanel.addMouseListener(new MouseAdapter() { | |
@Override | |
public void mousePressed(MouseEvent e) { | |
timer.stop(); | |
Point frameLocation = SwingFXEyes.this.getLocation(); | |
diffMouseX = e.getXOnScreen() - frameLocation.x; | |
diffMouseY = e.getYOnScreen() - frameLocation.y; | |
e.consume(); | |
} | |
@Override | |
public void mouseReleased(MouseEvent e) { | |
timer.start(); | |
} | |
}); | |
jfxPanel.addMouseMotionListener(new MouseMotionAdapter() { | |
@Override | |
public void mouseDragged(MouseEvent e) { | |
SwingFXEyes.this.setLocation(e.getXOnScreen() - diffMouseX, e.getYOnScreen() - diffMouseY); | |
e.consume(); | |
} | |
}); | |
this.setUndecorated(true); | |
AWTUtilities.setWindowOpaque(this, false); | |
Platform.runLater(new Runnable() { | |
public void run() { | |
initJFXComponents(); | |
} | |
}); | |
pack(); | |
} | |
/** | |
* JavaFXのコンポーネントを初期化する。 | |
* 完了後、Swingのタイマーをキックする。 | |
*/ | |
private void initJFXComponents() { | |
final Group root = new Group(); | |
final Scene scene = new Scene(root); | |
leftEye = new Eye(); | |
rightEye = new Eye(); | |
rightEye.setLayoutX(leftEye.prefWidth(-1) + 5); | |
menu = createContextMenu(); | |
root.getChildren().addAll(leftEye, rightEye); | |
root.setOnMouseClicked(new EventHandler<javafx.scene.input.MouseEvent>() { | |
public void handle(javafx.scene.input.MouseEvent event) { | |
if (event.getButton() == MouseButton.SECONDARY) { | |
menu.show(root, event.getScreenX(), event.getScreenY()); | |
} | |
} | |
}); | |
scene.setFill(null); | |
jfxPanel.setScene(scene); | |
jfxPanel.setOpaque(true); | |
SwingUtilities.invokeLater(new Runnable() { | |
public void run() { | |
startTimer(); | |
} | |
}); | |
} | |
/** | |
* マウス位置取得処理を行うタイマーを起動する。 | |
*/ | |
private void startTimer() { | |
timer = new Timer(50, new ActionListener() { | |
public void actionPerformed(ActionEvent ae) { | |
updateMousePosition(); | |
} | |
}); | |
timer.start(); | |
} | |
/** | |
* グローバルのマウス位置を取得し、目のマウス位置を更新する。 | |
*/ | |
private void updateMousePosition() { | |
final Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); | |
Platform.runLater(new Runnable() { | |
public void run() { | |
updateEye(mouseLocation.x, mouseLocation.y); | |
} | |
}); | |
} | |
/** | |
* 左右のEyeにコンポーネントからの相対的なマウス位置を渡す。 | |
* @param mouseX マウスのグローバルなx座標 | |
* @param mouseY マウスのグローバルなy座標 | |
*/ | |
private void updateEye(double mouseX, double mouseY) { | |
Point panelLocaiton = jfxPanel.getLocationOnScreen(); | |
leftEye.updateMousePosition(mouseX - panelLocaiton.x, mouseY - panelLocaiton.y); | |
rightEye.updateMousePosition(mouseX - panelLocaiton.x - leftEye.prefWidth(-1) - 5, mouseY - panelLocaiton.y); | |
} | |
/** | |
* アプリケーションを終了するためのコンテキストメニューの修正。 | |
* @return アプリケーションを終了するためのコンテキストメニュー | |
*/ | |
private ContextMenu createContextMenu() { | |
final MenuItem exitMenu = new MenuItem("Exit SwingFXEyes"); | |
exitMenu.setOnAction(new EventHandler<javafx.event.ActionEvent>() { | |
public void handle(javafx.event.ActionEvent event) { | |
terminateApp(); | |
} | |
}); | |
return new ContextMenu(exitMenu); | |
} | |
private void terminateApp() { | |
SwingUtilities.invokeLater(new Runnable() { | |
public void run() { | |
timer.stop(); | |
System.exit(0); | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment