DockingFrames

Status
Nicht offen für weitere Antworten.

PollerJava

Top Contributor
Hallo,

ich habe die DockingFrames von der Seite http://dock.javaforge.com/help.html verwendet.
Mein Problem ist jetzt, dass, wenn ich den JButton vom Programm unten drücke, ein neuer DockingFrame hinzugefügt werden soll (station.drop(new DefaultDockable( "Beschreibung" ), SplitDockProperty.EAST );
);
Das funktioniert auch aber das Problem ist, wenn ich die Größe des DockingFrames in East ändere, ein neuer JFrame in East erzeugt wird und nicht ein JFrame zu den bestehenden hinzugefügt wird,

Hat da jemmand eine Idee, wie man das machen kann,

Vielen Dank,

lg

(PS: Das Programm unten funktioniert)




Code:
package javaapplication15;

import bibliothek.gui.dock.station.split.SplitDockProperty;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import bibliothek.gui.DockController;
import bibliothek.gui.dock.station.SplitDockStation;
import bibliothek.*;
import bibliothek.extension.gui.dock.theme.EclipseTheme;
import bibliothek.gui.DockTheme;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.station.SplitDockStation;
import java.awt.event.ActionListener;
import javax.swing.JButton;

class Main implements ActionListener
{
    SplitDockStation station;
    
    public Main()
    {
     JButton button = new JButton("addPanel");
     button.setBounds(20,20,200,80);
     button.addActionListener(this);
     DockController controller = new DockController();
     controller.setSingleParentRemove( true );
     station = new SplitDockStation();
     DockTheme theme = new EclipseTheme();
     controller.setTheme( theme );
     controller.add(station);   
     controller.add( station );
     DefaultDockable dD = new DefaultDockable( "One");
     dD.getContentPane().add(button);
     station.drop(dD , SplitDockProperty.NORTH );
     station.drop( new DefaultDockable( "Two" ), SplitDockProperty.NORTH );
     station.drop( new DefaultDockable( "Three" ), SplitDockProperty.EAST );
     station.drop( new DefaultDockable( "Four" ), SplitDockProperty.EAST );


     JFrame frame = new JFrame();
     frame.add( station.getComponent() );

     frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
     frame.setBounds( 20, 20, 400, 400 );
     frame.setVisible( true );  
    }

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

    public void actionPerformed(ActionEvent e) {
        station.drop(new DefaultDockable( "Beschreibung" ), SplitDockProperty.EAST );
    }
}
 
B

Beni

Gast
Ich muss leider sagen, dass es dafür keine optimale Lösung gibt.

Diese Konstanten "EAST", "NORTH", ... mögen zwar implizieren, dass eine SplitDockStation mit dem BorderLayout verwandt wäre... dem ist aber nicht so. Der Benutzer kann diese Dockables ja frei bewegen, und spätestens wenn er z.B: "Three" nach rechts oben, und "Four" nach rechts unten setzt, macht die Position "EAST" nicht mehr viel Sinn.

Die SplitDockStation versucht deshalb folgendes: EAST beschreibt das Rechteck welches das neue Dockable gerne einnehmen würde. Falls sich dieses Rechteck zu mindestens 75% mit einem anderen Rechteck (eines Dockables) überschneidet, werden die Elemente aufeinandergestappelt - sonst nicht.

Wenn du weisst, mit welchem anderen Dockable das neue Dockable "vereinigt" (oder gestappelt) werden soll, kannst du aber folgendes Stücklein Code anwenden:

Code:
Dockable oldDockable = ...
Dockable newDockable = ...
SplitDockStation station = ...

// alte Position lesen
DockableProperty location = DockUtilities.getPropertyChain( station, oldDockable );

// neues Dockable absetzen
if( !station.drop( location, newDockable ) ){
  // failsave
  station.drop( newDockable );
}
 

PollerJava

Top Contributor
Vielen Dank Beni, das war genau das was ich brauche,
Ich hätte da noch ein paar Fragen und zwar, ist es möglich, ein Schließen- Kreuz auf den Tabs zu plazieren
und wie kann ich die Größe von EAST beim starten des Programms angeben (momentan ist bei mir der EAST- Bereich zu schmal).
Ist der Code von den ScreenShots eigentlich frei verfügbar?

