JTable im Fenster anzeigen - Per NullLayout gehts es nicht, per BorderLayout schon

Hi,

Ich habe soeben erfolgreich meine JTable meinem Fenster hinzugefügt. Das ganze habe ich mithilfe eines Beispiels umgesetzt. Allerdings wird dort das BorderLayout verwendet, jedoch möchte ich das Nulllayout verwenden.
Das Problem ist nun, sobald ich das Nulllayout einstelle, meine JTable plötzlich nicht mehr im Fenster angezeigt wird (Location habe ich gesetzt!). Ich weiß nicht wo der Fehler liegt…

Ich poste hier am besten mal beide Varianten, einmal die funktionierende und einmal die nicht funktionierende (ist nur die View des Programms, also ohne main()).
Unterschieden tuen sich die beiden Varianten nur darin, dass ich in der einen eben den LayoutManager des Frame und Panel nicht explizit auf null setze.

Die nicht funktionierende Variante mit dem Nulllayout:

package View;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import Controller.Controller;

public class ViewHauptprogramm extends View {
	
	private JFrame frameHauptprogramm;
	private JPanel panelHauptprogramm;
	private JTable table;
	private DefaultTableModel model;
	
	public ViewHauptprogramm(Controller controller) {
		this.controller = controller;
		
		frameHauptprogramm = new JFrame("FTP-Programm");
		frameHauptprogramm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frameHauptprogramm.setSize(800, 800);
		frameHauptprogramm.setLocationRelativeTo(null);
		panelHauptprogramm = new JPanel();
		frameHauptprogramm.add(panelHauptprogramm);
		frameHauptprogramm.setLayout(null);
		panelHauptprogramm.setLayout(null);
		
		String[] titles = new String[]{ "Dateiname", "Dateigroeße", "Downloads", "Uploader" };
 
		model = new DefaultTableModel(titles, 0);
 		table = new JTable(model);
		table.setBounds(10, 10, 500, 500);
		panelHauptprogramm.add(new JScrollPane(table));
		table.setVisible(true);

		frameHauptprogramm.setVisible(true);
	}

}

Die funktionierende Variante mit dem BorderLayout (Standart-Layout, habs nirgends explizit gesetzt):

package View;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import Controller.Controller;

public class ViewHauptprogramm extends View {
	
	private JFrame frameHauptprogramm;
	private JPanel panelHauptprogramm;
	private JTable table;
	private DefaultTableModel model;
	
	public ViewHauptprogramm(Controller controller) {
		this.controller = controller;
		
		frameHauptprogramm = new JFrame("FTP-Programm");
		frameHauptprogramm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frameHauptprogramm.setSize(800, 800);
		frameHauptprogramm.setLocationRelativeTo(null);
		panelHauptprogramm = new JPanel();
		frameHauptprogramm.add(panelHauptprogramm);
		//frameHauptprogramm.setLayout(null);                                                       Auskommentiert!
		//panelHauptprogramm.setLayout(null);                                                       Auskommentiert!
		
		String[] titles = new String[]{ "Dateiname", "Dateigroeße", "Downloads", "Uploader" };
 
		model = new DefaultTableModel(titles, 0);
 		table = new JTable(model);
		table.setBounds(10, 10, 500, 500);
		panelHauptprogramm.add(new JScrollPane(table));
		table.setVisible(true);

		frameHauptprogramm.setVisible(true);
	}

}

Dann benutz BorderLayout und fertig. Man sollte nie “NullLayout” nehmen. Denn wenn man die Fenstergroesse aendert dann sieht es einfach nur ******* aus.

Es muss aber doch per NullLayout gehen? O.o

Ja aber ich werde es dir nicht verraten sorry. Denn das verstoesst gegen meine Prinzipien. Warum brauchst du denn ausgerechnet Nulllayout?

Die Tabelle brauchst du nicht explizit auf visible(true) setzen, kann also weggelassen werden:
table.setVisible(true);

Im NULL-Layout musst du die Grössenangabe nicht auf die Tabelle sondern auf das Scrollpane setzen. Beim BorderLayout wird das standardmäßig in den CENTER-Bereich gelegt und nimmt deshalb den komplett verfügbaren Platz ein. Aber NULL-Layout ist wirklich nicht zu empfehlen.

@groggy
wenn du dich bewußt einer Antwort verschließt, dann lieber das Thema ganz offen lassen,
damit leichter von anderen gefunden (Liste der unbeantworteten Themen)

