2011-04-15 126 views
3

我有兩個JFrame開放。我有窗口B產生在窗口A的右邊,緊貼窗口A的右邊緣。我希望它堅持並移動窗口A.我怎樣才能做到這一點?如何在Swing中將一個窗口連接到另一個窗口?

+0

如果你有兩個幀,他們爲什麼停靠在一起?創建一個框架的想法是,它們可以獨立使用。另外,作爲一般規則應用程序應該只有一個JFrame。如果需要其他窗口,則應使用JDialog。 – camickr 2011-04-15 23:52:01

回答

0
+0

我想你已經誤解了OP的想法。 'JInternalFrame'放置一個小僞裝窗口_另一個窗口;它不會將兩個窗口綁在一起。 – Pops 2011-04-15 21:15:52

+0

我建議JInternalFrame,當他說'我希望它堅持並移動窗口A.' – alibenmessaoud 2011-04-15 21:28:52

+0

»窗口B產生到窗口A的右側,緊貼窗口A的右邊緣« - 沒有*內部*有;它是一個單獨的窗口,在窗口A之外。 – Joey 2011-04-15 21:54:50

3

更看我做了一個叫DockingManager類,可以讓你停靠對話框和框架僞Winamp的風格

它也可以讓你做出不同的集羣,並設置磁水平來選擇哪一幀拖動其他)

package com.gsteren.docking; 

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Map; 
import java.util.Set; 

import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.Timer; 
import javax.swing.UIManager; 

public class DockingManager { 

    public static enum DockingMode { 
     EAST, WEST, NORTH, SOUTH, NONE 
    } 

    int magneticDistance = 20; 

    public static Map<Component, DockingApplier> monitoredComponents = new HashMap<Component, DockingApplier>(); 

    /** 
    * Para saber cual es el último Component movido por el usuario. 
    */ 
    private static DockingApplier focusedApplier; 

    public void registerComponent(Component component) { 
     this.registerComponent(component, 1); 
    } 

    public void registerComponent(Component component, int magneticLevel) { 
     DockingApplier applier = new DockingApplier(component, magneticLevel); 
     monitoredComponents.put(component, applier); 
    } 

    /** 
    * Indica el grupo completo de componentes pegados al que pertenece un 
    * componente. 
    * 
    * @author Guillermo 
    * 
    */ 
    protected class DockingApplierCluster { 
     Set<DockingApplier> appliers = new HashSet<DockingApplier>(); 
     DockingApplier leader = null; 

     public DockingApplierCluster(DockingApplier applier) { 
      this.addToCluster(applier); 
     } 

     public DockingApplierCluster(Set<DockingApplier> appliers) { 
      for (DockingApplier applier : appliers) { 
       this.addToCluster(applier); 
      } 
     } 

     public void addToCluster(DockingApplier applier) { 
      appliers.add(applier); 
      applier.setCluster(this); 
      if (null == leader || applier.getMagneticLevel() < leader.getMagneticLevel()) { 
       this.setLeader(applier); 
      } 
     } 

     public int getSize() { 
      return getAppliers().size(); 
     } 

     public void mergeCluster(DockingApplierCluster cluster) { 
      DockingApplierCluster bigCluster; 
      DockingApplierCluster smallCluster; 
      if (getSize() > cluster.getSize()) { 
       bigCluster = this; 
       smallCluster = cluster; 
      } else { 
       bigCluster = cluster; 
       smallCluster = this; 
      } 
      for (DockingApplier applier : smallCluster.getAppliers()) { 
       bigCluster.addToCluster(applier); 
      } 

     } 

     public Set<DockingApplier> getAppliers() { 
      return this.appliers; 
     } 

     /** 
     * @return the leader 
     */ 
     public DockingApplier getLeader() { 
      return leader; 
     } 

     /** 
     * @param leader 
     *   the leader to set 
     */ 
     public void setLeader(DockingApplier leader) { 
      this.leader = leader; 
     } 

     public void remove(DockingApplier applier) { 
      if (this.getAppliers().size() == 1) { 
       /* No sacamos el único elemento */ 
       return; 
      } 

      this.getAppliers().remove(applier); 

      if (this.leader == applier) { 
       this.leader = findLeader(); 
      } 

      /* Pude haber dividido en varios clusters */ 
      this.recalculateClustersAfterRemoval(); 
     } 

