# Divider zentrieren bei Gui Start



## tokitok (14. Jan 2009)

Hallo,

ich habe eine JSplitPane, dessen Divider immer in der Mitte sein soll.

Mit einem HierarchyBoundsListener funktioniert das auch ganz gut, sobald der Benutzer JFrame verändert.

Nur beim Start der GUI hängt der Divider ganz links. In der init Methode bleibt der Befehl setDividerLocation(0.5) ohne Wirkung. Ich denke das liegt daran, dass die Größe des JSplitPanes erst später steht.

Kann mir da jemand helfen?

Gruß,
To


----------



## André Uhres (14. Jan 2009)

tokitok hat gesagt.:
			
		

> Ich denke das liegt daran, dass die Größe des JSplitPanes erst später steht.


Das klingt nach einem Job für SwingUtilities.invokeLater(java.lang.Runnable).


----------



## tokitok (15. Jan 2009)

```
Runnable runnable = new Runnable(){
		   public void run() {
			   splitPan.setDividerLocation(0.5);			   
		   }
	   };
	   javax.swing.SwingUtilities.invokeLater(runnable);
```

Das hat das Problem leider nicht behoben..


----------



## André Uhres (15. Jan 2009)

Hast du die GUI auch auf dem EventDispatchThread gestartet?


----------



## tokitok (15. Jan 2009)

hatte ich nicht.

Aber jetzt starte ich die GUI auch über SwingUtilities.invokeLater

Das Problem ist aber leider immer noch dasselbe..


----------



## André Uhres (15. Jan 2009)

Du musst dich wohl irren, denn wenn wir die GUI Initialisierung und Sichtbarmachung auf den EventDispatchThread schicken, und danach setDividerLocation, dann haben wir threadsicher programmiert. Du machst einfach ein kurzes, selbständiges und kompilierbares Beispiel, um es selbst zu sehen.


----------



## Ebenius (15. Jan 2009)

tokitok, kannst Du mal testweise die beiden Komponenten von dem SplitPane runter nehmen und statt dessen new JButton("button1"); und new JButton("button2"); auf das SplitPane setzen? Passiert dann das gleiche Problem?

Ich habe nur den ganz leisen Verdacht, dass es irgendwas mit preferred sizes oder minimum sizes oder sowas zu tun hat. Hab zwar schon lange kein SplitPane mehr verwendet, aber ich erinnere mich daran, dass diese Komponente als weniger gelungen bezeichnet werden muss.

Ebenius


----------



## André Uhres (16. Jan 2009)

Splitpane respektiert in der Regel immer die "divider location" beim Startup.
Aber sobald der Benutzer den Divider verschiebt, kann es sein, 
daß es nicht mehr möglich ist, zu der programmatisch angegebenen Position zurückzuschieben
(wegen der Grösse der enthaltenen Komponenten).


----------



## Ebenius (16. Jan 2009)

Unsinn. Guckst Du: 
	
	
	
	





```
final JSplitPane splitPane = new JSplitPane();
splitPane.setPreferredSize(new Dimension(400, 400));
splitPane.setLeftComponent(new JButton());
splitPane.setRightComponent(new JButton());
splitPane.setDividerLocation(0.5);

final JFrame f = new JFrame("Transparent Text Pane");
f.setContentPane(splitPane);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
```







// EDIT: Die API-Doc sagt dazu übrigens:  





> This method immediately changes the size of the split pane based on its current size. If the split pane is not correctly realized and on screen, this method will have no effect (new divider location will become (current size * proportionalLocation) which is 0).



tokitok, probier doch mal, ob setResizeWeight(0.5) Dich schon weiter bringt.

Ebenius


----------



## André Uhres (16. Jan 2009)

Das Problem, das du jetzt zeigst, haben wir schon besprochen. Die Lösung findest du oben.


----------



## Ebenius (16. Jan 2009)

André Uhres hat gesagt.:
			
		

> Das Problem, das du jetzt zeigst, haben wir schon besprochen. Die Lösung findest du oben.



Verstehe ich nicht.


----------



## André Uhres (16. Jan 2009)

Lies bitte den Thread nochmal von Anfang an und versuch die Vorschläge in dein Beispiel einzubauen.


----------



## Ebenius (16. Jan 2009)

André, ich entwickle seit 7 Jahren beinahe täglich Swing-GUIs beruflich. Natürlich habe ich setDividerLocation auch im EventListenerThread probiert, bevor ich gepostet habe. Das hilft nix. Es sei denn man fügt ... 
	
	
	
	





```
SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    splitPane.setDividerLocation(0.5);
  }
}
```
 ... so ein, dass das SplitPane bereits displayable und visible ist, wenn setDividerLocation(0.5) aufgerufen wird.

