JPanel Größe falsch

Lunitarii

Grünschnabel
Hallo erstmal zusammen,

Bin neu hier und würd euch gern sofort mit einem Problem bombadieren :), welches mir beim Schreiben eines einfachen Testprogramms wiederfahren ist:

Im Prinzip ist es ein JFrame mit einem JPanel und auf das ich zunächst ein Hintergrundbild male via Graphics2D Objekt und darüber lasse ich ein weiteres bild sich bewegen.
Eigendlich trivial und es klappt auch alles soweit wunderbar.

Mein Problem ist, dass ich beim erstellen des JFrames explizit seine Größe angebe (640 x 480).
Wenn ich nun das Programm starte ist das Fenster jedoch nur etwa 455 Pixel hoch, was mich bald zur Verzweiflung bringt, da ich es auch nach eingehender Recherche nicht in den Griff bekomm.

Vll hat ja jemand schon Erfahrungen damit gesammelt und weiss einen Rat?

Vielen Dank schonmal im Vorraus

EDIT: Ich hab noch etwas rumprobiert und habe folgende Vermutung:
Kann es sein, dass ich bei der Angabe des der Größe des JFrames die höhe des Statusbalkens sowie die Breite des Ramens des Fensters mit einberechnen muss?

Mhhh, meine Vermutung scheint sich zu bestätigen. Addiere ich 32 auf die Höhe und 6 auf die Breite (JFrame) ist der angezeigte Bereich korrekt (WinXP).
Da der Ramen tatsächlich 3 Pixel Breite zu haben scheint wäre das zumindest ein einleuchtender Erklärungsversuch.

Die Frage die sich dann jedoch unweigerlich stellt ist: Wenn dies alles tatsächlich der Fall sein sollte, bleibt das dann auch Plattformunabhängig?
Ich kann mir gut vorstellen, dass unter anderen Windowmanagern die Abmessungen des Fenster"overheads" (entschuldigt dieses konstruierte Wort :) ) andere Dimensionen hat.

Mein Ziel ist es ja, den Anzeigebereich (JPanel) plattformunabhängig immer auf genau 640x480 Pixel zu setzen ohne Schmiereffekte wir weisse Balken etc zu bekommen.

Nun ja, soviel zu meine Vermutungen, würd mich freun, wenn mich jemand korrigiert oder auch gern bestätigt :)

Weitere Zeit zieht ins Land und ich hab die "Antwort" auf meine Frage gefunden:
Die Größe des JFrames beinhaltet tatsächlich die Größe des "Drumherums".

Aber eine beantwortete Frage wirft zwangsläufig 3 weitere auf :)

Mein Ziel ist es nun, die Größe des JFrames so zu wählen, dass die Innengröße genau den gewünschten 640x480 entspricht.

habe da bisher einiges über frame.pack() und setPreferedSize gelesen, leider noch nichts, was mir wirklich weiterhilft. Aber ich bleib am Ball ;)

Eine Frage möcht ich aber dennoch gern in den Raum werfen:
Java:
public class GrafTTT extends JFrame implements Konstanten{
  
    public GrafTTT() {
        add(new Board());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(WINWIDTH, WINHEIGHT);
        setLocationRelativeTo(null);
        setTitle("GrafixTTT");
        setVisible(true);
    }

    public static void main(String[] args) throws IOException {

       new GrafTTT();
    }
}

class Board extends JPanel implements ActionListener, Konstanten {

    public Board() {

       [...]

        setDoubleBuffered(true);
        timer = new Timer(TIMER, this);
        timer.start();
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;

        [...]

        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


    public void actionPerformed(ActionEvent e) 
      {

         [...]

         repaint();  
      }
}

Das ist mein Ansatz bisher (ohne lästigen Code der auch wirklich was macht :) )
Ist meine ursprüngliche Premisse (Größe des JFrames anhand der gewünschten Größe des JPanels plattformunabhängig zu wählen) kompatibel mit diesem Ansatz, oder muss ich ganz oder etwas andere Wege gehen?
 
Zuletzt bearbeitet von einem Moderator:

genodeftest

Erfahrenes Mitglied
Hi
kannst du deinen Code bitte in java-Tags fassen (siehe meine Signatur) ?

