Java sur l'écran virtuel joystick contrôle


J'ai besoin d'une solution de joystick virtuel à l'écran pour contrôler un périphérique externe-un chariot. Mon programme est écrit sur Java / Swing et il fonctionne sur une tablette durcie Windows avec écran tactile résistif. Il n'y a pas de contrôle de curseur xy dans Swing, n'a pas réussi à le trouver via Google, donc j'ai probablement besoin de l'écrire à partir de zéro. Maintenant, la question: quelle est la meilleure approche pour écrire un tel contrôle ? Je pensais placer deux contrôles JSlider, un horizontal et un second vertical, et faire un pouce personnalisé, mais je suis peur que cela puisse me causer des problèmes parce que c'est en fait un hack. Peut-être juste l'écrire à partir de zéro? Peut-être existe-t-il une solution existante? Je vais l'utiliser avec le pouce en faisant glisser et en touchant la position finale du pouce.

Author: tutejszy, 2013-05-08

3 answers

Par exemple

entrez la description de l'image icientrez la description de l'image ici

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);
    }
}
 5
Author: mKorbel, 2013-05-08 12:08:21

Ceci est du code retravaillé de @mKorbel, il est basé sur les événements et plus orienté swing, sans flottants:

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;

class JoyDemo extends JPanel implements ChangeListener {    
    private JLabel lblPosition;

    public JoyDemo() {
        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 {
    /** 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);
            }
        }
    }
}
 1
Author: tutejszy, 2013-05-08 18:31:41

Code retravaillé de @tutejszy. Avertissements supprimés et le PointChangeEvent manquant ajouté.

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;
    }
}
 1
Author: Dark.Rider, 2014-06-06 21:22:14