I'm using Java Swing for my application, and I want to make use of the JViewport to show a fragment of some canvas-like panel 'behind' the port. But somehow the viewport never positions its view, so there must be something I'm doing. What am I doing wrong, why this code is not working?

The following is an example of what I'm doing on a bigger and more complex scale.

public class MyApp
{
  // THIS IS A TEMPORARY TEST TO GET VIEWPORT WORKING
  public static void main(String[] args)
  {
    JFrame frame = new JFrame();
    JViewport viewport = new JViewport();
    viewport.setOpaque(true);
    viewport.setBackground(Color.GRAY);
    frame.add(viewport, BorderLayout.CENTER);
    JPanel canvas = new JPanel(null);
    canvas.setBackground(Color.CYAN);
    viewport.setView(canvas);
    viewport.setViewSize(new Dimension(500, 500));
    viewport.setExtentSize(new Dimension(300, 300));
    viewport.setPreferredSize(new Dimension(300, 300));

    // item one
    JLabel label = new JLabel("This is a 32x32 box");
    label.setOpaque(true);
    label.setBackground(Color.GREEN);
    label.setIcon(Sprites.BOX2.getSprite());
    label.setBounds(0, 0, 200, 32); // position upper left, 200 wide
    label.setHorizontalAlignment(SwingConstants.LEFT);
    canvas.add(label);

    // item two
    JLabel label2 = new JLabel("This is a 32x32 wall");
    label2.setOpaque(true);
    label2.setBackground(Color.ORANGE);
    label2.setIcon(Sprites.WALL1.getSprite());
    label2.setBounds(300, 468, 200, 32); // position lower right, 200 wide
    label2.setHorizontalAlignment(SwingConstants.RIGHT);
    label2.setHorizontalTextPosition(SwingConstants.LEFT);
    canvas.add(label2);

    // this should scroll the canvas to the left and up, so the box becomes invisible and the wall visible
    viewport.setViewPosition(new Point(200, 200));  

    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}

The result is that the 'canvas' is simply sticking at 0,0, it never moves to 200,200 like I do with setViewPostition(). It's contents is perfectly positioned well, regardless of the null layout manager. I just wrote the canvas to be a JPanel for simplicity, but it's really a complex JLayeredPane.

有帮助吗?

解决方案

There are several problems in your case:

  • You use null-layout/absolute positionning: stop doing that... forever. It's a bad practice, a very bad and nasty habit which always leads to the same point: tons of problems.
  • Don't call setPreferredSize(): either use an appropriate LayoutManager or override getPreferredSize()
  • Consider implementing Scrollable for your canvas and where getPreferredScrollableViewportSize() would return new Dimension(300, 300) (the targetted viewport extent size)
  • Calling setSize()/setExtentSize() is pretty much useless because this will be overriden by LayoutManager.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top