有 Java 编程相关的问题?

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

JavaJScrollPane不会在JPanel上滚动

我有一个JFrame,在其中我在一个大网格中绘制了很多图像。我的窗口不够大,无法容纳整个网格,因此我想使用一个JScrollPane,它允许我在窗口中显示网格的某些部分

我的问题是我不能滚动。当我这样做时,滚动条总是出现,它们似乎已经覆盖了整个区域

enter image description here

如您所见,滚动条给人的印象是整个区域都显示在窗口中。然而,如果我调整它的大小,你会注意到根本不是这样的

enter image description here

滚动条继续显示它们覆盖了整个区域

请注意,网格中的数字实际上是16×16像素的图像,但为了制作一个最小、完整且可验证的示例,我将图像替换为坐标字符串

以下是我的代码,用于最小、完整和可验证的示例:

import java.awt.Dimension;
import java.awt.Graphics;

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


public class Main {
    public static int[][] tiles;
    public static void main(String[] args) {
        Foo foo = new Foo();
        foo.run();
    }
}

class Foo {
    public void run(){
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        Panel panel = new Panel();

        panel.setPreferredSize(new Dimension(512,448));
        JScrollPane scrollPane = new JScrollPane(panel);

        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        frame.add(scrollPane);
        frame.setVisible(true);
        frame.pack();

        Main.tiles = new int[32][32];

        while (true) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            panel.repaint();    
        }
    }

}

class Panel extends JPanel {

    public void paintComponent(Graphics g){ 
        paintScreen(g);
    }

    private void paintScreen(Graphics g){
        int x =0, y =0;
        for (int i = 0; i < Main.tiles.length; i++) {
            for (int j = 0; j < Main.tiles[i].length; j++){
                g.drawString(i + " " + j, x*32, y*32);
                y++;
            }
            y=0;
            x++;
        }
    }
}

所以我的问题是:

Q:为什么JScrollPane不允许我在JPanel上滚动


共 (1) 个答案

  1. # 1 楼答案

    你的问题似乎就在这里:

    panel.setPreferredSize(new Dimension(512,448));
    

    将JScrollPane持有的JPanel约束为特定大小,不允许其扩展。永远不要这样做。而是约束JScrollPane或其视图端口

    例如

    import java.awt.Dimension;
    import java.awt.Graphics;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    public class Main {
       public static int[][] tiles;
    
       public static void main(String[] args) {
          Foo foo = new Foo();
          foo.run();
       }
    }
    
    class Foo {
       public void run() {
          JFrame frame = new JFrame();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
    
          Panel panel = new Panel();
    
          // !! panel.setPreferredSize(new Dimension(512,448));
          JScrollPane scrollPane = new JScrollPane(panel);
          scrollPane.getViewport().setPreferredSize(new Dimension(512, 448));
    
          scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
          scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    
          frame.add(scrollPane);
          frame.setVisible(true);
          frame.pack();
    
          Main.tiles = new int[32][32];
    
          while (true) {
             try {
                Thread.sleep(500);
             } catch (InterruptedException e) {
                e.printStackTrace();
             }
             panel.repaint();
          }
       }
    
    }
    
    class Panel extends JPanel {
    
       private static final int PREF_W = 1200;
       private static final int PREF_H = 1200;
    
       public void paintComponent(Graphics g) {
          super.paintComponent(g);
          paintScreen(g);
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    
       private void paintScreen(Graphics g) {
          int x = 0, y = 0;
          for (int i = 0; i < Main.tiles.length; i++) {
             for (int j = 0; j < Main.tiles[i].length; j++) {
                g.drawString(i + " " + j, x * 32, y * 32);
                y++;
             }
             y = 0;
             x++;
          }
       }
    }
    

    编辑
    尝试根据程序员的建议改进版本:

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.Scrollable;
    
    public class Main {
       public static int[][] tiles;
    
       public static void main(String[] args) {
          Foo foo = new Foo();
          foo.run();
       }
    }
    
    class Foo {
       public void run() {
          JFrame frame = new JFrame();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
    
          NumberPanel panel = new NumberPanel();
    
          // !! panel.setPreferredSize(new Dimension(512,448));
          JScrollPane scrollPane = new JScrollPane(panel);
          // !! scrollPane.getViewport().setPreferredSize(new Dimension(512, 448));
    
          scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
          scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    
          frame.add(scrollPane);
          frame.setVisible(true);
          frame.pack();
    
          Main.tiles = new int[32][32];
    
          while (true) {
             try {
                Thread.sleep(500);
             } catch (InterruptedException e) {
                e.printStackTrace();
             }
             panel.repaint();
          }
       }
    
    }
    
    class NumberPanel extends JPanel implements Scrollable {
    
       private static final int PREF_W = 1200;
       private static final int PREF_H = 1200;
       private static final int VP_WIDTH = 512;
       private static final int VP_HEIGHT = 448;
    
       public void paintComponent(Graphics g) {
          super.paintComponent(g);
          paintScreen(g);
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    
       private void paintScreen(Graphics g) {
          int x = 0, y = 0;
          for (int i = 0; i < Main.tiles.length; i++) {
             for (int j = 0; j < Main.tiles[i].length; j++) {
                g.drawString(i + " " + j, x * 32, y * 32);
                y++;
             }
             y = 0;
             x++;
          }
       }
    
       @Override
       public Dimension getPreferredScrollableViewportSize() {
          return new Dimension(VP_WIDTH, VP_HEIGHT);
       }
    
       @Override
       public int getScrollableBlockIncrement(Rectangle arg0, int arg1, int arg2) {
          // TODO Consider improving
          return 0;
       }
    
       @Override
       public boolean getScrollableTracksViewportHeight() {
          return false;
       }
    
       @Override
       public boolean getScrollableTracksViewportWidth() {
          return false;
       }
    
       @Override
       public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2) {
          // TODO Consider improving
          return 0;
       }
    }