JFrame.MAXIMIZED_BOTH höhe und breite abfragen

Hallo,

wie kann ich bei einem JFrame bei dem die Größe mit frame.setExtendedState(JFrame.MAXIMIZED_BOTH) gesetzt wurde herausfinden wie hoch und breit das Fenster ist?

Mit: frame.getWidth & frame.getHeight bekomme ich nur 0 raus.

Im Internet hatte jemand geschrieben, das man die abfrage erst nach frame.setVisible(true); machen muss.
Da bekomme ich auch was raus nur benötige ich diesen Wert bevor das JFrame gezeichnet wird, da auf diesen ein JLayeredPane mit JPanel drauf muss.

Daher habe ich folgendes versucht:

  1. JFrame erzeugen mit größe usw.
  2. frame auf setVisible = true setzen.
  3. width & heigth abfragen.
  4. frame auf setVisible = false setzen.
  5. LayeredPane und JPanel erstellen und auf JFrame setzen.
  6. frame wieder auf setVisible = true setzen.

Funktioniert leider nicht, man sieht nur kurz mal einen weißen streifen am Monitor und das wars dann.

Wie könnte ich das machen, ich benötige diese Werte.

SG

Wofür? (Nur um sicherzustellen, dass man nicht irgendwelche Workarounds bastelt, für etwas, was mit frame.doWhatYouWant() erledigt sein könnte. Im speziellen: Geht es darum, rauszufinden, wie viel Platz auf dem Bildschirm verfügbar ist? Wie genau muss das ggf. sein?)

Das JFrame passt sich an den Bildschirm an.
Das JLayeredPane das sich auf dem JFrame befindet soll einfach gleich groß sein wie das JFrame mehr nicht.
Damit das JLayeredPane auch funktioniert muss ich wie z.B. auch bei einem JLabel die größe angeben.
Das mache ich beim JLayeredPane mit setBounds.
Also: setBounds(0, 0, frame.getWidth, frame.getHeigth);
So wäre das JLayeredPane auch immer gleich groß wie das jFrame, dafür benötige ich aber getWidth & getHeigth von JFrame.

SG

Den ganzen Kram bräuchtest du nicht, wenn du dir das Beispiel aus deinem anderen Thread angesehen und übernommen hättest.
Ein LayoutManager erledigt das, ohne dass du dich darum kümmern musst.

Bei der Größe des Frames, die man mit getWidth() und getHeight() bekommt, wäre ohnehin der Rahmen und die Titelleiste dabei - d.h. für was auch immer im Frame ist, ist weniger Platz verfügbar. Und den verfügbaren Platz verteilen die LayoutManager.

Hör auf L-ectron-X und nutze LayoutManager. Bei allem anderen wirst du nicht glücklich werden … oder anders gesagt: du wirst im besten Fall selber eine eigene Version eines existierenden LayoutManagers nachbauen. Denn was passiert, wenn der Anwender die Größe deines Frames ändert? Richtig: du musst das Layout anpassen - das müsstest du dann auch reinprogrammieren.

2 Likes

Dem kann ich nur beipflichten. Nach einer kleinen Einarbeitungszeit kann man mit (verschachtelten) Layoutmanagern viel einfacher und flexibler, wartungsfreundlicher und dergleichen sein Layout vornehmen.

Vielen kann man schon mit verschachtelten JPaneln mit dem BorderLayout erledigen.

Inneren Maße eines Containies berechnen

Für den Fall, dass man doch aus irgendeinem Grund die Maße innerhalb eines Containers braucht, etwa um ihn zu bemalen, habe ich mir mal die folgende Klasse gebastelt:

package your.package;

import java.awt.Container;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;

/**
 * Diese Klasse berechnet von einem Container (also z.B. einem JPanel) den wirklich zum Bemalen zur
 * Verfügung stehenden Bereich und stellt verschiedenste Methoden zur Verfügung, diesen zu
 * erfragen.
 */

public class PaintableAreaCalculator {

    /** Breite des bemalbaren Bereichs. */
    private final int paintableWidth;

    /** Höhe des bemalbaren Bereichs. */
    private final int paintableHeight;


    /** x-Koordinate der oberen, linken Ecke des bemalbaren Bereichs. */
    private final int upperLeftX;

    /** y-Koordinate der oberen, linken Ecke des bemalbaren Bereichs. */
    private final int upperLeftY;

    /** Die obere, linke Ecke. */
    private final Point upperLeftPoint;


    /** x-Koordinate der unteren, rechten Ecke des bemalbaren Bereichs. */
    private final int lowerRightX;

    /** y-Koordinate der unteren, rechten Ecke des bemalbaren Bereichs. */
    private final int lowerRightY;

