Java - Как отцентрировать рендер после операции масштабирования с хорошей позицией мыши - PullRequest
0 голосов
/ 16 февраля 2020

В приведенном ниже коде, когда я перемещаю колесо мыши, квадрат увеличивается или уменьшается, и я всегда определяю положение квадрата повсюду на экране, если моя мышь go внутри него, даже если карта прокручивается , Это действительно здорово:)

Если я изменю логическое значение «centerScreen» на true, я смогу увеличить масштаб, и квадрат всегда будет в центре экрана. Это действительно очень здорово ...

... но обнаружение мыши не очень хорошо: (

Как я могу изменить мой код для увеличения или уменьшения масштаба, когда Render все еще находится в центре экран, но с идеальным распознаванием мыши с квадратом?

Спасибо за вашу помощь!

Вот мой полный «чистый код» - работа с копировальной пастой (в 3 классе) -

Основной класс

package main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class ZoomDemo extends JPanel
{
    private static final long   serialVersionUID    = 1L;

    private Rectangle2D         square;
    private Mouse               mouse;
    private ScrollMap           scrollMap;

    private static int          screenWidth;
    private static int          screenHeight;
    private static int          centerScreenWidth;
    private static int          centerScreenHeight;
    private static boolean      centerScreen;

    private List<Point>         listStar            = new ArrayList<Point>();

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 800);
        frame.setLocationRelativeTo(null);

        screenWidth = frame.getWidth();
        screenHeight = frame.getHeight();
        centerScreenWidth = screenWidth / 2;
        centerScreenHeight = screenHeight / 2;

        centerScreen = false;

        ZoomDemo zoomDemo = new ZoomDemo();
        frame.add(zoomDemo);

        frame.setVisible(true);
    }

    public ZoomDemo()
    {
        mouse = new Mouse();
        addMouseListener(mouse);
        addMouseMotionListener(mouse);
        addMouseWheelListener(mouse);

        scrollMap = new ScrollMap(mouse, screenWidth, screenHeight);

        int centerX = (int) getCenter(0, screenWidth, 50, true);
        int centerY = (int) getCenter(0, screenHeight, 50, true);
        square = new Rectangle2D.Double(centerX, centerY, 50, 50);

        Random rand = new Random();
        for (int i = 0; i < 50; i++)
        {
            int x = rand.nextInt(screenWidth);
            int y = rand.nextInt(screenHeight);

            listStar.add(new Point(x, y));
        }
    }

    @Override
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g.create();

        /* Optimization */
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);

        /* Background */
        g2d.setColor(Color.GRAY);
        g2d.fillRect(0, 0, this.getWidth(), this.getHeight());

        /* Translatation center -- it is working, but mouse detection is not good */
        if (centerScreen)
            g2d.translate(centerScreenWidth, centerScreenHeight);

        /* Listener Wheel Mouse for zooming and translation */
        mouse.zoom(g2d);

        /* Restore Translatation center */
        if (centerScreen)
            g2d.translate(-centerScreenWidth, -centerScreenHeight);

        render(g2d);

        g2d.dispose();

        //@formatter:off
        try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
        //@formatter:on

        repaint();
    }

    public void render(Graphics2D g2d)
    {
        /* Ask for scroll */
        isScrolling(g2d);

        /* Mouse Detection */
        int xMouse = (int) (mouse.pMousePosition.x - scrollMap.getMapX());
        int yMouse = (int) (mouse.pMousePosition.y - scrollMap.getMapY());
        boolean detection = square.contains(xMouse, yMouse);

        /* Graphic render */
        g2d.setColor(Color.WHITE);
        for (int i = 0; i < listStar.size(); i++)
            g2d.fillRect(listStar.get(i).x, listStar.get(i).y, 4, 4);

        g2d.setColor(detection ? Color.red : Color.black);
        g2d.fill(square);

        /* End of Scroll */
        endScrolling(g2d);
    }

    private void isScrolling(Graphics2D g2d)
    {
        /* If Mouse on edge, so change value for scrolling */
        scrollMap.scrolling();

        /* Translation scrolling */
        g2d.translate(scrollMap.getMapX(), scrollMap.getMapY());
    }

    private void endScrolling(Graphics2D g2d)
    {
        g2d.translate(-scrollMap.getMapX(), -scrollMap.getMapY());
    }


    public float getCenter(float startXZone, float longueurZone, float longueurElem, boolean round)
    {
        float s = startXZone + (longueurZone - longueurElem) / 2f;
        return (round) ? Math.round(s) : s;
    }
}



