Hi,
Ich habe ein paar Probleme beim Resizen einer JScrollPane.
Hier ist, was ich tun möchte. Ich möchte gewisse Inhalte, z.B. Bilder, welche während der Laufzeit ihre Größe ändern können, anzeigen. Dabei möchte ich, dass mein Fenster stets nur so groß ist, wie nötig, um das Bild anzuzeigen (genau so, wie das viele Bildbetrachtungsprogramme tun). Wenn das Bild jedoch größer als der Bildschirm wird, sollen automatisch Scrollbars angezeigt werden.
Nun habe ich eine JComponent, auf die das Bild gezeichnet wird. Diese liefert die Bildgröße als preferred size. Ich habe diese in eine JScrollPane mit "scrollbars as needed" gepackt, um die Scrollbars wenn nötig anzuzeigen. Wenn sich nun die Größe des Bildes ändert, setze ich die Größe meines Frames auf dessen getPreferredSize(). Soweit, so gut.
Was nun passiert ist folgendes. Wenn das Bild größer wird, funktioniert alles wie gewünscht. Aber wenn das Bild kleiner wird, liefert die JScrollPane nicht ihre korrekte Größe in getPreferredSize() zurück (ich habe das soweit debugged, dass immer 16 Pixel zuviel in Breite und Höhe geliefert werden), so dass mein Frame nicht richtig verkleinert wird. Die extra Pixel entsprechen genau der Größe der Scrollbars, die aber nicht vorhanden sind (weil ja nicht nötig).
Interessant ist, dass das nur passiert, wenn ich die JScrollPane mit "scrollbars as needed" erstelle. Mit "scrollbars always" oder "never" passiert das nicht.
Hier ist ein wenig Beispielcode, der das Problem veranschaulicht. Ich habe das mit Java 1.6 unter Windows Vista und XP getestet und mit Java 1.5 under Fedora 6. Es tritt auf allen diesen Plattformen auf.
Was mache ich falsch?
Thomas
Ich habe ein paar Probleme beim Resizen einer JScrollPane.
Hier ist, was ich tun möchte. Ich möchte gewisse Inhalte, z.B. Bilder, welche während der Laufzeit ihre Größe ändern können, anzeigen. Dabei möchte ich, dass mein Fenster stets nur so groß ist, wie nötig, um das Bild anzuzeigen (genau so, wie das viele Bildbetrachtungsprogramme tun). Wenn das Bild jedoch größer als der Bildschirm wird, sollen automatisch Scrollbars angezeigt werden.
Nun habe ich eine JComponent, auf die das Bild gezeichnet wird. Diese liefert die Bildgröße als preferred size. Ich habe diese in eine JScrollPane mit "scrollbars as needed" gepackt, um die Scrollbars wenn nötig anzuzeigen. Wenn sich nun die Größe des Bildes ändert, setze ich die Größe meines Frames auf dessen getPreferredSize(). Soweit, so gut.
Was nun passiert ist folgendes. Wenn das Bild größer wird, funktioniert alles wie gewünscht. Aber wenn das Bild kleiner wird, liefert die JScrollPane nicht ihre korrekte Größe in getPreferredSize() zurück (ich habe das soweit debugged, dass immer 16 Pixel zuviel in Breite und Höhe geliefert werden), so dass mein Frame nicht richtig verkleinert wird. Die extra Pixel entsprechen genau der Größe der Scrollbars, die aber nicht vorhanden sind (weil ja nicht nötig).
Interessant ist, dass das nur passiert, wenn ich die JScrollPane mit "scrollbars as needed" erstelle. Mit "scrollbars always" oder "never" passiert das nicht.
Hier ist ein wenig Beispielcode, der das Problem veranschaulicht. Ich habe das mit Java 1.6 unter Windows Vista und XP getestet und mit Java 1.5 under Fedora 6. Es tritt auf allen diesen Plattformen auf.
Was mache ich falsch?
Thomas
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ScrollPaneTest2 implements ActionListener {
JFrame frame;
JComponent comp;
JButton b1, b2;
public void perform() {
frame = new JFrame("TestFrame");
JScrollPane scroll = new JScrollPane();
comp = new JComponent() {
public void paintComponent(Graphics g) {
Dimension d = getPreferredSize();
g.setColor(Color.blue);
g.fillRect(0, 0, (int)d.getWidth(), (int)d.getHeight());
}
};
comp.setPreferredSize(new Dimension(640, 480));
JPanel p = new JPanel(new BorderLayout());
JPanel pTop = new JPanel();
frame.getContentPane().add(p);
p.add(scroll, BorderLayout.CENTER);
scroll.getViewport().add(comp);
p.add(pTop, BorderLayout.NORTH);
pTop.add(b1 = new JButton("Big"));
pTop.add(b2 = new JButton("Small"));
b1.addActionListener(this);
b2.addActionListener(this);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == b1) {
comp.setPreferredSize(new Dimension(800, 600));
} else if (src == b2) {
comp.setPreferredSize(new Dimension(640, 480));
}
comp.revalidate();
Dimension dim = frame.getPreferredSize();
// TODO: adjust size to screen size if needed
frame.setSize(dim);
frame.validate();
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ScrollPaneTest2 test = new ScrollPaneTest2();
test.perform();
}
});
}
}