外部デバイス (カート) を制御するための画面上の仮想ジョイスティック ソリューションが必要です。私のプログラムは Java/Swing で書かれており、抵抗膜式タッチ スクリーンを備えた Windows の頑丈なタブレットで動作します。Swing には xy スライダー コントロールがなく、Google で見つけられなかったので、おそらくゼロから作成する必要があります。ここで質問:そのようなコントロールを作成するための最善の方法は何ですか? 水平と垂直の 2 つの JSlider コントロールを配置し、カスタム サムを作成することを考えていましたが、これは実際にはハックであるため、問題が発生する可能性があります。ひょっとして最初から書くだけ?たぶん、既存のソリューションがありますか?親指をドラッグして最終的な親指の位置に触れて使用します。
2850 次
4 に答える
5
例えば
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SimpleJoystickDemo extends JFrame {
//I think that orginally made by @HFOE
private int displayWidth = 340;
private int displayHeight = 550;
private final Point position;
public SimpleJoystickDemo() {
super("SimpleJoystickDemo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(displayWidth, displayHeight);
setLocationRelativeTo(null);
position = new Point();
SimpleJoystick myJoystick = new SimpleJoystick(150, position, 100);
add(myJoystick, BorderLayout.PAGE_END);
Drawing drawing = new Drawing(position);
add(drawing);
}
public static void main(final String[] args) {
Runnable gui = new Runnable() {
@Override
public void run() {
new SimpleJoystickDemo().setVisible(true);
}
};
SwingUtilities.invokeLater(gui);
}
private class Drawing extends JPanel {
private static final long serialVersionUID = 1L;
private final Point position;
public Drawing(Point position) {
this.position = position;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillOval(160 + position.x, 160 - position.y, 15, 15);
}
}
}
class SimpleJoystick extends JPanel {
private static final long serialVersionUID = 1L;
//Maximum value for full horiz or vert position where centered is 0:
private int joyOutputRange;
private float joySize; //joystick icon size
private float joyWidth, joyHeight;
private float joyCenterX, joyCenterY; //Joystick displayed Center
//Display positions for text feedback values:
private int textHorizPos, textVertPos;
private int fontSpace = 12;
private float curJoyAngle; //Current joystick angle
private float curJoySize; //Current joystick size
private boolean isMouseTracking;
private boolean leftMouseButton;
private int mouseX, mouseY;
private Stroke lineStroke = new BasicStroke(10, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND);
private final Point position;
public SimpleJoystick(final int joyOutputRange,
final Point position, final int joySize) {
this.joyOutputRange = joyOutputRange;
this.position = position;
this.joySize = joySize;
joyWidth = joySize;
joyHeight = joyWidth;
setPreferredSize(new Dimension((int) joyWidth + 250,
(int) joyHeight + 80));
joyCenterX = getPreferredSize().width / 2;
joyCenterY = getPreferredSize().height / 2;
this.joySize = joyWidth / 2;
setBackground(new Color(226, 226, 226));
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mouseMoved(final MouseEvent e) {
mouseCheck(e);
}
@Override
public void mousePressed(final MouseEvent e) {
leftMouseButton = SwingUtilities.isLeftMouseButton(e);
mouseCheck(e);
}
};
addMouseMotionListener(mouseAdapter);
addMouseListener(mouseAdapter);
}
private void mouseCheck(final MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
float dx = mouseX - joyCenterX;
float dy = mouseY - joyCenterY;
if (leftMouseButton) {
isMouseTracking = true;
} else {
isMouseTracking = false;
}
if (isMouseTracking) {
curJoyAngle = (float) Math.atan2(dy, dx);
curJoySize = (float) Point.distance(mouseX, mouseY,
joyCenterX, joyCenterY);
} else {
curJoySize = 0;
}
if (curJoySize > joySize) {
curJoySize = joySize;
}
position.x = (int) (joyOutputRange * (Math.cos(curJoyAngle)
* curJoySize) / joySize);
position.y = (int) (joyOutputRange * (-(Math.sin(curJoyAngle)
* curJoySize) / joySize));
SwingUtilities.getRoot(SimpleJoystick.this).repaint();
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.LIGHT_GRAY);
g2.fillOval((int) (joyCenterX - joyWidth / 2),
(int) (joyCenterY - joyHeight / 2),
(int) joyWidth, (int) joyHeight);
//rotate and draw joystick line segment:
Graphics2D g3 = (Graphics2D) g2.create();
g3.translate(joyCenterX, joyCenterY);
g3.rotate(curJoyAngle);
g3.setColor(Color.GRAY);
g3.setStroke(lineStroke);
g3.drawLine(0, 0, (int) curJoySize, 0);
g3.dispose();
//
g2.setColor(Color.GRAY);
g2.fillOval((int) joyCenterX - 10, (int) joyCenterY - 10, 20, 20);
textHorizPos = 50;
textVertPos = (int) (joyCenterY - 50);
g2.drawString("Horizont:", textHorizPos, textVertPos);
textHorizPos += (4 * fontSpace);
g2.drawString(String.valueOf(position.x), textHorizPos, textVertPos);
textHorizPos = 50;
textVertPos += 12;
g2.drawString("Vertical :", textHorizPos, textVertPos);
textHorizPos += (4 * fontSpace);
g2.drawString(String.valueOf(position.y), textHorizPos, textVertPos);
}
}
于 2013-05-08T12:08:21.270 に答える
2
@tutejszy のコードを作り直しました。警告が削除され、欠落していた PointChangeEvent が追加されました。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class VJoystick extends JPanel implements ChangeListener
{
private JLabel lblPosition;
private static final long serialVersionUID = 1L;
public VJoystick()
{
setLayout(new BorderLayout(0, 0));
SimpleJoystick myJoystick = new SimpleJoystick(150);
myJoystick.setPreferredSize(new Dimension(100,100));
myJoystick.addChangeListener(this);
add(myJoystick, BorderLayout.CENTER);
lblPosition = new JLabel("position");
add(lblPosition, BorderLayout.SOUTH);
}
@Override
public void stateChanged(ChangeEvent ev) {
Point p = null;
try {
p = ((PointChangeEvent)ev).p;
} catch (Exception e) {
return;
}
lblPosition.setText("x="+p.x+" y="+p.y);
}
}
class SimpleJoystick extends JPanel
{
private static final long serialVersionUID = 1L;
/** Maximum value for full horiz or vert position where centered is 0 */
private int joyOutputRange;
/** max x and y value, in pixels */
private int joyRadius;
/** Joystick displayed Center, in pixels */
private int joyCenterX, joyCenterY;
/** joystick output position scaled to given joyOutputRange */
private Point position = new Point();
/** joystick x axis value in pixels */
private int dx = 0;
/** joystick y axis value in pixels */
private int dy = 0;
/**
* @param joyOutputRange
*/
public SimpleJoystick(final int joyOutputRange) {
this.joyOutputRange = joyOutputRange;
setBackground(new Color(226, 226, 226));
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && cursorChanged(e.getX(), e.getY())) {
SwingUtilities.getRoot(SimpleJoystick.this).repaint();
fireStateChanged();
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && cursorChanged(e.getX(), e.getY())) {
SwingUtilities.getRoot(SimpleJoystick.this).repaint();
fireStateChanged();
}
}
};
addMouseMotionListener(mouseAdapter);
addMouseListener(mouseAdapter);
}
private boolean cursorChanged(int mouseX, int mouseY) {
if (joyRadius == 0) return false;
dx = mouseX - joyCenterX;
dy = mouseY - joyCenterY;
if (dx > joyRadius) dx = joyRadius;
if (dy > joyRadius) dy = joyRadius;
if (dx < -joyRadius) dx = -joyRadius;
if (dy < -joyRadius) dy = -joyRadius;
position.x = joyOutputRange * dx / joyRadius;
position.y = -joyOutputRange * dy / joyRadius;
return true;
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
int joyWidth = getSize().width;
int joyHeight = getSize().height;
joyRadius = Math.min(joyWidth, joyHeight) / 2;
if (joyRadius == 0) return;
joyCenterX = joyWidth / 2;
joyCenterY = joyHeight / 2;
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int diameter;
//background
g2.setColor(Color.LIGHT_GRAY);
diameter = joyRadius*2;
g2.fillOval(joyCenterX - diameter/2 , joyCenterY - diameter/2, diameter, diameter);
g2.setColor(Color.RED);
diameter = 40;
g2.fillOval(joyCenterX + dx - diameter/2 , joyCenterY + dy - diameter/2, diameter, diameter);
//thumb
g2.setColor(Color.GRAY);
diameter = 20;
g2.fillOval(joyCenterX - diameter/2 , joyCenterY - diameter/2, diameter, diameter);
}
void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireStateChanged() {
ChangeEvent e = new PointChangeEvent(this, position);
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChangeListener.class) {
((ChangeListener) listeners[i + 1]).stateChanged(e);
}
}
}
}
class PointChangeEvent extends ChangeEvent
{
private static final long serialVersionUID = 1L;
public Point p;
public PointChangeEvent(Object source, Point p)
{
super(source);
this.p=p;
}
}
于 2014-06-06T21:22:14.953 に答える