Du könntest das JContentPane oder JRootPane auf eine feste Größe setzen und dann pack() aufrufen. Normalerweise ist es aber weder sinnvoll noch nötig, das Fenster auf eine genau definierte Breite zu setzen. Wozu bräuchtest du das?
 

Lunitarii

Grünschnabel
Danke erstmal für die schnelle Antwort,
Das mit den Javatags ist auf jeden Fall sinnvoll und ich werd mich in Zukunft gern daran halten
(Ok, nächstes mal sollte ich mich vll erstmal informieren über soetwas :) )

Der Grund ist in erster Linie einen vergleichstest zwischen den Geschwindigkeiten von Swing und der SDL library von C zu realisieren. Da ich das gerne auf verschiedenen Plattformen testen würde, wäre es wünschenswert, das ganze plattformunabhängig zu gestalten.
Die feste Größe ergibt sich aus der Premisse, möglichst identische Verhältnisse zwischen den beiden Testprogrammen zu schaffen.
Nun könnte man einwerfen, dass es sicherlich schon derartige Tests gibt, aber sehe ich das ganze auch als gute Übung, um einen Überblick über die Möglichkeiten von Java zu bekommen.
Ferner denke ich mir, dass bei der Benutzung von Skins zB die Innengröße eher entscheidend ist, als die Größe des gesamtframes, welche ja extrem Plattform - und einstellungsabhängig ist.

Als nächsten Schritt hatte ich mir vorgestellt, Skins und Sprites dynamisch anhand der Fenstergröße zu skalieren, aber einen Schritt nach dem anderen :)
Ich denke mir, dass die Fähigkeit, die Innengröße direkt zu manipulieren auch ein guter Verständnisschritt ist, um dann später mit selbiger rumzujonglieren.

Leider hatte ich noch keine Gelegenheit, mit pack() zu experimentieren, aber ich werd mich sofort daransetzen und meine Erfahrungen und eventuelle Probleme dann hier gerne zum Besten geben... :)

Edit: Super, läuft tadellos :D

Durch hinzufügen von
Java:
 pack();
im Konstruktor von GrafTTT und
Java:
setPreferredSize(new Dimension(640, 480));
im Konstruktor von Board ist die Innengröße genau so, wie ich sie haben wollte :)

Ein kleiner "Schmiereffekt ist mir jedoch aufgefallen:
setze ich
Java:
  setResizable(false);
wird das Fenster 2 Pixel in Höhe und Breite vergrößert.
Lasse ich es weg ists perfekt, aber leider resizeble.
Die Frage, die sich mir nun stellt (ich weiss, es nimmt einfach kein Ende :) ) ist, sind diese 2 Pixel unabhängig von Plattform und persönlichen Einstellungen des OS immer konstant?
Wenn dem so wäre könnte ich ja darauf recht trivial plattformunabhängig reagieren.
 
Zuletzt bearbeitet:

Lunitarii

Grünschnabel
Alle Klarheiten beseitigt. Hier mal der vollständige Rahmencode:

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.imageio.*;
import java.io.*;

// imports ohne Gewähr, da ich für den Rest des Codes so einiges brauch, was hierfür vll 
// überflüssig ist

interface Konstanten
  {
     int WINWIDTH = 640, WINHEIGHT = 480, TIMER = 1;
  }

public class GrafTTT extends JFrame implements Konstanten{
  
    public GrafTTT() {
        add(new Board());
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        setTitle("GrafixTTT");
        setVisible(true);
    }
 
    public static void main(String[] args) throws IOException {
 
       new GrafTTT();
    }
}
 
class Board extends JPanel implements ActionListener, Konstanten {
 
    public Board() {

       setPreferredSize(new Dimension(WINWIDTH - 2, WINHEIGHT - 2));
 
       //  [...] 
 
        setDoubleBuffered(true);
        timer = new Timer(TIMER, this);
        timer.start();
    }
 
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;
 
        //  [...] 
 
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }
 
 
    public void actionPerformed(ActionEvent e) 
      {
 
      //   [...] 
 
         repaint();  
      }
}
 

genodeftest

Erfahrenes Mitglied
Ich vermute mal, dass die 2 Pixel von deinem Window Manager abhängen. So einen Effekt habe ich schon mehrfach bei nativen Anwendungen beobachtet, kann mich allerdings gerade nicht erinnern, auf welchem System.