Snippets

Andrei Kleshchanka Java 2D grid for xterro (https://www.linux.org.ru/forum/development/12786683)

Created by A.K.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

public class DrawArea extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener {

    private int aDPI = 300;

    /** По умолчанию панель будет размером с лист А4 */
    private Dimension aSize = new Dimension(794, 1122);

    /** Коэффициент зумирования */
    private double  scaleFactor           = 1.0;

    /** Размер сетки(во внутренник единицах измерения), если включена */
    private int     gridSize              = 40;
    /** Позиция курсора - позиция от которой рисуем(в логических, мировых координатах) */
    private Point2D crossHairPosition     = new Point2D.Double();
    /** Привязывать ли курсор к сетке */
    private boolean snapCursorToGrid      = true;
    /** Включаем выключаем сетку */
    private boolean isGridEnabled         = true;
    /** Крест по центру экрана, если надо */
    private boolean isCrossEnabled        = true;
    /** Сглаживание, если требуется */
    private boolean isAnlialiasingEnabled = false;

    /** Включен режим рисования(рисуется курсор для 
     * рисования на панели, иначе простой указатель) */
    private boolean isDrawMode            = true;

    /** Включен ли режим просмотра для панели.
     * В этом режиме запрещено редактировать или что-либо рисовать на панели,
     * события мыши и клавиатуры игнорируются, изображение на панели 
     * панорамируется(если необходимо) */
    private boolean isViewMode            = false;

    /** Координата, на которой нажали кнопку */
    private Point mousePressedPos;

    //GridSize s = new GridSize(15, SizeMeasureUnits.MIL);

    private AffineTransform at = new AffineTransform();

    public DrawArea() {

        setPreferredSize(aSize);

        System.out.println("Size w: " + aSize.width + " h: " + aSize.height);

        addMouseMotionListener(this);
        addMouseListener(this);
        addMouseWheelListener(this);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension((int)(aSize.width*scaleFactor),
                (int)(aSize.height*scaleFactor));
    }

    /** Переводит координаты окна в координаты панели(мировые координаты) */
    private Point TranslateW2WCoordinates(int winX, int winY) {
        Container parent = getParent();
        Point point = null;
        if(parent != null)
            point = SwingUtilities.convertPoint(parent, new Point(winX, winY), this);

        return point;
    }

    public void setCenterInViewport() {
        Container parent = getParent();
        if (parent instanceof JViewport) {

            JViewport port = (JViewport)parent;
            Rectangle viewRect = port.getViewRect();

            int width = getWidth();
            int height = getHeight();

            viewRect.x = (int) ((width - viewRect.width) / 2F - viewRect.x);
            viewRect.y = (int) ((height - viewRect.height) / 2F - viewRect.y);

            port.scrollRectToVisible(viewRect);
        }
    }

    /** Находит ближайший узел сетки для установки курсора.
     * curX, curY - координаты курсора в мировых координатах */
    private Point getNearestGridPosition(int curX, int curY) {

        int scaledGridSize = (int) Math.floor(gridSize * scaleFactor);

        float cellx = (float) Math.floor(curX / scaledGridSize);
        float celly = (float) Math.floor(curY / scaledGridSize);

        int x = (int)Math.floor(cellx * scaledGridSize);
        int y = (int)Math.floor(celly * scaledGridSize);

        System.out.println("Grid size: " + gridSize + " ScaleFactor: " + scaleFactor + " Scaled grid size: " + scaledGridSize);
        System.out.println("Cursor pos - x: " + curX + " y: " + curY);
        System.out.println("Cell num - x: " + cellx + " y: " + celly);
        System.out.println("CrossHairPos - x: " + x + " y: " + y);
        System.out.println("--------------------");

        return new Point(x, y);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        setBackground(Color.WHITE);

        if(isAnlialiasingEnabled) {
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                    RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        }
        
        /* Prepare draw area */
        if(isGridEnabled) {
            int w = getWidth();
            int h = getHeight();
            int gridStep = (int) Math.floor(gridSize * scaleFactor);

            g2d.setColor(new Color(235, 235, 235));
            for(int i = 0; i < w; i += gridStep)
                g2d.drawLine(i, 0, i, h);

            for(int j = 0; j < h; j += gridStep)
                g2d.drawLine(0, j , w, j);
        }

        if(isCrossEnabled) {
            g2d.setColor(Color.GRAY);
            float[] dash = {2f, 0f, 2f};
            Stroke oldStroke = g2d.getStroke();
            BasicStroke bs = new BasicStroke(1, BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_ROUND, 1.0f, dash, 2f);
            g2d.setStroke(bs);
            g2d.drawLine(getWidth()/2, 0, getWidth()/2, getHeight());
            g2d.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
            g2d.setStroke(oldStroke);
        }

        if (isDrawMode) {
            int cs = 12; // размер крестика-курсора в пикселях
            g2d.setColor(Color.GRAY);
            
            /* Координаты курсора в мировых координатах, приведем их к оконным */
            int cx = (int)crossHairPosition.getX();
            int cy = (int)crossHairPosition.getY();

            Point p = SwingUtilities.convertPoint(this, new Point(cx, cy), getParent());

            g2d.drawLine(p.x-cs/2, p.y, p.x+cs/2, p.y);
            g2d.drawLine(p.x, p.y-cs/2, p.x, p.y+cs/2);
        }
      
        /* Отрисовываем всё остальное(рисуем модель) */  
        /*
        g2d.setColor(Color.WHITE);
        g2d.fillRect(100, 100, 80, 160);
        g2d.setColor(Color.BLACK);
        g2d.drawRect(100, 100, 80, 160); */


        g2d.dispose();

    }

    public void setDPI(int dpi) {
        aDPI = dpi;
        repaint();
    }

    public int getDPI() {
        return aDPI;
    }

    public void setGridSize(int sizePx) {
        if(sizePx <= 0)
            sizePx = 1;

        gridSize = sizePx;
        repaint();
    }

    public void setGridEnabled(boolean enabled) {
        isGridEnabled = enabled;
        repaint();
    }

    public void setCrossEnabled(boolean enabled) {
        isCrossEnabled = enabled;
        repaint();
    }

    public void setAntialiasingEnabled(boolean enabled) {
        isAnlialiasingEnabled = enabled;
        repaint();
    }

    public void setViewModeEnabled(boolean enabled) {
        isViewMode = enabled;
        repaint();
    }

    /** Включает режим просмотра и панорамирует всё что нарисовано
     * (чтобы оно влезло в вид) */
    public void setViewModeEnabled(boolean enabled, boolean panning) {
        isViewMode = enabled;
        
        /* Если включено панорамирование, перерисуем всё что есть 
         * предварительно отмасштабировав под размеры viewport-а */

        //...

        repaint();
    }

    /****** MOUSE EVENTS  ******/

    @Override
    public void mouseClicked(MouseEvent me) {}

    @Override
    public void mousePressed(MouseEvent me) {
        mousePressedPos = new Point(me.getPoint());
        System.out.println("mousePressedPos " + mousePressedPos.x + "/" + mousePressedPos.y);
    }

    @Override
    public void mouseReleased(MouseEvent me) {

    }

    @Override
    public void mouseEntered(MouseEvent me) {}

    @Override
    public void mouseExited(MouseEvent me) {}

    @Override
    public void mouseDragged(MouseEvent me) {
        if(!isViewMode) {
            if(SwingUtilities.isMiddleMouseButton(me)) {
                if(mousePressedPos != null) {

                    JViewport port = (JViewport)getParent();
                    Rectangle viewRect = port.getViewRect();

                    int deltaX = mousePressedPos.x - me.getX();
                    int deltaY = mousePressedPos.y - me.getY();

                    viewRect.x += deltaX;
                    viewRect.y += deltaY;

                    scrollRectToVisible(viewRect);
                }
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent me) {
        if(!isViewMode) {
            int x = me.getX();
            int y = me.getY();

            // в мировые координаты
            Point p = SwingUtilities.convertPoint(getParent(), new Point(x, y), this);
            JViewport port = (JViewport)getParent();
            Point vp = port.getViewPosition();

            //System.out.println( "view.x: " + x + " view.y: " + y + 
            //                    " / area.x: " + p.x + " area.y: " + p.y + 
            //                    " / vpos.x: " + vp.x + " vpos.y: " + vp.y);

            if(snapCursorToGrid) {
                // Привязываем курсор к узлам сетки
                Point np = getNearestGridPosition(p.x, p.y);
                crossHairPosition.setLocation(np.x, np.y);
            }
            else {
                crossHairPosition.setLocation(p.x, p.y);
            }
            repaint();
        }
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent mwe) {
        if(!isViewMode) {
            /* минус для изменения направления движения колесика при маштабировании, так удобнее */
            scaleFactor += -(0.035 * mwe.getWheelRotation());
            scaleFactor = Math.max(0.05, scaleFactor);
            scaleFactor = Math.min(scaleFactor, 4);
            revalidate();
            repaint();
        }
    }
    
}
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Current IP");
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        DrawArea drawArea = new DrawArea();
        JViewport viewport = new JViewport();
        viewport.add(drawArea);
        frame.getContentPane().add(viewport);
        frame.pack();
        frame.setVisible(true);
    }
    
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.