    /** Die untere, rechte Ecke. */
    private final Point lowerRightPoint;


    /** Bemalbarer Bereich als Rechteck. */
    private final Rectangle rectangle;

    /**
     * Konstruktor.
     *
     * Die wirklich Zeichenfläche wird ermittelt nach:
     * http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/java_swing_zeichenflaeche_ermitteln
     *
     * @param container
     *            Zu untersuchendes Gui-Element.
     */
    public PaintableAreaCalculator(Container container) {
        /* Gesamtmaße der Komponente bestimmen: */
        int totalPanelWidth = container.getWidth();
        int totalPanelHeight = container.getHeight();

        /* Größe des bemalbaren Bereiches ermitteln: */
        Insets insets = container.getInsets();
        paintableWidth = totalPanelWidth - insets.left - insets.right - 1;
        paintableHeight = totalPanelHeight - insets.top - insets.bottom - 1;

        /* Obere linke Ecke des bemalbaren Bereiches bestimmen: */
        upperLeftX = insets.left;
        upperLeftY = insets.top;
        upperLeftPoint = new Point(upperLeftX, upperLeftY);

        /* Untere rechte Ecke des bemalbaren Bereiches bestimmen: */
        lowerRightX = totalPanelWidth - insets.right - 1;
        lowerRightY = totalPanelHeight - insets.bottom - 1;
        lowerRightPoint = new Point(lowerRightX, lowerRightY);

        /* Rechteck bestimmen: */
        rectangle = new Rectangle(upperLeftX, upperLeftY, paintableWidth, paintableHeight);
    }

    /** Getter für die Breite des bemalbaren Bereichs. */
    public int getPaintableWidth() {
        return paintableWidth;
    }

    /** Getter für die Höhe des bemalbaren Bereichs. */
    public int getPaintableHeight() {
        return paintableHeight;
    }

    /** Getter für die x-Koordinate der oberen, linken Ecke des bemalbaren Bereichs. */
    public int getUpperLeftX() {
        return upperLeftX;
    }

    /** Getter für die y-Koordinate der oberen, linken Ecke des bemalbaren Bereichs. */
    public int getUpperLeftY() {
        return upperLeftY;
    }

    /** Getter für die obere, linke Ecke. */
    public Point getUpperLeftPoint() {
        return upperLeftPoint;
    }

    /** Getter für die x-Koordinate der unteren, rechten Ecke des bemalbaren Bereichs. */
    public int getLowerRightX() {
        return lowerRightX;
    }

    /** Getter für die y-Koordinate der unteren, rechten Ecke des bemalbaren Bereichs. */
    public int getLowerRightY() {
        return lowerRightY;
    }

    /** Getter für die untere, rechte Ecke. */
    public Point getLowerRightPoint() {
        return lowerRightPoint;
    }

    /** Getter für den bemalbaren Bereich als Rechteck. */
    public Rectangle getRectangle() {
        return rectangle;
    }

}

@Crian Ein bißchen OT, aber: Das ist ein bißchen heikel. Der container gibt ggf. eine width/height von -1 zurück, wenn er noch nicht “realized” ist (d.h. noch nicht “sichtbar und fertig gerendert”) …

Das mag sein, ich habe es bislang nur auf bereits dargestellte Container angewendet.

Etwas hab ich noch vergessen, ich habe auch noch ein JScrollPane.

So sollte das ganze aussehen:

  1. Auf das JFrame wird ein JScrollPane gelegt.
  2. Auf dem JScrollPane soll ein JLayeredPane drauf.
  3. Nun kommt das JPanel auf das LayeredPane.

Damit das JLayeredPane und das JScrollPane angezeigt wird, muss ich diesen beiden eine Größe geben.
Da das JFrame mit: “setExtendedState(JFrame.MAXIMIZED_BOTH)” sich an die Größe des Monitors anpasst, war meine Idee, das ich einfach vom JFrame die Größe abfrage und diese dann an die anderen beiden weitergebe. Somit wäre das JLayeredPane und das JScrollPane immer gleich groß wie das JFrame. Genau das möchte ich.

Wie kann ich das am einfachsten machen?

Hatte sowas noch nie.

SG

Noch etwas, wenn das JLayeredPane auch verwendet wird hat das JScrollPane keine ScrollBar mehr.
Nehme ich das JLayeredPane heraus, dann hat das JScrollPane wieder eine ScrollBar.
Muss ich diese nun zusätzlich erzeugen?
Normalerweise setzt das JScrollPane ja automatisch eine ScrollBar, wenn der Bedarf gegeben ist.