Класс мыши

package main;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;

public class Mouse implements MouseMotionListener, MouseWheelListener, MouseListener
{
    public Point            pMousePosition  = new Point();
    public double           scaleCoef;
    public double           inverseScaleCoef;
    public boolean          clic;

    private AffineTransform affineScale;
    private AffineTransform inverseScale;

    public Mouse()
    {
        scaleCoef = 1;
        inverseScaleCoef = 1;

        transform();
    }

    private void transform()
    {
        affineScale = AffineTransform.getScaleInstance(scaleCoef, scaleCoef);

        //@formatter:off
        try { inverseScale = affineScale.createInverse(); } catch (NoninvertibleTransformException e) { }
        //@formatter:on
    }

    public void zoom(Graphics2D g2)
    {
        transform();
        g2.transform(affineScale);
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e)
    {
        if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
        {
            scaleCoef -= (0.1 * e.getWheelRotation());
            scaleCoef = Math.max(0.1, scaleCoef);

            inverseScaleCoef = 1d / scaleCoef;
        }
    }

    @Override
    public void mouseMoved(MouseEvent e)
    {
        pMousePosition = e.getPoint();
        inverseScale.transform(pMousePosition, pMousePosition);
    }

    @Override
    public void mousePressed(MouseEvent e)
    {
        clic = true;
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        clic = false;
    }

    @Override
    public void mouseClicked(MouseEvent e)
    {

    }

    @Override
    public void mouseEntered(MouseEvent e)
    {

    }

    @Override
    public void mouseExited(MouseEvent e)
    {

    }

    @Override
    public void mouseDragged(MouseEvent e)
    {

    }

}


(Необязательно) Класс прокрутки

package main;

public class ScrollMap
{
    private float   mapX            = 0;
    private float   mapY            = 0;
    private int     speedScroll     = 1;
    private int     edgeDetection   = 70;
    private int     screenWidth;
    private int     screenHeight;

    private Mouse   mouse;

    public ScrollMap(Mouse mouse, int screenWidth, int screenHeight)
    {
        this.mouse = mouse;
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
    }

    /**
     * Scrolling ecran
     */
    public void scrolling()
    {
        double scale = mouse.inverseScaleCoef;

        /* Mouse to Right */
        if ((mouse.pMousePosition.x > screenWidth * scale - edgeDetection))
        {
            for (int k = 0; k < speedScroll; k++)
                moveMapToRight();
        }

        /* Mouse to Left */
        else if ((mouse.pMousePosition.x < edgeDetection * scale))
        {
            for (int k = 0; k < speedScroll; k++)
                moveMapToLeft();
        }

        /* Mouse to Down */
        if ((mouse.pMousePosition.y < edgeDetection * scale))
        {
            for (int k = 0; k < speedScroll; k++)
                moveMaptoDown();
        }

        /* Mouse to Up */
        else if ((mouse.pMousePosition.y > screenHeight * scale - edgeDetection))
        {
            for (int k = 0; k < speedScroll; k++)
                moveMapToUp();
        }
    }

    public float moveMapToRight()
    {
        return mapX--;
    }

    public float moveMapToLeft()
    {
        return mapX++;
    }

    public float moveMapToUp()
    {
        return mapY--;
    }

    public float moveMaptoDown()
    {
        return mapY++;
    }

    public float getMapY()
    {
        return mapY;
    }

    public float getMapX()
    {
        return mapX;
    }
}


...