Konkret heißt das in meinem Code-Beispiel, dass es nicht funktioniert, wenn ich den Code-Block in Zeile 2-7 einfüge. Wenn ich ihn in Zeile >8 einfüge klappts. Woran das liegt liest Du in oben erwähnter API-Doc nach.

//EDIT: 





> Splitpane respektiert in der Regel immer die "divider location" beim Startup.



Und genau dieser Ausspruch ist Unsinn, wenn Du in die API-Doc guckst!

Ebenius


----------



## André Uhres (16. Jan 2009)

http://www.java-forum.org/de/viewtopic.php?p=484528#484528
Sorry meinte diesen:
http://www.java-forum.org/de/viewtopic.php?p=484392#484392


----------



## Ebenius (16. Jan 2009)

Oh, Du meinst mit "Sichtbarmachung" nicht "setVisible()" (was ja sichtbar heißt), sondern "isShowing() == true"? Bist Du sicher, dass der Thread Opener das so verstanden hat? Ich verstand das so nicht. Sorry.


----------



## André Uhres (16. Jan 2009)

Selbstverständlich meinte ich mit 'Sichtbarmachung' "setVisible(true)" (eine andere Möglichkeit gibt es auch nicht).


----------



## Ebenius (16. Jan 2009)

Damn it, wir reden aneinander vorbei.  Egal.

tokitok, das SplitPane muss angezeigt werden (isShowing == true), wenn man setDividerLocation() benutzt. Entweder baust Du Deine GUI so auf, dass erst das Fenster sichtbar gemacht wird und danach setDividerLocation() für das SplitPane benutzt wird. Oder Du nutzt set setResizeWeight(double), sofern das für Dich passt.

Ebenius


----------



## André Uhres (16. Jan 2009)

Ebenius hat gesagt.:
			
		

> wir reden aneinander vorbei


Nimm einfach den Code oben von tokitok und bau ihn ein, etwa so:

```
/*
 * SwingBasicDemo.java
 */

import java.awt.*;
import javax.swing.*;

public class SwingBasicDemo extends JFrame {

    private javax.swing.JSplitPane splitPan;

    public SwingBasicDemo() {
        initComponents();
        Runnable runnable = new Runnable() {

            public void run() {
                splitPan.setDividerLocation(0.5);
            }
        };
        javax.swing.SwingUtilities.invokeLater(runnable);
    }

    private void initComponents() {
        splitPan = new JSplitPane();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        splitPan.setPreferredSize(new Dimension(400, 300));
        getContentPane().add(splitPan, BorderLayout.CENTER);
        pack();
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            @Override
            public void run() {
                new SwingBasicDemo().setVisible(true);
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }
}
```


----------



## tokitok (17. Jan 2009)

Hallo,

also, ich habe jetzt dank Eurer Informationen was hinbekommen, das funktioniert.
Das SplitPane ist auf einem Panel, welches erst angezeigt wird, nach dem ein bestimmter button gedrückt wurde. Also zentriere ich einfach danach den Divider und schon funktionierts.
Allerdings habe ich das jetzt aus der aufrufenden Klasse heraus gemacht, nicht im meinem "ComparePanel" = SplitPane, was ich etwas unschön finde..

Danke Euch,
To


----------



## Ebenius (17. Jan 2009)

tokitok hat gesagt.:
			
		

> Allerdings habe ich das jetzt aus der aufrufenden Klasse heraus gemacht, nicht im meinem "ComparePanel" = SplitPane, was ich etwas unschön finde..



Kann ich verstehen. setResizeWeight(0.5) hilft Dir nicht?


----------



## tokitok (17. Jan 2009)

Nö, das hat leider auch nichts gebracht.

Kann man denn nicht einen Event abfangen der eintritt, wenn die Komponente Visible wird?


----------



## Ebenius (17. Jan 2009)

Hab noch ein bisschen rumprobiert.  Das da funktioniert, wenn das SplitPane tatsächlich in der GUI die richtige Größe bekommt (hängt also von den Layout Managern der Parent Panels ab): 
	
	
	
	





```
final JSplitPane splitPane = new JSplitPane();
splitPane.setLeftComponent(new JButton("Extra extra huge"));
splitPane.setRightComponent(new JButton("small"));
splitPane.setPreferredSize(new Dimension(400, 400));
splitPane.setSize(new Dimension(400, 400));
splitPane.setDividerLocation(0.5);
splitPane.validate();

JFrame.setDefaultLookAndFeelDecorated(true);
final JFrame f = new JFrame("Split Pane Fun");
f.setContentPane(splitPane);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
```

Ebenius


----------