Find die DockFrames echt super, ist ideal für viele Anwendungen.

Vielen Dank für Deine Hilfe,

lg
 
B

Beni

Gast
PollerJava hat gesagt.:
ist es möglich, ein Schließen- Kreuz auf den Tabs zu plazieren
Die einfachste Variante: verwende ein DockFrontend anstelle des DockControllers. Das wird dann ungefähr so aussehen:
Code:
SplitDockStation station = ...

// brauchen wir nichtmehr
// DockController controller = new DockController();
DockFrontend frontend = new DockFrontend();
frontend.addRoot( station, "station-id" );

DefaultDockable dock = new DefaultDockable( "One" );
frontend.add( dock, "one" );
frontend.setHideable( dock, true );

Die etwas komplizierte Variante ist eine eigene DockAction zu schreiben. Das würde dann ungefähr so gehen:
Code:
// die Annotation sagt, dass diese Action auf die Tabs
// kommt (funktioniert aber nur beim EclipseTheme).
@EclipseTabDockAction
public class CloseAction extends SimpleButtonAction{
  public CloseAction(){
    setText( "Close" );
    setIcon( ... );
  }

  public void action( Dockable dockable ){
    // schliessen
    dockable.getDockParent().drag( dockable );
  }
}

Und später:
Code:
DefaultDockable dock = new DefaultDockable( "one" );
CloseAction close = new CloseAction();
dock.setActionOffers( new DefaultDockActionSource( close ));


und wie kann ich die Größe von EAST beim starten des Programms angeben (momentan ist bei mir der EAST- Bereich zu schmal).
EAST selbst kannst du nicht ändern, aber eine neue Position generieren:
Code:
double size = ...
SplitDockProperty east = new SplitDockProperty( 1-size, 0, size, 1 );
(P.S. size ist besser < 0.75, ansonsten schlägt die 75%-Regel der SplitDockStation zu)

Ist der Code von den ScreenShots eigentlich frei verfügbar?
Nein. Das Programm von dem die Screenshots stammen entstand fast zeitgleich mit den DF, und wurde deshalb auch oft als Experimentierkaninchen missbraucht... *du willst den Code nicht sehen* :wink:

Der Code zu den Demonstrationen findest du aber im Repository (theoretisch gäbe es einen anonymen Zugang mit "User=anonymous", "pw=anon", praktisch scheint das mal mehr mal weniger gut zu funktionieren. Auf der download-Seite gibt es sonst einen checkout des gesammten Projektes, da sind die Demos auch drin).
 

PollerJava

Top Contributor
Hallo Beni,

ich hätte noch eine Frage und zwar wie bekomme ich das Schließen- Kreuz auf die DockingFrames, ich habs jetzt so ausprobiert, wie du geschrieben hast, funkt aber irgendwie noch nicht:
Könntest Du mir vielleicht schreiben, was ich da noch falsch mache?

Hier mein Programm

Code:
package javaapplication83;

import bibliothek.extension.gui.dock.theme.eclipse.EclipseTabDockAction;
import bibliothek.gui.DockFrontend;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockableProperty;
import bibliothek.gui.dock.action.DefaultDockActionSource;
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
import bibliothek.gui.dock.station.split.SplitDockProperty;
import bibliothek.gui.dock.util.DockUtilities;
import java.awt.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import bibliothek.gui.DockController;
import bibliothek.gui.dock.station.SplitDockStation;
import bibliothek.*;
import bibliothek.extension.gui.dock.theme.EclipseTheme;
import bibliothek.gui.DockTheme;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.station.SplitDockStation;
import java.awt.event.ActionListener;
import javax.swing.JButton;

class Main implements ActionListener
{
    SplitDockStation station;
    DefaultDockable testdD;
   
