Skip to content

Instantly share code, notes, and snippets.

@aoetk
Created December 25, 2011 15:28
Show Gist options
  • Save aoetk/1519410 to your computer and use it in GitHub Desktop.
Save aoetk/1519410 to your computer and use it in GitHub Desktop.
Swing + JavaFXで作ったxeyesのソース
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);
}
}
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