Weiters habe ich herausgefunden, das es unter Window 10 zumindest bei meinem Rechner kein: “getDisplayModes().heigth();” mehr gibt, sondern nur: “getDisplayModes().length”??
Unter Win 7 gibt es das.

Ich habe versucht über GraphicsDevice mir die länge und höhe zu holen, funktioniert unter Win 7 auch wunderbar.

Woran liegt das??

SG

Nein. (<- Punkt).

Wenn du ein compilierbares Beispiel postest, wird vermutlich in der darauffolgenden Antwort die Lösung gepostet. “Vermutlich”, weil es auf Basis dessen, was du hier beschreibst, auch passieren könnte, dass man dir erklärt, was an deinem bisherigen Ansatz von Grund auf falsch ist, aber das wäre ja auch was.

Wenn man eine einzelne Component in einen JFrame legt, ist die automatisch so groß, wie der verfügbare Platz im Frame. Wenn diese Component ein ScrollPane ist, dann muss das, was IN dieser Scrollpane ist, sagen, wie groß es gerne wäre, damit entschieden werden kann, ob Scrollbalken angezeigt werden, oder nicht.

Als ich angefangen habe zu programmieren, war ich auch so stur, aber ich habe schnell mitbekommen, dass die Leute möglicherweise doch wissen, wovon sie reden. Also habe ich mich mit dem befasst, wovon sie redeten. Und erst mit diesem Schritt machte ich Fortschritte.

So lange du nicht einsiehst, dass du mit deinen Bemühungen auf dem Holzweg bist, wirst du dich immer im Kreise drehen, kaum Fortschritte erzielen und niemals gute Software schreiben.

Poste relevanten Code, am besten kompilierbar/ausführbar, zeige an Hand von Bildern, wie es aussehen soll, dann kann man auch helfen.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class probieren {

probieren(){
	
	BorderLayout border_layout = new BorderLayout();
	GraphicsDevice display;
	JFrame frame = new JFrame();
	JButton button = new JButton();
	JLabel label = new JLabel();
	JPanel panel = new JPanel();
	JScrollPane scroll_pane = new JScrollPane();
	JLayeredPane layered_pane = new JLayeredPane();
	ImageIcon icon = new ImageIcon("Test-Bild.jpg"); // Das Bild habe ich jetzt nicht angehängt.
	
	display = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setLayout(border_layout);
	frame.setSize(display.getDisplayMode().getWidth(), display.getDisplayMode().getHeight());
	
	button.setBounds(50, 50, 80, 80);
	button.setBackground(Color.red);
	button.setText("Test-Button");
	
	scroll_pane.setSize(frame.getWidth(), frame.getHeight());
	
	panel.setSize(frame.getWidth(), frame.getHeight());
	panel.setOpaque(false);
	panel.setLayout(null);
	
	label.setBounds(0, 0, 2000, 1800); // Bild mit einer Größe von 2000 x 1800 px.
	label.setIcon(icon);
	
	panel.add(button);
	
	frame.add(scroll_pane, BorderLayout.CENTER);
	scroll_pane.setViewportView(layered_pane);
	layered_pane.add(label, new Integer(0));
	layered_pane.add(button, new Integer(1));
	
	frame.setVisible(true);
}

public static void main(String[] args) {
	probieren test = new probieren();
}
}

Mal mit LayoutManager, mal ist er ausgeschaltet…
Wozu ist die JScrollPane? Was soll da hinein? Welchen Sinn hat sie? Warum willst du die JLayeredPane scrollen? Welchem Zweck soll die JLayeredPane dienen? Wie soll denn dein JFrame mal aussehen?

Der Code ist ein Anfang, um zu sehen, dass Einiges schief läuft. Für eine Beispiellösung wäre noch interessant, was du für ein Ziel verfolgst. Was möchtest du erreichen?

  • Klassennamen werden groß und in CamelCase geschrieben
  • Das GUI sollte auf dem Event-Dispatch-Thread erzeugt werden
  • Keine unterstriche_in_variablennamen
  • Keine “überflüssigen” Variablen erzeugen

Wenn man das Layout vernünftig macht, braucht man auf components praktisch nie setBounds oder setSize aufzurufen. Tatsächlich macht der layout manager solche Aufrufe wieder “kaputt” - er setzt Größe und Bounds, so, dass alles richtig ist.

Es ist aber immer noch nicht klar, was richtig hier sein soll.

Also:

Du willst einen Frame. Im Hintergrund soll ein Bild angezeigt werden. Das Bild soll man (mit einer ScrollPane) scrollen können, falls es größer ist, als der im Frage verfügbare Platz.

So weit richtig?

