Moving a view port over a larger image; JLablel+JScrollPane

前端 未结 1 1328
悲&欢浪女
悲&欢浪女 2020-12-21 12:30

I have a JScrollPane m_jScrollPane with a JLabel m_jlImage being displayed inside of it. The m_jlImage is a screen capture with a red

相关标签:
1条回答
  • 2020-12-21 13:20

    This is a pretty basic example. It uses a image file and places it within a scrollpane (in a round about way).

    From there, it simply uses a Swing Timer to randomly generate points (within the bounds of the image).

    Each time a new point is generated, I simply use scrollToRectVisible, passing it the location and the size of the point I want to render. This will ensure that the new point (and the dot) is visible within the scroll pane.

    enter image description here

    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.border.LineBorder;
    
    public class ScrollTest {
    
        public static void main(String[] args) {
            new ScrollTest();
        }
    
        private JScrollPane scrollPane;
        private DesktopPane desktopPane;
    
        public ScrollTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    try {
                        desktopPane = new DesktopPane();
                        scrollPane = new JScrollPane(desktopPane);
    
                        JFrame frame = new JFrame("Testing");
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        frame.add(scrollPane);
                        frame.setSize(desktopPane.getPreferredSize().width / 2, desktopPane.getPreferredSize().height / 2);
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    } catch (IOException exp) {
                        exp.printStackTrace();
                    }
                }
            });
        }
    
        public class DesktopPane extends JLayeredPane {
    
            private List<Point> points;
    
            public DesktopPane() throws IOException {
                points = new ArrayList<>(25);
                final BufferedImage img = ImageIO.read(new File("Desktop.jpg"));
                final JLabel desktop = new JLabel(new ImageIcon(img));
                final JPanel overlay = new JPanel() {
    
                    @Override
                    protected void paintComponent(Graphics g) {
                        super.paintComponent(g);
                        int xOff = desktop.getX();
                        int yOff = desktop.getY();
                        int count = 0;
                        FontMetrics fm = g.getFontMetrics();
                        int height = fm.getHeight();
                        for (Point p : points) {
                            g.setColor(Color.RED);
                            String text = Integer.toString(++count);
                            int width = fm.stringWidth(text);
                            int radius = Math.max(width, height) + 5;
                            int x = xOff + p.x - radius / 2;
                            int y = yOff + p.y - radius / 2;
                            g.fillOval(x, y, radius, radius);
                            g.setColor(Color.WHITE);
                            x += (radius - width) / 2;
                            y += ((radius - height) / 2) + fm.getAscent();
                            g.drawString(text, x, y);
                        }
                    }
                };
                overlay.setOpaque(false);
    
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.weightx = 1;
                gbc.weighty = 1;
                gbc.fill = GridBagConstraints.BOTH;
    
                add(desktop, gbc);
                add(overlay, gbc);
    
                setLayer(desktop, 0);
                setLayer(overlay, 5);
    
                overlay.setBorder(new LineBorder(Color.RED));
    
                Timer timer = new Timer(1000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        int x = (int) Math.round(Math.random() * img.getWidth());
                        int y = (int) Math.round(Math.random() * img.getHeight());
                        points.add(new Point(x, y));
                        repaint();
    
                        FontMetrics fm = getFontMetrics(overlay.getFont());
                        int height = fm.getHeight();
                        String text = Integer.toString(points.size() - 1);
                        int width = fm.stringWidth(text);
                        int radius = Math.max(width, height) + 5;
    
                        scrollRectToVisible(new Rectangle(x - radius / 2, y - radius / 2, radius, radius));
                    }
                });
                timer.start();
            }
        }
    }
    

    Now, if you want to display the point as close to the centre as possible, that will require additional work...

    Now, if you really want to have fun, set the delay to something like 50 - 100 milliseconds ;)

    0 讨论(0)
提交回复
热议问题