Snippets

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

Created by A.K.

File DrawArea.java Added

  • Ignore whitespace
  • Hide word diff
+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();
+        }
+    }
+    
+}

File Main.java Added

  • Ignore whitespace
  • Hide word diff
+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);
+    }
+    
+}
HTTPS SSH

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