Dann soll da noch irgendwo ein Button sein. Der soll über das “Hintergrundbild” drübergemalt sein. Gibt es einen driftigen Grund, warum der Button händisch an eine bestimmte Position gesetzt werden soll?


Edit:

  • Gruppiere den Code so, dass er Sinn ergibt, und man weiß, was passiert
  • Der button wird sowohl zum panel als auch zur LayeredPane hinzugefügt. Was soll da rauskommen?

Eigentlich hatte L-ectron-X in einem anderen Thread schon passenden Code gepostet. Ich vermute, dass ein layered pane nicht das ist, was du willst.

Aber um auf den Titel dieses threads zurückzukommen: Die Größe des DisplayMode zu verwenden macht hier schlicht keinen Sinn. Die Taskleiste bei Windows wird das Fenster zum Teil überdecken. Du suchst vermutlich das hier:

    ....
    frame.setBounds(getMaximumWindowBounds());
    frame.setVisible(true);
}

private static Rectangle getMaximumWindowBounds()
{
    GraphicsEnvironment graphicsEnvironment = 
        GraphicsEnvironment.getLocalGraphicsEnvironment();
    return graphicsEnvironment.getMaximumWindowBounds();
}

Diese Klasse habe ich nur erstellt, um mal zu testen wie das gehen könnte.

Ich weiß das man Klassen Groß schreibt, ist aber nur eine Test-Klasse.
Ich verwende das underline, da es bei einer großen Menge an Variablen viel einfacher ist den Überblick zu behalten.
In diesem Beispiel ist es natürlich überflüssig.

„Keine überflüssigen Variablen“, sollten nicht vorkommen ist mir auch klar.
Wie gesagt, ich habe hier nur mal schnell versucht wie es funktionieren könnte.

Ich weiß das dieser Source schlampig ist, doch das heißt nicht, das meine Programme nichts wert sind. Bis jetzt habe ich noch alles hinbekommen.
Ich würde hier ja nicht nachfragen wenn ich wüsste wie ich das mit dem JLayeredPane und dem JScrollPane machen muss.
Da ich das in dieser Form so noch nie benötigt habe, weiß ich auch nicht wirklich wie ich das machen muss.
Daher frage ich ja euch.

Das eine hat mit dem anderen nicht (zwingend) was zu tun. Du kannst die tollsten Programme schreiben, wenn du dich aber nicht an gängige Sprachkonventionen hälst, werden dich deine Kollegen hassen :wink:.

Die Konventionen sollten dir in Fleisch und Blut übergehen. Deswegen zählt sowas wie “Test-code” als Ausrede herzlich wenig. Vor allem weil dir die Leute hier basierend auf dem Code helfen möchten. Und je mehr du von gewohnten Konventionen abweichst, desto weniger bock haben andere, deinen Code zu lesen. (Hat nichts mit Böswilligkeit zu tun).

Das ist eine Gewöhnungssache. Dummerweise gewöhnst du dir hier etwas falsches an. Damit tust du dir keinen gefallen.

Ich möchte nochmal Betonen: Konventionen sind unglaublich wichtig und erleichtern das Miteinander. Sowohl hier als auch wenn du mal in einer Firma programmierst. Und spätestens beim letzteren wird man dich zwingen. Z.T automatisiert mit Tools die deine Änderungen ablehnen, wenn du gegen Konventionen verstößt. Und da geht es dann weiter mit so Sachen wie “… final static …” oder doch “… static final …” (ich habs mir anscheinend falsch rum angewöhnt, weswegen Sonar jedes mal drüber meckert…)

2 Likes

Die Punkte habe ich (stichpunktartig) erwähnt, weil sie wichtig sind, aber nichts mit der eigentlichen Frage zu tun haben. Die Frage ist aber, soweit ich das sehe, noch nicht vieeel genauer benannt, als mit

Beschreib’ nochmal (präzise) was das Ergebnis sein soll.

Ich möchte einfach nur ein JFrame haben, was sich an den Bildschirm anpasst.
Auf das JFrame soll ein JScrollPane und auf dieses ein JLayeredPane.
Auf das JLayeredPane kommt dann einmal ein JLabel für das Hintergrundbild und dann noch ein JPanel mit Buttons.
Das JScrollPane benötige ich als erstes Mal für das Hintergrundbild, damit man auf jeden Monitor egal mit welcher Größe alles sehen kann. Weiters wird es sehr viele Buttons geben, die eine bestimmte Größe haben und damit hier auch alle Sichtbar sind muss ich ebenfalls ein JScrollPane haben.
Mehr nicht.
Das meiste funktioniert ja schon, bis auf die Kombination von JScrollPane und JLayeredPane.
So eine Kombination hatte ich noch nie, da ich dies bis jetzt nicht gebraucht habe.