so etwas fragwürdig,
Hinweise gegen NullLayout sind gut, höhere Aktionen schlecht

Gut sehe ich ein…
aber was ich nicht verstehe ist,warun er nicht einfach Border nimmt. Anscheinend gibt es keinen richtigen Grund warum er NullLayout nimmt.

Bitteschön, einmal mit einem NullLayoutManager. Wenn du das unbedingt so machen willst bitte:


import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class NullLayout
{
	JFrame frameHauptprogramm;
	JPanel panelHauptprogramm;
	JTable table;
	DefaultTableModel model;
	JScrollPane scrollPane;
	
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					new NullLayout();
				}
			});
	}
	
	public  NullLayout()
	{
		
		frameHauptprogramm = new JFrame("FTP-Programm");
		frameHauptprogramm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frameHauptprogramm.setSize(800, 800);
		frameHauptprogramm.setLocationRelativeTo(null);
		panelHauptprogramm = new JPanel();
		frameHauptprogramm.add(panelHauptprogramm);
		frameHauptprogramm.setLayout(new LayoutManager()
			{
				
				@Override
				public void addLayoutComponent(String name, Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void removeLayoutComponent(Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public Dimension preferredLayoutSize(Container parent)
				{
					return new Dimension(500, 500);
				}
				
				@Override
				public Dimension minimumLayoutSize(Container parent)
				{
					// TODO Auto-generated method stub
					return new Dimension(10,10);
				}
				
				@Override
				public void layoutContainer(Container parent)
				{
					Rectangle r = frameHauptprogramm.getBounds();
					panelHauptprogramm.setBounds(0,0, r.width, r.height);
				}
				
			});
		panelHauptprogramm.setLayout(new LayoutManager()
			{
				
				@Override
				public void addLayoutComponent(String name, Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void removeLayoutComponent(Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public Dimension preferredLayoutSize(Container parent)
				{
					return new Dimension(500, 500);
				}
				
				@Override
				public Dimension minimumLayoutSize(Container parent)
				{
					// TODO Auto-generated method stub
					return new Dimension(10,10);
				}
				
				@Override
				public void layoutContainer(Container parent)
				{
					scrollPane.setBounds(0, 0, 500, 500);
				}
			});
		
		String[] titles = new String[] { "Dateiname", "Dateigroeße", "Downloads", "Uploader" };
		
		model = new DefaultTableModel(titles, 0);
		table = new JTable(model);
		scrollPane = new JScrollPane(table);
		panelHauptprogramm.add(scrollPane);
		
		frameHauptprogramm.pack();
		frameHauptprogramm.setVisible(true);
	}
	
}

[QUOTE=bERt0r]Bitteschön, einmal mit einem NullLayoutManager. Wenn du das unbedingt so machen willst bitte:


import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class NullLayout
{
	JFrame frameHauptprogramm;
	JPanel panelHauptprogramm;
	JTable table;
	DefaultTableModel model;
	JScrollPane scrollPane;
	
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
			{
				@Override
				public void run()
				{
					new NullLayout();
				}
			});
	}
	
	public  NullLayout()
	{
		
		frameHauptprogramm = new JFrame("FTP-Programm");
		frameHauptprogramm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frameHauptprogramm.setSize(800, 800);
		frameHauptprogramm.setLocationRelativeTo(null);
		panelHauptprogramm = new JPanel();
		frameHauptprogramm.add(panelHauptprogramm);
		frameHauptprogramm.setLayout(new LayoutManager()
			{
				
				@Override
				public void addLayoutComponent(String name, Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void removeLayoutComponent(Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public Dimension preferredLayoutSize(Container parent)
				{
					return new Dimension(500, 500);
				}
				
				@Override
				public Dimension minimumLayoutSize(Container parent)
				{
					// TODO Auto-generated method stub
					return new Dimension(10,10);
				}
				
				@Override
				public void layoutContainer(Container parent)
				{
					Rectangle r = frameHauptprogramm.getBounds();
					panelHauptprogramm.setBounds(0,0, r.width, r.height);
				}
				
			});
		panelHauptprogramm.setLayout(new LayoutManager()
			{
				
				@Override
				public void addLayoutComponent(String name, Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void removeLayoutComponent(Component comp)
				{
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public Dimension preferredLayoutSize(Container parent)
				{
					return new Dimension(500, 500);
				}
				
				@Override
				public Dimension minimumLayoutSize(Container parent)
				{
					// TODO Auto-generated method stub
					return new Dimension(10,10);
				}
				
				@Override
				public void layoutContainer(Container parent)
				{
					scrollPane.setBounds(0, 0, 500, 500);
				}
			});
		
		String[] titles = new String[] { "Dateiname", "Dateigroeße", "Downloads", "Uploader" };
		
		model = new DefaultTableModel(titles, 0);
		table = new JTable(model);
		scrollPane = new JScrollPane(table);
		panelHauptprogramm.add(scrollPane);
		
		frameHauptprogramm.pack();
		frameHauptprogramm.setVisible(true);
	}
	
}
```[/QUOTE]


Danke, das funktioniert zwar, aber geht das nicht etwas einfacher? 
In deinem Beispiel schreibst du doch deinen eigenen LayoutManager, wenn ich das richtig verstehe?! Ich hatte jetzt eher etwas in der Richtung erwartet, dass man einfach dasLayout vom frame und/oder panel auf null setzt

frameHauptprogramm.setLayout(null);
panelHauptprogramm.setLayout(null);


und dann weiter unten im Code die Tabelle erstellt und diese dann dem panel hinzufügt und direkt die entsprechenden Koordinaten und Größe per  ```setLocation(int a, int b, int x, int y)``` übergibt. (Hatte ich ja auch erst so versucht, das ging aber nicht).

So jedenfalls ist das doch der übliche/einfachere Weg wenn ich z.B. nur 1 Button per Nulllayout in meiner GUI setzten will?! Da schreib ich ja auch nicht meinen komplett eigenen LayutManager...
Oder ist das hier speziell bei der JTable notwendig?

genauer nachgeschaut ist auch das Programm von bERt0r kaum anders als Schikane zu interpretieren,
ich frage mich was hier los ist…


in deinem Code vom ersten Posting sind mit View und Controller nicht benötigte unbekannte Klassen enthalten,

ansonsten musst du nur auf konsequente Einhaltung der null-Layout-Regeln achten,

  • wenn frameHauptprogramm null-Layout hat muss die eingefügte Komponente panelHauptprogramm Bounds haben,
    bei dir? Fehlanzeige
  • wenn panelHauptprogramm null-Layout hat muss die eingefügte Komponente ScrollPane Bounds haben,
    bei dir? Fehlanzeige

die JTable braucht keine Bounds, das ScrollPane weiß da intern was zu tun ist,
die Bounds vererben sich nicht nach oben hin, jede Komponente muss für sich beschrieben werden

edit: man kann schließlich auch mehrere Panel auf den Bildschirm verteilen wollen, die brauchen alle eigene Angaben,

setBounds() gilt auch jeweils nur relativ,
wenn du absolut auf die Hauptfläche platzieren willst, dann ist das Zwischenpanel panelHauptprogramm fragwürdig,
deren 10,10 und weitere 10,10 auf das ScrollPane in meinem Beispiel wird jedenfalls zu 20,20


ein setVisible(true) auf das JFrame reicht, alles andere im Moment ohne Auswirkung,
schrieb Camino alles auch schon mehr oder weniger

...

        table = new JTable(model);
        JScrollPane p = new JScrollPane(table);
        panelHauptprogramm.add(p);
        
        p.setBounds(10, 10, 500, 500);
        panelHauptprogramm.setBounds(10, 10, 600, 600);
        frameHauptprogramm.setVisible(true);

@ SlaterB:

Danke, so in etwa hatte ich mir das Codemäßig vorgestellt :wink:

Jetzt wo alles geklärt ist, können wir noch gerne etwas OT werden:

LayoutManager hören sich zunächst ganz toll an, können aber je komplexer die GUI wird eine Wissenschaft für sich werden. Eine komplexe (dafür statische) GUI, die ich vielleicht in 1 Stunde fertig habe, würde mit LayoutManagern sicherlich Stunden dauern, falls ich überhaupt soweit käme. Und selbst dann stört es mich als Programmier extrem, dass ich keine absolute Kontrolle über die absoluten Positionen der Komponenten habe. Und wenn ich diese nicht habe, dann sieht meine GUI niemals genauso so aus, wie ich sie eigentlich haben will, sondern immer nur annähernd.

Das stimmt natürlich, dass es mit den fixen Werten (Positition und Grösse) schnell gemacht ist. Aber die LayoutManager sehen nur am Anfang etwas kompliziert aus, mit der Zeit gewöhnt man sich aber dran. Wenn die GUI aufwändiger und komplexer sind, muss man auch mal verschiedene LayoutManager nehmen und verschachteln, bis man das gewünschte Ergebnis bekommt. Der Vorteil dabei ist, dass wenn sich die Grösse deines Frames ändert, sich auch dein Layout anpassen kann. Das kriegst du mit dem Null-Layout nur schwer hin.

Danke, das funktioniert zwar, aber geht das nicht etwas einfacher?

Ja das geht einfacher indem man einen vorgefertigten Layoutmanager verwendet.

Alles was der Code tut, ist dein Panel so groß wie den Frame bzw. dein ScrollPane so groß wie dein Panel zu machen. Das geht mit setLayout(null) nicht. Wenn du alle Komponenten absolut einstellen willst und volle Kontrolle benötigst musst du dir einen eigenen Layoutmanager schreiben wie in dem Beispiel. Dass das nicht ganz so einfach ist liegt nunmal daran dass die Sache nicht trivial ist. Der übliche Weg ist nunmal einen Layoutmanager zu verwenden. NullLayout kannst du vielleicht bei einem Prototypen benutzen aber für ein Programm ist es absolut ungeeignet. Es gibt auch Layoutmanager wie XYLayout die auch absolute Positionseingaben unterstützen und mit denen die Sache dann funktioniert, aber da muss man eben auch erst wie lernen wie man die Klasse benutzt.

Werbung in eigener Sache:

Und das ist auch schon der einzige Vorteil, oder?
Das kann man doch ganz einfach dadurch beheben, indem man die Fenstergröße im laufenden Betrieb nicht mehr ändern kann.

Ja genau -.- @!#§?
Wie wuerde es dir gefallen wenn Firefox oder Chrome einfach das Fenster auf 400*300 setzen und das wars?

Das ist nicht der einzige nachteil von setLayotu(null). Guck mal hier: http://www.leepoint.net/notes-java/GUI/layouts/nulllayout.html

Gibt halt verschieden grosse Bildschirme und Auflösungen…

das genannte Beispiel ist aber ziemlich einfälltig,
dass man für Komponenten direkt hintereinander ein Layout verwenden kann, darauf kommen selbst null-Layouter oftmals,

im Zweifel geht es selbst mit strengen null-Layout, selber Hilfen nachgebaut:
die Komponenten in eine Liste, per Schleife das Hinzufügen und die meiste Berechnung, nur die Breiten vielleicht noch zu merken,
bei Textfeldern auf normalen Weg auch nicht ganz simpel,

ein Koordinatensystem mit Beschriftung 0, 1, 2, 3 malt man ja auch nicht absolut sondern mit bestimmter Breite von bestimmten Punkt aus, dann ebenso halbwegs zu verschieben,


auf dem Gebiet geht ein Angriff etwas fehl,
besser wäre das wahre Schlachtfeld: 5 Komponenten nichttrivial im Raum anordnen,

allerdings muss man so ein Beispiel auch erstmal finden, die meisten GUIs wie wahllos aus dem Netz

sehen doch recht regelmäßig aus, und da lohnt sich durchaus fast immer Ordnung in Reih und Glied,

insofern der Link wieder näher an der Wahrheit, aber für so eine Liste geht wohl keiner zum null-Layout, @Jack159 , was sagst du? :wink:

Meiner Meinung nach aber eines der staerksten…

@Slater ist das jetzt dein ernst oder trollst du? Ich bin mir nicht sicher was du mit Angriffen/Schlachtfeld/Koordinatensystem eigentlich meinst aber sogar dein Bild hat als Titel “Preview”. Wenn man zur Demonstration einer Gui mit dem GUIBuilder + NullLayout einen Wegwerfprototyp bastelt ist da ja nix dagegen einzuwenden. Für ein lauffähiges Programm ist NullLayout nichts als Schikane. Man muss alles selber einstellen und übersieht zwangsläufig Fehler die das ganze Layout kippen. Nochdazu ist es absolut unflexibel auf etwaige Änderungen der Laufzeitumgebung. Was wenn ein Sehbehinderter, der extra große Schrift eingestellt hat dein Nulllayout Programm ausführen will. Dann sind die Buttons plötzlich zu klein für die Schrift.