     public void recalculateClustersAfterRemoval() { 
      Set<DockingApplier> myAppliersCopy = new HashSet<DockingManager.DockingApplier>(getAppliers()); 
      Set<DockingApplier> visitedAppliers = new HashSet<DockingManager.DockingApplier>(); 
      for (DockingApplier applier : myAppliersCopy) { 
       if (visitedAppliers.contains(applier)) { 
        continue; 
       } 
       Set<DockingApplier> newClusterComponents = findClusteredAppliers(applier); 
       if (newClusterComponents.size() == myAppliersCopy.size()) { 
        /* No se dividieron los clusters */ 
        return; 
       } 
       visitedAppliers.addAll(newClusterComponents); 
       /* Creo un nuevo cluster, y le agrego los elementos */ 
       new DockingApplierCluster(newClusterComponents); 
      } 

     } 

     /** 
     * Devuelve todos los DockingAppliers anexos entre si. 
     * 
     * @param anApplier 
     * @return 
     */ 
     public Set<DockingApplier> findClusteredAppliers(DockingApplier anApplier) { 
      return findClusteredAppliers(anApplier, new HashSet<DockingManager.DockingApplier>()); 
     } 

     public Set<DockingApplier> findClusteredAppliers(DockingApplier anApplier, Set<DockingApplier> currentSet) { 
      currentSet.add(anApplier); 
      for (DockingApplier applier : anApplier.getAttachedComponents()) { 
       if (currentSet.contains(applier)) { 
        continue; 
       } 
       currentSet.add(applier); 
       currentSet.addAll(findClusteredAppliers(applier, currentSet)); 
      } 
      return currentSet; 
     } 

     private DockingApplier findLeader() { 
      DockingApplier leaderCandidate = null; 
      for (DockingApplier applier : getAppliers()) { 
       if (leaderCandidate == null || applier.getMagneticLevel() < leaderCandidate.getMagneticLevel()) { 
        leaderCandidate = applier; 
        if (applier.getMagneticLevel() == 1) { 
         /* Encontramos óptimo */ 
         break; 
        } 
       } 
      } 
      return leaderCandidate; 
     } 

    } 

    protected class DockingApplier implements ComponentListener, FocusListener { 

     private Component component = null; 
     private DockingApplierCluster cluster; 

     public DockingApplier(Component component, int magneticLevel) { 
      this.component = component; 
      this.cluster = new DockingApplierCluster(this); 
      this.magneticLevel = magneticLevel; 
      this.updateLastLocation(); 

      /* 
      * Esto no es necesario ya que registerComponent es quien crea el 
      * applier 
      */ 
      if (!monitoredComponents.containsKey(component)) { 
       monitoredComponents.put(component, this); 
      } 

      this.component.addComponentListener(this); 
      this.component.addFocusListener(this); 
      componentFinishedMovingDetector.setRepeats(false); 
     } 

     public void setCluster(DockingApplierCluster cluster) { 
      this.cluster = cluster; 
     } 

     /** 
     * @return the cluster 
     */ 
     public DockingApplierCluster getCluster() { 
      return cluster; 
     } 

     boolean isClusterLeader() { 
      return getCluster().getLeader() == this; 
     } 

     /** 
     * @return the magneticLevel 
     */ 
     public Integer getMagneticLevel() { 
      return magneticLevel; 
     } 

     /** 
     * @param magneticLevel 
     *   the magneticLevel to set 
     */ 
     public void setMagneticLevel(Integer magneticLevel) { 
      this.magneticLevel = magneticLevel; 
     } 

     /** 
     * @return the isDocking 
     */ 
     protected boolean isDocking() { 
      return isDocking; 
     } 

     /** 
     * @param isDocking 
     *   the isDocking to set 
     */ 
     protected void setDocking(boolean isDocking) { 
      this.isDocking = isDocking; 
     } 

     /** 
     * @return the attachedComponents 
     */ 
     public Set<DockingApplier> getAttachedComponents() { 
      return attachedComponents; 
     } 

