Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallihallo,
habe ein Problem mit JPanels.
Das JPanel, welches über den Rand hinaus exisitiert, sollte eigentlich im CENTER des inneren
BorderLayouts liegen, jedoch stimmt das ja irgendwie nicht.
Ich habe schon versucht an allen möglichen Stellen pack() einzufügen, was leider auch nichts geändert hat.
Da mein Projekt recht unübersichtlich mit unterschiedlichen Klassen, die zur Oberfläche beitragen (jeweiliger Teil wird als return JPanel im Endeffekt in die mainGUI gesetzt) weiß ich nicht so recht, was ich davon posten soll, deshalb erst Mal nur ein Foto
Ich hoffe ihr könnt mir helfen... würd mich freuen
lg Schmuggler
GUI-Programmierung kann eine komplizierte Sache sein.
Und ohne einen Fetzen Code, nur mit einem Bild kann man nur sehr schlecht eine Fehleranalyse machen.
Das ist dann mehr so was wie ein ins Blaue hinein raten.
Mein Rateversuch:
Ich vermute, daß du dem JFrame "Bla" eine feste (Fenster-)Größe zugeordnet hast (z. B. mit .setBounds()).
Nimm es heraus, dann sollte es mit .pack() funktionieren. Setze das .pack() bevor du das JFrame sichtbar machts.
Hier der Code hoffentlich ausreichend ausgewählt zum Verständnis
Main-GUI:
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.UIManager.*;
public class GUI extends JFrame {
// Anfang Attribute
// Layout
private JPanel rahmen = new JPanel(new GridLayout(6,1));
private JPanel zweiteSchicht = new JPanel(new BorderLayout());// in dessen CENTER tritt der Fehler auf
private JPanel innenButtons = new JPanel(new GridLayout(8,1)); // die Buttons am WEST des zweiteSchicht
private JPanel main = new JPanel();
// Buttons & Labels
// Rahmen
private JButton logo = new JButton("Logo");
private JButton haus = new JButton("Haus");
private JButton kommunikation = new JButton("Kommunikation");
private JButton organisation = new JButton("Organisation");
private JButton www = new JButton("WWW");
private JButton einstellungen = new JButton("Einstellungen");
// zu Haus
private JButton back = new JButton("Back");
private JButton hausinnen = new JButton("Innen");
private JButton hausaußen = new JButton("Außen");
private JButton sicherheit = new JButton("Sicherheit");
// Zum Testen
JPanel test = new JPanel();
// Ende Attribute
public GUI(String title, Ctrl c) {
// Frame-Initialisierung
super(title);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
int frameWidth = 800;
int frameHeight = 600;
setPreferredSize(new Dimension(frameWidth, frameHeight));
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
// Layout aufbauen
cp.add(rahmen, BorderLayout.WEST);
cp.add(zweiteSchicht, BorderLayout.CENTER);
zweiteSchicht.add(main, BorderLayout.CENTER); // in main spielt sich am Ende alles ab also auch der Fehler
main.setBackground(Color.BLUE);
// Buttons für Navigation anbringen
rahmen.add(logo);
rahmen.add(haus);
rahmen.add(kommunikation);
rahmen.add(organisation);
rahmen.add(www);
rahmen.add(einstellungen);
// Buttons für Innen
innenButtons.add(back);
innenButtons.add(hausinnen);
innenButtons.add(hausaußen);
innenButtons.add(sicherheit);
// Anfang Komponenten
// ActionListener
haus.addActionListener(c);
haus.setActionCommand("Haus");
back.addActionListener(c);
back.setActionCommand("Back1");
hausinnen.addActionListener(c);
hausinnen.setActionCommand("Innen");
// Ende Komponenten
setResizable(true);
pack();
setVisible(true);
}
// Anfang Methoden
public void clickHaus(){ // innere Buttonleiste vom Bild wird mit click auf Button Haus geöffnet
zweiteSchicht.add(innenButtons, BorderLayout.WEST);
zweiteSchicht.setOpaque(false);
innenButtons.setVisible(true);
/*innenButtons.add(back);
innenButtons.add(hausinnen);
innenButtons.add(hausaußen);
innenButtons.add(sicherheit);*/
pack();
setVisible(true);
}
public void clickBack1(){ // auf Back verschwindet alles was die Zeit über aufgebaut wurde nur noch //Randnavigation zu sehen
zweiteSchicht.remove(main);
innenButtons.setVisible(false);
main = new JPanel();
zweiteSchicht.add(main,BorderLayout.CENTER);
main.setBackground(Color.BLUE);
main.setVisible(true);
pack();
setVisible(true);
}
public void setMain(JPanel p) // hier wird über den Methodenaufruf aus der Klasse Innen heraus die Hauptseite // gesetzt
{ zweiteSchicht.add(main, BorderLayout.CENTER);
pack();
main.add(p);
pack();
p.setVisible(true);
pack();
setVisible(true);
}
// Ende Methoden
}
Klasse Innen
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Innen implements ActionListener{
private Raum[] raeume;
private JPanel p; // JPanel welches diese Klasse füllz
private GUI window; // setMain aus GUI setzt dann JPanel
// GUI Spezial
private JPanel buttons = new JPanel(new GridLayout(1,8));
private JButton add = new JButton("Neuer Raum");
private JButton[] clickRaum;
private boolean loadWindow; // um Teil im Fenster korrekt wiederzugeben, nur damit Backbutton korrekt funktioniert
public Innen(GUI window){
//raeume = new Raum[0];
// zu Test zwecken
raeume = new Raum[4];
raeume[0] = new Raum("Hause");
raeume[1] = new Raum("Bla");
raeume[2] = new Raum("Jaha");
raeume[3] = new Raum("Test");
//
clickRaum = new JButton[raeume.length];
for (int i =0; i< clickRaum.length;i++)
clickRaum[i] = new JButton(raeume[i].getName());
this.window = window;
loadWindow = false;
}
public void createWindow(){
if (loadWindow == false)
{
p = new JPanel(new BorderLayout());
p.add(buttons, BorderLayout.NORTH);
buttons.add(add);
add.addActionListener(this);
add.setActionCommand("add");
if (gefuellt <=7){
for (int i =0; i<6;i++)
{ if (i<clickRaum.length){
buttons.add(clickRaum[i]);}
else buttons.add(new JLabel());
}
}
loadWindow = true;
}
if (raeume.length >0){
p.add(raeume[0].makeWindow(), BorderLayout.CENTER); // zunächst mal geht es nur um die Darstellung des //ersten verfügbaren Raumes, makeWindow erzeugt ein // JPanel welches zurückgegeben wird
p.setVisible(true);
window.setVisible(true);}
window.pack();
window.setMain(p); // hier wird das gerade erzeugte JPanel ins Hauptfenster eingefügt
}
public void setUnseen(){ // dient auch nur dem Backbutton
loadWindow = false;
}
}
Klasse Raum
Java:
import java.awt.GridLayout;
import javax.swing.*;
public class Raum{
private String name;
private Geraet[] geraet;
public Raum(String name){
this.name = name;
geraet = new Geraet[1];
geraet[0] = new undimmedGeraet("undimmedGeraet"); // Einfügen nur um zu Testen obs geht
}
public String getName(){
return name;
}
public JPanel makeWindow(){
JPanel p = new JPanel(new GridLayout(geraet.length,1));
if (geraet.length >0){
for (int i =0; i< geraet.length;i++)
{
p.add(geraet[i].createOutline()); // und jetzt wird aus den einzelnen Geräten, wenns dann //mal mehrere gibt die spezielle Realisierung //rausgeholt werden und eingefügt gleiche Strategie //mit JPanel zurückgeben
p.setVisible(true);
}
}
return p;
}
}
Klasse undimmedGeraet Es existiert noch ein Interface was aber für die GUI denk ich nicht relevant ist
Java:
import java.awt.GridLayout;
import java.io.IOException;
import javax.swing.*;
public class undimmedGeraet implements Geraet {
private String name;
// Outline
private JButton on = new JButton("on");
private JButton off = new JButton("off");
private JLabel nameIn = new JLabel();
public undimmedGeraet(String name){
this.name = name;
nameIn.setText(name);
}
public String getName() {
// TODO Auto-generated method stub
return name;
}
public JPanel createOutline(){
JPanel x = new JPanel(new GridLayout(1,3));
x.add(nameIn);
x.add(on);
x.add(off);
x.setVisible(true);
return x;
}
}
Mmmh, ziemlich... umständlich. Aber wie heißt es so schön:
Warum einfach, wenn man es auch kompliziert machen kann?
Kommentier mal die Zeilen 44 bis 46 aus deiner Main-Gui aus:
[JAVA=44]
int frameWidth = 800;
int frameHeight = 600;
setPreferredSize(new Dimension(frameWidth, frameHeight));
[/code]
Somit wird sichergestellt, daß der Layoutmanager nicht an irgendwelche Größenangaben festhält.
Und setze folgenden Abschnitt
[JAVA=48]
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
[/code]
hinter pack() also nach Zeile 94.
[JAVA=94]
pack();
[/code]
Dann sollte sich das Fenster dem Inhalt anpassen. (Hoffe ich zumindest)
~"Premature optimization is the root of all evil" (so ungefähr hat D. Knuth das gesagt). Das stimmt aber so nicht. Durch verfrühte Optimierungen werden viele unschöne Dinge verursacht. Aber ich postuliere: Den größen Mist macht man, wenn man versucht, schnell einen Fehler zu beheben, dessen Ursache man nicht kennt.
Also... die ganzen pack()s und setVisible(true)s kannst du mal rausnehmen. Das einzige, was da EINmal gepackt und visble gemacht werden muss, ist der Frame. Und das ganz am Ende, wenn alles fertig gebaut ist.
Die Liste der GUI-Elemente in "GUI" sieht zwar auf den ersten Blick (und auch in bezug auf die Variablennamen und so) gar nicht sooo unübersichtlich aus, aber ob jetzt zu dem "innenButtons"-Panel 7,8 oder 9 buttons Hinzugefügt werden, und ob vielleicht irgendwo zwei Components an die gleiche Stelle von irgendeinem BorderLayout gelegt werden, kann man am gegebenen Code (praktisch natürlich schon, aber sehr) schlecht nachvollziehen. Sowas KANN(!) aber die beschriebenen Effekte verursachen.
Ansonsten würde ich dir dringend empfehlen, keine überflüssigen Instanzvariablen in der Klasse rumlungern zu haben. Es gibt nur sehr selten einen Grund, wirklich ein [c]private JPanel somePanel[/c] zu haben.
Ganz subjektiv (!!!) finde ich zum Aufbau von GUIs eine Aufteilung in (private) Methoden und ggf. Klassen ganz praktisch. Wenn man eine "Komplexere" GUI-Klasse hat, die vielleicht sogar eine eigene Entität in einem Datenmodell repräsentiert, kann man dafür eine eigene Klasse erstellen. Ansonten finde ich (nochmal: GANZ subjektiv) den Aufbau des GUIs in einer Hierarchie von Methodenaufrufen, die die grobe Aufteilung des GUI wiederspiegeln, am übersichtlichsten:
Java:
class GUI extends JFrame
{
void init()
{
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(createButtonPanel(), BorderLayout.WEST);
cp.add(createMainControlPanel(), BorderLayout.CENTER);
}
private JPanel createButtonPanel()
{
JPanel buttonPanel = new JPanel(new GridLayout(1,3)); // Wird nur hier lokal benötigt!
buttonPanel.add(someButton0);
buttonPanel.add(someButton1);
buttonPanel.add(someButton2);
return buttonPanel;
}
private JPanel createMainControlPanel()
{
JPanel mainControlPanel = new JPanel(new BorderLayout()); // Wird nur hier lokal benötigt!
mainControlPanel.add(createDefaultControlPanel(), BorderLayout.NORTH);
mainControlPanel.add(createOtherControlPanel(), BorderLayout.NORTH);
return mainControlPanel;
}
private JPanel createDefaultControlPanel() { .... }
private JPanel createOtherControlPanel() { .... }
...
}
Aber das kann man sehen, wie man will
EDIT: Der Fehler, der sich in diesem Pseudocode-Beispiel eingeschlichen hat, bleibt jetzt mal drin - als Beispiel dafür, dass man ihn recht schnell findet
Also, leider hab ich meinen ersten Poste iwie wieder gelöscht naja...
deshalb...
Vielen Dank also schon Mal nochmal
also wenn ich Zeile 44 bis 46 auskommentiere behebt sich das Problem zwar, aber leider
ist das Fenster immer nur gerade so groß wies unbedingt sein muss, damit alles sichtbar ist,
das wollte ich eigentlich nicht, deshalb löst das zwar das Problem aber halt nur naja nicht so ganz.
Zumindest ist das Bild mit Verschiebung der Positionierung auch jetzt in der Mitte
nunja sonst reduzieren von pack und setVisible hat auch nichts geändert...
Ich überdenke jetzt noch einmal mein Konzept und melde mich, falls ich was rausgefunden habe,
ich denke nämlich, dass das an dem Klasse"gewurschtel" liegt nun denn
lg
Schmuggler