    public Main()
    {
     JButton button = new JButton("addPanel");
     button.setBounds(20,20,200,80);
     button.addActionListener(this);
     DockController controller = new DockController();
     controller.setSingleParentRemove( true );
     station = new SplitDockStation();
     DockTheme theme = new EclipseTheme();
     controller.setTheme( theme );
     controller.add(station);   
     controller.add( station );
     DefaultDockable dD = new DefaultDockable( "One");
     dD.getContentPane().add(button);
     station.drop(dD , SplitDockProperty.NORTH );
     station.drop( new DefaultDockable( "Two" ), SplitDockProperty.NORTH );
     testdD = new DefaultDockable( "Three" );
     station.drop(testdD, SplitDockProperty.EAST );
     station.drop( new DefaultDockable( "Four" ), SplitDockProperty.EAST );     
     CloseAction close = new CloseAction();
     testdD.setActionOffers( new DefaultDockActionSource( close )); 
     JFrame frame = new JFrame();
     frame.add( station.getComponent() );
     frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
     frame.setBounds( 20, 20, 400, 400 );
     frame.setVisible( true );  
    }

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

    public void actionPerformed(ActionEvent e) {
        DockableProperty location = DockUtilities.getPropertyChain( station, testdD);
        DefaultDockable testdD1 = new DefaultDockable("Test");
        if( !station.drop(testdD1,  location ) ){
            station.drop( testdD1 );
        } 
    }
}

@EclipseTabDockAction
class CloseAction extends SimpleButtonAction{
  public CloseAction(){
    setText( "Close" );
        try {
            setIcon(new ImageIcon(new URL("C:/Projekte/DMerstellung.png") ));
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
  }

  public void action( Dockable dockable ){
    // schliessen
    dockable.getDockParent().drag( dockable );
  }
}
 
B

Beni

Gast
Wenn das Dockable bereits angezeigt wird, dann hat "setActionOffers" keinen direkten Effekt mehr (wenn das Dockable einen neuen Parent bekommt, würde die Action aber auftauchen). Zuerst die DockActionSource verändern, dann das Dockable anzeigen.

Code:
     testdD = new DefaultDockable( "Three" );
     CloseAction close = new CloseAction();
     testdD.setActionOffers( new DefaultDockActionSource( close ));
     