     int northY; 
     int southY; 
     int westX; 
     int eastX; 

     public void recalculateBorderCoordinates() { 
      Point compLoc = component.getLocation(); 
      Dimension compDim = component.getSize(); 
      northY = compLoc.y; 
      southY = northY + compDim.height; 
      westX = compLoc.x; 
      eastX = westX + compDim.width; 
     } 

     public DockingMode calculateWhereToDock(DockingApplier other, int magneticDistance) { 
      return calculateWhereToDock(this, other, magneticDistance); 
     } 

     /** 
     * Indica si me debería lockearse con other 
     * 
     * @param me 
     * @param other 
     * @return 
     */ 
     public DockingMode calculateWhereToDock(DockingApplier me, DockingApplier other, int magneticDistance) { 

      /* Talvez innecesario */ 
      me.recalculateBorderCoordinates(); 
      other.recalculateBorderCoordinates(); 

      if (me.getAttachedComponents().contains(other)) { 
       /* Ya estan conectados */ 
       return DockingMode.NONE; 
      } 

      int dockDistN = me.northY - other.southY; 
      int dockDistS = other.northY - me.southY; 
      int dockDistW = me.westX - other.eastX; 
      int dockDistE = other.westX - me.eastX; 

      if (dockDistN > 0 && magneticDistance > dockDistN && checkOverlappingEastWest(me, other)) { 
       return DockingMode.NORTH; 
      } else if (dockDistS > 0 && magneticDistance > dockDistS && checkOverlappingEastWest(me, other)) { 
       return DockingMode.SOUTH; 
      } else if (dockDistW > 0 && magneticDistance > dockDistW && checkOverlappingNorthSouth(me, other)) { 
       return DockingMode.WEST; 
      } else if (dockDistE > 0 && magneticDistance > dockDistE && checkOverlappingNorthSouth(me, other)) { 
       return DockingMode.EAST; 
      } 
      return DockingMode.NONE; 
     } 

     /** 
     * Checks whether components overlap in north/south direction. 
     */ 
     protected boolean checkOverlappingEastWest(DockingApplier me, DockingApplier other) { 
      return checkOverlappingEastWest_aux(me, other) || checkOverlappingEastWest_aux(other, me); 
     } 

     /** 
     * Checks whether components overlap in east/west direction. 
     */ 
     protected boolean checkOverlappingEastWest_aux(DockingApplier me, DockingApplier other) { 
      return me.westX >= other.westX && me.westX <= other.eastX || me.eastX >= other.westX 
        && me.eastX <= other.eastX; 
     } 

     /** 
     * Checks whether components overlap in north/south direction. 
     */ 
     protected boolean checkOverlappingNorthSouth(DockingApplier me, DockingApplier other) { 
      return checkOverlappingNorthSouth_aux(me, other) || checkOverlappingNorthSouth_aux(other, me); 
     } 

     /** 
     * Checks whether components overlap in north/south direction. 
     */ 
     protected boolean checkOverlappingNorthSouth_aux(DockingApplier me, DockingApplier other) { 
      return me.northY >= other.northY && me.northY <= other.southY || me.southY >= other.northY 
        && me.southY <= other.southY; 
     } 

     public Point calculateDockedLocation(DockingApplier other, DockingMode mode) { 
      return calculateDockedLocation(this, other, mode); 
     } 

     public Point calculateDockedLocation(DockingApplier me, DockingApplier other, DockingMode mode) { 
      final Point meLoc = me.getComponent().getLocation(); 
      final Point otherLoc = other.getComponent().getLocation(); 
      final Dimension otherDim = other.getComponent().getSize(); 
      final Dimension meDim = me.getComponent().getSize(); 

      /* Posiciones relativas a other */ 
      switch (mode) { 
      case NORTH: 
       return new Point(meLoc.x, otherLoc.y + otherDim.height); 
      case SOUTH: 
       return new Point(meLoc.x, otherLoc.y - meDim.height); 
      case WEST: 
       return new Point(otherLoc.x + otherDim.width, meLoc.y); 
      case EAST: 
       return new Point(otherLoc.x - meDim.width, meLoc.y); 
      default: 
       return new Point(meLoc.x - otherLoc.x, meLoc.y); 
      } 
     } 

