如何根据矩形的可见性向可缩放面板动态添加和删除滚动条

问题描述 投票:0回答:1

我正在尝试在一个有限的、更大的红色矩形内操纵一些蓝色矩形。
我将其与放大和缩小功能一起使用

问题是我想在红色矩形不完全可见时显示滚动条 并在整个红色矩形可见时动态删除滚动条。

我怎样才能实现这个目标?这就是我到目前为止所得到的...

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

public class Demo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Zoomable Canvas");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);

        ZoomPanel zoomPanel = new ZoomPanel();
        frame.add(zoomPanel);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }
}

class ZoomPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private double zoomFactor = 1.0;
    private static final double ZOOM_MULTIPLIER = 1.1;
    private static final double MIN_ZOOM = 0.1; // Minimum zoom level
    private static final double MAX_ZOOM = 4.0; // Maximum zoom level

    private Point zoomCenter;
    private AffineTransform currentTransform;
    private Point lastMousePosition;
    private Rectangle2D.Double square;
    private Point dragOffset;
    private Rectangle2D.Double redRectangle;

    public ZoomPanel() {
        currentTransform = new AffineTransform();
        square = new Rectangle2D.Double(100, 100, 200, 200);
        redRectangle = new Rectangle2D.Double(0, 0, 1000, 1000);

        addMouseWheelListener(new MouseAdapter() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                double adjustedZoomFactor = e.getWheelRotation() < 0 ? ZOOM_MULTIPLIER : 1 / ZOOM_MULTIPLIER;
                double newZoomFactor = zoomFactor * adjustedZoomFactor;

                // Check if the new zoom factor is within the valid range
                if (newZoomFactor >= MIN_ZOOM && newZoomFactor <= MAX_ZOOM) {
                    zoomFactor = newZoomFactor;
                    zoomCenter = e.getPoint();

                    AffineTransform at = new AffineTransform();
                    at.translate(zoomCenter.getX(), zoomCenter.getY());
                    at.scale(adjustedZoomFactor, adjustedZoomFactor);
                    at.translate(-zoomCenter.getX(), -zoomCenter.getY());

                    currentTransform.preConcatenate(at);

                    repaint();
                }
            }
        });

        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
                if (square.contains(transformedPoint)) {
                    lastMousePosition = e.getPoint();
                    dragOffset = new Point(transformedPoint.x - (int) square.getX(), transformedPoint.y - (int) square.getY());
                } else {
                    lastMousePosition = null;
                }
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                if (lastMousePosition != null) {
                    Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
                    int newX = transformedPoint.x - dragOffset.x;
                    int newY = transformedPoint.y - dragOffset.y;

                    // Check if the new position is within the red rectangle
                    if (redRectangle.contains(newX, newY, square.getWidth(), square.getHeight())) {
                        square.setRect(newX, newY, square.getWidth(), square.getHeight());
                        lastMousePosition = e.getPoint();

                        repaint();
                    }
                }
            }
          });
      }
    
    
    private Point transformPoint(Point point, AffineTransform transform) {
        try {
            AffineTransform inverse = transform.createInverse();
            Point transformedPoint = new Point();
            inverse.transform(point, transformedPoint);
            return transformedPoint;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

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

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // Apply zoom factor
        if (zoomCenter != null) {
            g2d.transform(currentTransform);
        }

        // Draw red rectangle
        g2d.setColor(Color.red);
        g2d.fill(redRectangle);

        // Draw blue square
        g2d.setColor(Color.BLUE);
        g2d.fill(square);
    }
}

我的代码有问题......

package zoom;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

public class Demo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Zoomable Canvas");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);

        ZoomPanel zoomPanel = new ZoomPanel();
        JScrollPane scrollPane = new JScrollPane(zoomPanel);
        frame.add(scrollPane);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }
}

class ZoomPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private double zoomFactor = 1.0;
    private static final double ZOOM_MULTIPLIER = 1.1;
    private static final double MIN_ZOOM = 0.1; // Minimum zoom level
    private static final double MAX_ZOOM = 4.0; // Maximum zoom level

    private Point zoomCenter;
    private AffineTransform currentTransform;
    private Point lastMousePosition;
    private Rectangle2D.Double square;
    private Point dragOffset;
    private Rectangle2D.Double redRectangle;

    public ZoomPanel() {
        currentTransform = new AffineTransform();
        square = new Rectangle2D.Double(100, 100, 200, 200);
        redRectangle = new Rectangle2D.Double(0, 0, 1000, 1000);

        addMouseWheelListener(new MouseAdapter() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                double adjustedZoomFactor = e.getWheelRotation() < 0 ? ZOOM_MULTIPLIER : 1 / ZOOM_MULTIPLIER;
                double newZoomFactor = zoomFactor * adjustedZoomFactor;

                // Check if the new zoom factor is within the valid range
                if (newZoomFactor >= MIN_ZOOM && newZoomFactor <= MAX_ZOOM) {
                    zoomFactor = newZoomFactor;
                    zoomCenter = e.getPoint();

                    AffineTransform at = new AffineTransform();
                    at.translate(zoomCenter.getX(), zoomCenter.getY());
                    at.scale(adjustedZoomFactor, adjustedZoomFactor);
                    at.translate(-zoomCenter.getX(), -zoomCenter.getY());

                    currentTransform.preConcatenate(at);
                    updatePreferredSize(); // Add this line
                    repaint();
                }
            
            }
        });

        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
                if (square.contains(transformedPoint)) {
                    lastMousePosition = e.getPoint();
                    dragOffset = new Point(transformedPoint.x - (int) square.getX(), transformedPoint.y - (int) square.getY());
                } else {
                    lastMousePosition = null;
                }
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                if (lastMousePosition != null) {
                    Point transformedPoint = transformPoint(e.getPoint(), currentTransform);
                    int newX = transformedPoint.x - dragOffset.x;
                    int newY = transformedPoint.y - dragOffset.y;

                    // Check if the new position is within the red rectangle
                    if (redRectangle.contains(newX, newY, square.getWidth(), square.getHeight())) {
                        square.setRect(newX, newY, square.getWidth(), square.getHeight());
                        lastMousePosition = e.getPoint();

                        repaint();
                    }
                }
            }
          });
      }
    
    
    private Point transformPoint(Point point, AffineTransform transform) {
        try {
            AffineTransform inverse = transform.createInverse();
            Point transformedPoint = new Point();
            inverse.transform(point, transformedPoint);
            return transformedPoint;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

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

        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // Apply zoom factor
        if (zoomCenter != null) {
            g2d.transform(currentTransform);
        }

        // Draw red rectangle
        g2d.setColor(Color.red);
        g2d.fill(redRectangle);

        // Draw blue square
        g2d.setColor(Color.BLUE);
        g2d.fill(square);
    }

    private void updateScrollbars() {
        Container parent = getParent();
        if (parent instanceof JViewport) {
            JViewport viewport = (JViewport) parent;
            Rectangle viewRect = viewport.getViewRect();

            boolean horizontalScrollbarVisible = viewRect.width < redRectangle.width * zoomFactor;
            boolean verticalScrollbarVisible = viewRect.height < redRectangle.height * zoomFactor;

            JScrollPane scrollPane = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
            if (scrollPane != null) {
                scrollPane.setHorizontalScrollBarPolicy(horizontalScrollbarVisible ? JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED : JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                scrollPane.setVerticalScrollBarPolicy(verticalScrollbarVisible ? JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED : JScrollPane.VERTICAL_SCROLLBAR_NEVER);
            }
        }
    }

    private void updatePreferredSize() {
        int width = (int) (redRectangle.width * zoomFactor);
        int height = (int) (redRectangle.height * zoomFactor);
        setPreferredSize(new Dimension(width, height));
        revalidate();
    }
    
}

我尝试了camickr的建议,但没有使用scrollbarpolicy并覆盖有效的getPreferredSize——有点......当我调整大小时,我会得到时髦的滚动条闪烁,无论我尝试什么,我都无法在最大化后捕获恢复事件......所以覆盖代码没有任何效果

package zoom;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class SwingApp {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("Swing App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(640, 480);
        frame.setResizable(true);

        JScrollPane scrollPane = new JScrollPane();
        Editor editor = new Editor(scrollPane);

/*
        frame.addWindowStateListener(new WindowStateListener() {
            @Override
            public void windowStateChanged(WindowEvent e) {
                if ((e.getNewState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH
                        || e.getNewState() == Frame.NORMAL) {
                    editor.updateWorkspace();
                    editor.updatePreferredSize();
                    frame.repaint();
                }
            }
        });
*/
        frame.addComponentListener(new ComponentListener() {
            @Override public void componentResized(ComponentEvent arg0) {               
                editor.updateWorkspace();
                editor.updatePreferredSize();
                editor.repaint();
            }
            @Override public void componentHidden(ComponentEvent arg0) {}
            @Override public void componentMoved(ComponentEvent arg0) {}
            @Override public void componentShown(ComponentEvent arg0) {}                
        });     

        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    static class Editor extends JPanel {

        private static final long serialVersionUID = 1L;
        private static final int WORKSPACE_WIDTH = 300;
        private static final int WORKSPACE_HEIGHT = 300;

        private Dimension preferredSize;
        private Rectangle workspace;
        private Rectangle box;
        private JScrollPane scrollPane;

        private Editor(JScrollPane s) {
            scrollPane = s;
            preferredSize = new Dimension(WORKSPACE_WIDTH, WORKSPACE_HEIGHT);
            workspace = new Rectangle(0, 0, WORKSPACE_WIDTH, WORKSPACE_HEIGHT);
            box = new Rectangle(workspace.x + 100, workspace.y + 100, 100, 100);
            scrollPane.setViewportView(this);
//          updateWorkspace();
//          updatePreferredSize();
//          revalidate();
        }

        public void updateWorkspace() {
            int xPos = (getWidth() - workspace.width) / 2;
            int yPos = (getHeight() - workspace.height) / 2;
            workspace = new Rectangle(xPos, yPos, workspace.width, workspace.height);
            box = new Rectangle(workspace.x + 100, workspace.y + 100, box.width, box.height);
        }

        @Override
        public Dimension getPreferredSize() {
            return preferredSize;
        }

        private void updatePreferredSize() {
            Rectangle v = scrollPane.getViewport().getVisibleRect();

            if(v != null) { 
                int left = Math.min(v.x, workspace.x);
                int right = Math.max(v.x + v.width, workspace.x + workspace.width);
                int top = Math.min(v.y, workspace.y);
                int bottom = Math.max(v.y + v.height, workspace.y + workspace.height);
                preferredSize = new Dimension(right-left, bottom-top);
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillRect(workspace.x, workspace.y, workspace.width, workspace.height);

            g.setColor(Color.BLUE);
            g.fillRect(box.x, box.y, box.width, box.height);
        }
    }
}
java swing zooming jscrollpane mousewheel
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.