有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在更大的图像上移动视图端口;jlabel+JScrollPane

我有一个JScrollPane m_jScrollPane,里面显示着一个JLabel m_jlImagem_jlImage是一个屏幕截图,在用户上次单击屏幕的位置绘制了一个红点。我希望将m_jScrollPane的查看区域移到m_jlImage上的红点上(阅读滚动)lastClick是用户最后单击的位置,与m_jlImage位于同一坐标

事实证明,这比我想象的要困难得多

我决定沿着同一个轴获得点击点的值与整个屏幕长度的比率,并按其最大值的相同比率滚动相应的滚动条。这似乎只适用于屏幕上最后一次点击的点位于左上角的情况

当点击点位于屏幕边缘时,我不确定如何处理这种情况。这种情况会产生一个比率,导致滚动条以相同的比率滚动,但红点会被滚动到屏幕边缘,因此无法查看。有没有关于我该如何克服这一点的建议

    public void scrollViewToLastClick()
    {
        int clckH = lastClick.y;
        int clckW = lastClick.x;

        int picH = this.m_jlImage.getHeight();
        int picW = this.m_jlImage.getWidth();

        int ratW = (int)(m_jScrollPane.getWidth()*(double)clckW/(double)picW);
        int ratH = (int)(m_jScrollPane.getHeight()*(double)clckH/(double)picH);

        m_jScrollPane.getHorizontalScrollBar().setValue(ratW);
        m_jScrollPane.getVerticalScrollBar().setValue(ratH);
    }

共 (1) 个答案

  1. # 1 楼答案

    这是一个非常基本的例子。它使用一个图像文件并将其放置在滚动窗格中(以循环方式)

    从那里,它只需使用Swing Timer来随机生成点(在图像的边界内)

    每次生成一个新点时,我只需使用scrollToRectVisible,将要渲染的点的位置和大小传递给它。这将确保新点(和点)在滚动窗格中可见

    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();
            }
        }
    }
    

    现在,如果你想显示尽可能靠近中心的点,这将需要额外的工作

    现在,如果你真的想玩得开心,可以将延迟设置为50-100毫秒;)