     /** 
     * Retrasa la accion a ejecutar en onComponentFinishedMoving hasta que 
     * pasan 10ms sin que se mueva el componente afectado. 
     */ 
     Timer componentFinishedMovingDetector = new Timer(300, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       onComponentFinishedMoving(); 
      } 
     }); 

     /** 
     * Resetea el componentFinishedMovingDetector, se debe llamar cada vez 
     * que se mueve o cambia el tamaño de la ventana. 
     */ 
     protected void startComponentFinishedMovingDetector() { 
      if (componentFinishedMovingDetector.isRunning()) { 
       componentFinishedMovingDetector.restart(); 
      } else { 
       componentFinishedMovingDetector.start(); 
      } 
     } 

     /* Mientras es menor, más probable es ser lider */ 
     int magneticLevel = 1; 

     /* Indica si el componente esta en proceso de hacer dock */ 
     boolean isDocking = false; 

     /* Para desconectarlos en resize */ 
     Set<DockingApplier> attachedComponents = new HashSet<DockingApplier>(); 
     /* Indica la posición del componente */ 
     private Point lastLocation; 

     public boolean isDocked() { 
      return getCluster().getSize() > 1; 
     } 

     /** 
     * @return the component 
     */ 
     protected Component getComponent() { 
      return component; 
     } 

     public void componentResized(ComponentEvent e) { 
      startComponentFinishedMovingDetector(); 
      this.recalculateBorderCoordinates(); 
      this.unDock(); 
     } 

     public void componentMoved(ComponentEvent e) { 

      this.recalculateBorderCoordinates(); 

      /* 
      * Si el movimiento es consecuencia de hacer dock lo ignoro y marco 
      * como que el docking se completó 
      */ 
      if (this.isDocking()) { 
       this.setDocking(false); 
       return; 
      } 

      startComponentFinishedMovingDetector(); 

      if (this != focusedApplier) { 
       return; 
      } 

      if (getCluster().getSize() == 1) { 
       return; 
      } 

      if (!this.isClusterLeader()) { 
       this.updateLastLocation(); 
       this.unDock(); 
       return; 
      } 

      positionAttachedComponents(); 

     } 

     public void onComponentFinishedMoving() { 
      this.recalculateBorderCoordinates(); 
      for (DockingApplier otherDockingApplier : getMonitoredComponents().values()) { 
       if (otherDockingApplier == this) { 
        continue; 
       } 
       DockingMode dockMode = calculateWhereToDock(this, otherDockingApplier); 
       if (!DockingMode.NONE.equals(dockMode)) { 
        System.out.println("shouldAttach"); 
        this.dock(otherDockingApplier, dockMode);     
        this.updateLastLocation(); 
       } else { 
        System.out.println("shouldNotAttach"); 
       } 
      } 
     } 

     public void setLocation(int x, int y) { 
      this.setLocation(new Point(x, y)); 
     } 

     public void setLocation(Point location) { 
      this.getComponent().removeComponentListener(this); 
      this.getComponent().setLocation(location); 
      this.setLastLocation(location); 
      this.getComponent().addComponentListener(this); 
     } 

     private void setLastLocation(Point location) { 
      this.lastLocation = location; 
     } 

     public Point getLocation() { 
      return this.getComponent().getLocation(); 
     } 

     /** 
     * @return the lastLocation 
     */ 
     public Point getLastLocation() { 
      return lastLocation; 
     } 

     protected void dock(DockingApplier otherDockingApplier, DockingMode dockMode) { 
      this.setDocking(true); 
      Point dockInfo = this.calculateDockedLocation(otherDockingApplier, dockMode); 
      this.setLocation(dockInfo.x, dockInfo.y); 
      this.bindAppliers(otherDockingApplier); 
      /* Uno los clusters */ 
      otherDockingApplier.getCluster().mergeCluster(this.getCluster()); 
     } 

     public void bindAppliers(DockingApplier otherDockingApplier) { 
      this.getAttachedComponents().add(otherDockingApplier); 
      otherDockingApplier.getAttachedComponents().add(this); 
     } 

     public void unDock() { 
      if (this.getCluster().getSize() == 1) { 
       return; 
      } 
      /* 
      * Primero lo quito de sus vecinos, luego del cluster, el orden es 
      * importante para el calculo de clusters en caso de división. 
      */ 
      Set<DockingApplier> attachedComponentsCopy = new HashSet<DockingManager.DockingApplier>(
        this.getAttachedComponents()); 
      for (DockingApplier applier : attachedComponentsCopy) { 
       this.unbind(applier); 
      } 

      this.getCluster().remove(this); 
      this.setCluster(new DockingApplierCluster(this)); 
     } 

     public void unbind(DockingApplier dockingApplier) { 
      this.getAttachedComponents().remove(dockingApplier); 
      dockingApplier.getAttachedComponents().remove(this); 
     } 

     private DockingMode calculateWhereToDock(DockingApplier component, DockingApplier otherDockingApplier) { 
      return this.calculateWhereToDock(otherDockingApplier, magneticDistance); 
     } 

     public void componentShown(ComponentEvent e) { 
      getMonitoredComponents().get(component).recalculateBorderCoordinates(); 
      // positionAttachedComponents(e); 
     } 

     public void componentHidden(ComponentEvent e) { 
      getMonitoredComponents().get(component).recalculateBorderCoordinates(); 
      // positionAttachedComponents(e); 
     } 

     private void positionAttachedComponents() { 

      /* El lider del cluster debe arrastrar a los otros componentes */ 
      Point currentLocation = getComponent().getLocation(); 
      int xDiff = currentLocation.x - getLastLocation().x; 
      int yDiff = currentLocation.y - getLastLocation().y; 

      if (xDiff == 0 && yDiff == 0) { 
       return; 
      } 

      this.updateLastLocation(); 

      for (DockingApplier otherApplier : getCluster().getAppliers()) { 
       if (otherApplier == this) { 
        continue; 
       } 
       Point otherComponentLocation = otherApplier.getComponent().getLocation(); 
       otherApplier.getComponent().removeComponentListener(otherApplier); 
       otherApplier.setDocking(true); 
       otherApplier.getComponent().setLocation(otherComponentLocation.x + xDiff, 
         otherComponentLocation.y + yDiff); 
       otherApplier.getComponent().addComponentListener(otherApplier); 
      } 
     } 

     public void updateLastLocation() { 
      this.setLastLocation(getComponent().getLocation()); 
     } 

     @Override 
     public void focusGained(FocusEvent e) { 
      DockingManager.setFocusedApplier(this); 
     } 

     @Override 
     public void focusLost(FocusEvent e) { 
      // TODO Auto-generated method stub 

     } 
    } 

    public DockingManager() { 

    } 

    public static void setFocusedApplier(DockingApplier applier) { 
     DockingManager.focusedApplier = applier; 
    } 

    public static void main(String[] args) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Exception e) { 
     } 
     JFrame frame1 = new JFrame("Frame 1"); 
     JDialog dialog2 = new JDialog((JFrame) null, "Dialog 2"); 
     frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame1.setSize(200, 50); 
     dialog2.setSize(200, 50); 
     frame1.setVisible(true); 
     dialog2.setVisible(true); 

     JDialog dialog1 = new JDialog((JFrame) null, "Dialog 1"); 
     dialog1.setSize(200, 50); 
     dialog1.setVisible(true); 

     DockingManager manager = new DockingManager(); 

     manager.registerComponent(frame1, 1); 
     manager.registerComponent(dialog2, 2); 
     manager.registerComponent(dialog1, 2); 

    } 

    /** 
    * @return the monitoredComponents 
    */ 
    protected static Map<Component, DockingApplier> getMonitoredComponents() { 
     return monitoredComponents; 
    } 
} 
+0

我無法使它工作。只有3種公共方法。其他一切都是私人的或受保護的。其中2個正在添加組件。另一個需要發送DockingApplier對象。該類也受到保護,因此我無法創建一個發送它。要麼我錯過了一些東西,或者這段代碼需要修改。 – WVrock 2015-06-17 09:28:59

相關問題