更新时间:2023-12-05 20:22:28
首先,请记住,组件的preferredSize
同时提供了视口的大小和JScrollPane
现在,在从房间尖叫之前,Swing提供了Scrollable
界面,可让您向JScrollPane
和JViewport
提供更多信息,包括首选的视口尺寸(允许使用JScrollPane
小于视图在布局时显示的首选大小),这就是您感兴趣的,当视图小于视图区域时应如何调整视图大小
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane tp = new TestPane();
JSlider slider = new JSlider(50, 1024);
slider.setValue(200);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
tp.apply(new Dimension(value, value));
tp.revalidate();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(slider, BorderLayout.NORTH);
frame.add(new JScrollPane(tp));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private Dimension preferredSize = new Dimension(200, 200);
public TestPane() {
setBackground(Color.RED);
}
@Override
public Dimension getPreferredSize() {
return preferredSize;
}
public void apply(Dimension size) {
preferredSize = size;
revalidate();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
I'm making a level editor for a project of mine so I added a JPanel to a JScrollPane in order to view the level being worked on. The idea was that if the level was too big the scroll pane would handle that. The issue is when the level is to small, when I try to size the panel to a size smaller than the scrollpane it gets stretched to fill the whole scrollpane instead of the size I set. I can't seem to find a solution to the problem.
EDIT: I added a some sample code, When the window is enlarged the panel stretches to fit the scrollpane instead of staying at the set 500 by 500 in the example.
Setting up the JScrollPane:
public class Example {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
LevelView levelView = new LevelView();
JScrollPane pane = new JScrollPane(levelView);
frame.add(pane, BorderLayout.CENTER);
frame.setVisible(true);
}
}
JPanel:
public class LevelView extends JPanel {
private static final long serialVersionUID = 1L;
public LevelView() {
Dimension dim = new Dimension(500, 500);
setPreferredSize(dim);
setMaximumSize(dim);
setMinimumSize(dim);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(getWidth() + " " + getHeight());
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
// Draw grid
g.setColor(Color.WHITE);
for (int x = 0; x < getWidth(); x += 50) {
g.drawLine(x, 0, x, getHeight());
}
for (int y = 0; y < getHeight(); y += 50) {
g.drawLine(0, y, getWidth(), y);
}
}
}
Thanks in advance!
First of all, remember, the preferredSize
of the component is providing both the size of the viewport AND the size hints for the JScrollPane
Now, before you run screaming from the room, Swing provides the Scrollable
interface to allow you to provide more information to the JScrollPane
and JViewport
, including the preferred view port size (which allows the JScrollPane
to be smaller than the preferred size of the view been displayed when it's been laid out) and, which is what you're interested in, how the view should be sized when it is smaller than the view area
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane tp = new TestPane();
JSlider slider = new JSlider(50, 1024);
slider.setValue(200);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
tp.apply(new Dimension(value, value));
tp.revalidate();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(slider, BorderLayout.NORTH);
frame.add(new JScrollPane(tp));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private Dimension preferredSize = new Dimension(200, 200);
public TestPane() {
setBackground(Color.RED);
}
@Override
public Dimension getPreferredSize() {
return preferredSize;
}
public void apply(Dimension size) {
preferredSize = size;
revalidate();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}