pack() lässt Ränder

  • Themenstarter Themenstarter wizard9
  • Beginndatum Beginndatum
W

wizard9

Gast
Ich habe in meinem JFrame eine Content-Pane mit FlowLayout erstellt. Dieser habe ich dann wiederum eine JComponent hinzugefügt, deren Größe ich über setPreferredSize() und ein anschließendes revalidate() während der Laufzeit ändere. Anschließend rufe ich auf meinem JFrame pack() auf, um die Größes des Fensters exakt der Größe meiner JComponent anzupassen.

War das Fenster vor der Größenänderung der JComponent zu klein zur Darstellung, arbeitet pack() wie gewünscht und vergrößert es so weit, dass meine JComponent exakt reinpasst. Ziehe ich das Fenster jedoch vorher manuell größer, sodass pack() verkleinern muss, klappt das nur bedingt: Es bleiben rechts und unterhalb meiner JComponent immer Ränder übrig.

Dass die JComponent in Wirklichkeit größer sein könnte als gedacht (nämlich genau um diesen beschriebenen Rand) kann ich eigentlich ausschließen, da ich mit folgendem Aufruf eine ScrollPane verwende:

Java:
setContentPane(new JScrollPane(contentPane));
und hier erscheinen die Scrollbars eben erst, wenn ich das Fenster am Ende manuell noch genau um die auftretenden Ränder verkleinere, d.h. die Content-Pane (und somit auch die darin liegende JComponent) kann nicht größer sein als gedacht. Es muss irgendwie an einer Kombination aus pack() und der Fenstergröße vor dem Aufruf von pack() liegen.

Weiß von euch jemand, wie ich dieses Problem beheben könnte?

Gruß
Wizard
 
😎 Das kann ich bestätigen.

Hier ein KSKB das den Bug demonstriert und einen Workaround aufzeigt:
Java:
/* $Id$ */

/* Copyright 2010 Sebastian Haufe

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.*;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class JScrollPanePackTestGui {

  static void createAndShowGui() {
    final JPanel scrolledContent =
          new JPanel(new FlowLayout(SwingConstants.LEADING)) {

            @Override
            protected void paintComponent(Graphics g) {
              super.paintComponent(g);
              g.setColor(Color.RED);
              final Dimension prefSize = getPreferredSize();
              final int w = prefSize.width;
              final int h = prefSize.height;
              g.drawRect(0, 0, w - 1, h - 1);
              g.setColor(Color.GREEN);
              g.drawRect(0 + 1, 0 + 1, w - 3, h - 3);
              g.setColor(Color.BLACK);
              g.drawRect(0 + 2, 0 + 2, w - 5, h - 5);
            }
          };
    scrolledContent.setPreferredSize(new Dimension(200, 200));
    scrolledContent.add(new JButton(new AbstractAction("Bug") {

      public void actionPerformed(ActionEvent e) {
        final Window w =
              SwingUtilities.getWindowAncestor((Component) e.getSource());
        w.pack();
      }
    }));
    scrolledContent.add(new JButton(new AbstractAction("Workaround") {

      public void actionPerformed(ActionEvent e) {
        final JRootPane rootPane =
              SwingUtilities.getRootPane((Component) e.getSource());
        rootPane.setSize(1, 1);
        rootPane.validate();
        final Window w = SwingUtilities.getWindowAncestor(rootPane);
        w.pack();
      }
    }));

    final JFrame f = new JFrame("Test Frame: JScrollPanePackTestGui"); //$NON-NLS-1$
    f.setContentPane(new JScrollPane(scrolledContent));
    f.pack();
    f.setSize(f.getWidth() + 1, f.getHeight() + 1);
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

      public void run() {
        createAndShowGui();
      }
    });
  }
}
Ebenius
 
Wunderbar, dein Workaround funktioniert einwandfrei. 🙂 Es handelt sich also offenbar tatsächlich um einen Bug in der Swing-Bibliothek!?

In der Zwischenzeit hatte ich auch noch herausgefunden, dass es gerade an der JScrollPane liegt. Es scheint genau der Platz zusätzlich zu bleiben, den man für die Darstellung der Scrollbalken bräuchte, aber es werden eben gar keine dargestellt (da sie ja auch nicht benötigt werden).
 
Wunderbar, dein Workaround funktioniert einwandfrei. 🙂 Es handelt sich also offenbar tatsächlich um einen Bug in der Swing-Bibliothek!?
Vermute ich auch. Ich habe nicht danach gesucht, kann mir aber kaum vorstellen, dass der Bug noch nicht in der Bug-Parade auftaucht.

In der Zwischenzeit hatte ich auch noch herausgefunden, dass es gerade an der JScrollPane liegt. Es scheint genau der Platz zusätzlich zu bleiben, den man für die Darstellung der Scrollbalken bräuchte, aber es werden eben gar keine dargestellt (da sie ja auch nicht benötigt werden).
Ich stimme auch hier zu. Es ist laut meiner Beobachtung (und ohne näheres hinsehen) genau der Platz für die JScrollBars.

Ebenius
 

Neue Themen


Zurück
Oben