     station.drop(testdD, SplitDockProperty.EAST );
     station.drop( new DefaultDockable( "Four" ), SplitDockProperty.EAST );

Das ist ein Bug den es in der nächsten Version nicht mehr gibt.
 

PollerJava

Top Contributor
Hallo Beni,

hätte noch eine Frage zu den DockingFrames,

Funktioniert so weit sehr gut, ich möchte aber jetzt, dass 2 DockingFrames untereinander in EAST sind, also genau das Gegenteil wie vorher,
Ist das irgendwie möglich, 2 DockingFrames untereinander zu plazieren?

Vielen Dank für Deine Antworten,

lg
 
B

Beni

Gast
Platziere das erste in EAST. Für das zweite musst du dann eine eigene Position anlegen. Das sollte dann etwa so gehen:
Code:
SplitDockProperty southeast = new SplitDockProperty( 0.75, 0.5, 0.25, 0.5 );
station.drop( dockable, southeast );

[Edit: oder wenn das gleich beim Start des Programmes so sein soll, benutze ein SplitDockGrid: da werden die Koordinaten der Dockables einmal angegeben, und später so gut wie möglich umgesetzt. Auf der Homepage gäbe es ein Beispiel, aber da JavaForge gerade umgebaut wird habe ich es jetzt mal rauskopiert:

Code:
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JPanel;

import bibliothek.gui.DockFrontend;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DefaultDockable;
import bibliothek.gui.dock.station.SplitDockStation;
import bibliothek.gui.dock.station.split.SplitDockGrid;

public class Dock {
	public static void main( String[] args ){
		JFrame frame = new JFrame( "Demo" );
		DockFrontend frontend = new DockFrontend( frame );
		SplitDockStation station = new SplitDockStation();
		
		frame.add( station.getComponent() );
		frontend.addRoot( station, "station" );
		
// Das hier wäre für dich wichtig:
		SplitDockGrid grid = new SplitDockGrid();
		grid.addDockable( 0, 0, 1, 1, createDockable( "Red", Color.RED ) );
		grid.addDockable( 0, 1, 1, 1, createDockable( "Green", Color.GREEN ) );
		grid.addDockable( 1, 0, 1, 1, createDockable( "Blue", Color.BLUE ) );
		grid.addDockable( 1, 1, 1, 1, createDockable( "Yellow", Color.YELLOW ) );
		station.dropTree( grid.toTree() );
// ab hier ist es nicht mehr wichtig
		
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setBounds( 20, 20, 400, 400 );
		frame.setVisible( true );
	}
	
	public static Dockable createDockable( String title, Color color ) {
		JPanel panel = new JPanel();
		panel.setOpaque( true );
		panel.setBackground( color );
		return new DefaultDockable( panel, title );
	}
}

]
 

PollerJava

Top Contributor
Hallo Beni,

Ich hätte noch eine Frage zu den DockingFrames und zwar wenn ich mehrere

Code:
DefaultDockable pV = new DefaultDockable()

hinzufüge (quasi wenn ich mehrere Tabs auf einem DockingFrame habe)

Code:
DockableProperty location = DockUtilities.getPropertyChain( station, dummy);

station.drop(pV);

kann ich dann irgenwie bestimmen, welcher DefaultDockable gerade im Vordergrund ist, also den Focus hat??

lg und vielen dank für Deine Antworten,
 
B

Beni

Gast
"setFocusedDockable" sollte helfen:
Code:
DockController controller = ...
controller.setFocusedDockable( einDockable, true );
 

PollerJava

Top Contributor
Ahhh. tut mir leid, ich hab die Frage falsch formuliert,

wenn ich mehrere Tabs habe, wie könnte ich da in Erfahrung bringen, welcher gerade den Fokus hat also welcher gerade im Vordergrund ist,

vielen Dank
 
B

Beni

Gast
Zwei Varianten: "DockController#getFocusedDockable()", und alle DockStationen haben eine Methode "getFrontDockable", welche das selektierte Dockable (falls vorhanden) zurückgibt.
 

PollerJava

Top Contributor
Vielen dank!!

eine kleine Frage hätte ich noch und zwar habe ich intern ein JPanel "mainPanel" und diese JPanel geben ich auf das DefaultDockable:

Code:
 DefaultDockable pV = new DefaultDockable();
 pV.getContentPane().add(mainPanel);

und dieses DefaultDockable setze ich dann, wo ich es haben will:

Code:
DockableProperty location = DockUtilities.getPropertyChain( station, dummy);
                if( !station.drop(pV,  location ) ) {
                    station.drop(pV);


Wenn ich jetzt z.B.: 3 Tabs auf einer "location" habe und zwischen diesen Tabs umschalte, dann möchte ich immer, dann
"mainPanel" eine Referenz auf das JPanel im DefaultDockable hat, welches gerade im Vordergrund ist,

Ist das irgendwie möglich zu dedektieren, dass mit der Maus zwischen den Tabs hin und hergeschalten wird und ich dann eben meine Referenz JPanel mainPanel immer auf das aktuelle JPanel im DefaultDockable setze,

Vielen Dank,

lg
 
B

Beni

Gast
Ich bin mir jetzt nicht ganz sicher was du machen willst, aber ich denke folgendes wird dir helfen:
Du kannst dem DockController einen DockControllerListener hinzufügen. Der DockControllerListener wird über "dockableFocused" informiert, wenn ein Dockable den Fokus gewinnt. Und wenn man auf so ein Tab klickt, gewinnt das angeklickte Dockable meistens den Fokus.
 

PollerJava

Top Contributor
ist es irgenwie möglich, von EAST herauszufinden, welcher Tab im Vordergrund ist,

mit DockController#getFocusedDockable() bekomme ich ja den Dockable(), welcher allgemein (von EAST, WEST, NORTH und SOUTH) den Fokus hat, ich möchte aber nur den von EAST haben,

Ist das möglich?

lg
 
B

Beni

Gast
Nein, da EAST, WEST, etc. nur beim Hinzufügen eine Bedeutung haben. Der Benutzer kann das ja später auseinanderreissen...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
P DockingFrames schließen Allgemeine Java-Themen 2

Ähnliche Java Themen


Oben