2013-01-20 3 views
2

Я хочу реализовать JSplitPane (горизонтальный сплит), где правый компонент имеет постоянную ширину, т. Е. Когда разделитель перетаскивается, он вернется к правильному размеру, если только делитель перетаскивается достаточно далеко вправо, и в этом случае самый правый компонент будет иметь нулевую ширину.Обнаружение при перетаскивании разделителя JSplitPane, но не изменение размера компонента

Чтобы повторно отобразить нужный компонент, пользователь может перетащить разделитель достаточно далеко влево.

У меня это в основном работает, но когда я изменяю размер окна в зависимости от того, насколько и насколько быстро я изменяю размер окна, прыжки с разделителями показывают или скрывают правильный компонент, где, как я хочу, это то, что он не должен измените «состояние», т. е. если правый компонент не был виден, он должен оставаться невидимым и наоборот.

Я пробовал кучу вещей, но главным препятствием является то, что, кажется, не существует способа узнать погоду, которую разделитель перетаскивал пользователем с помощью мыши или если код (моя логика делителя и/или внутренняя логика JSplitPane) изменил положение разделителя.

Вот самостоятельный тестовый пример, запустите его и попробуйте перетащить горизонтальный разделитель, чтобы скрыть и открыть правую боковую панель, а с помощью скрытых/показанных попытайтесь изменить размер окна.

Не работает в соответствии с требованиями Mac OS X Java 1.6 (Apple) или Java 7 (Oracle). С материалом Oracle рендеринг выполняется гораздо медленнее, и проблема более серьезная. Изменение размера окна медленно работает, но быстрые изменения размера окна вызывают проблемы.

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

import net.miginfocom.swing.MigLayout; 

public class SplitTest { 
    public static class MySplitPane extends JSplitPane { 
     boolean m_RightCollapsed; 

     public MySplitPane(int orientation, JComponent left, JComponent right) { 
      super(orientation, left, right); 

      addPropertyChangeListener(new PropertyChangeListener() { 

       @Override 
       public void propertyChange(PropertyChangeEvent evt) { 

       } 
      }); 
      addComponentListener(new ComponentListener() { 

       @Override 
       public void componentShown(ComponentEvent e) { 
        reposDivider(); 
       } 

       @Override 
       public void componentResized(ComponentEvent e) { 
        reposDivider(); 
       } 

       @Override 
       public void componentMoved(ComponentEvent e) { 
        reposDivider(); 
       } 

       @Override 
       public void componentHidden(ComponentEvent e) { 
       } 
      }); 

     } 

     public void reposDivider() { 
      setDividerLocation(getDividerLocation()); 
     } 

     public void setDividerLocation(int location) { 
      int newLocation; 
      m_RightCollapsed = location > getSize().width - getRightComponent().getPreferredSize().width/2; 
      if (m_RightCollapsed) 
       newLocation = getSize().width; 
      else 
       newLocation = getSize().width - getInsets().right - getDividerSize() - getRightComponent().getPreferredSize().width; 
      super.setDividerLocation(newLocation); 
     } 
    } 
    static class MyScrollable extends JPanel implements Scrollable { 
     int m_Height; 

     public MyScrollable(int height) { 
      m_Height = height; 
     } 

     @Override 
     public void paint(java.awt.Graphics g) { 
      super.paint(g); 
      g.setColor(Color.CYAN); 
      g.fillOval(0, 0, getWidth(), 500); 
     } 

     @Override 
     public Dimension getPreferredScrollableViewportSize() { 
      //return super.getPreferredSize(); 
      return new Dimension(100, m_Height); 
     } 

     @Override 
     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 
      // TODO Auto-generated method stub 
      return 10; 
     } 

     @Override 
     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 
      return 20; 
     } 

     @Override 
     public boolean getScrollableTracksViewportWidth() { 
      return true; 
     } 

     @Override 
     public boolean getScrollableTracksViewportHeight() { 
      return false; 
     } 

    } 

    public static class ShrinkGrow extends JPanel { 
     public ShrinkGrow(final JComponent component, final JSplitPane split) { 
      JButton grow = new JButton("+++"); 
      JButton shrink = new JButton("---"); 
      add(grow); 
      add(shrink); 

      grow.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        Dimension oldSize = component.getPreferredSize(); 
        Dimension newSize = new Dimension(oldSize.width, oldSize.height + 10); 
        component.setPreferredSize(newSize); 
        component.setSize(newSize); 
       } 
      }); 
      shrink.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        Dimension oldSize = component.getPreferredSize(); 
        Dimension newSize = new Dimension(oldSize.width, oldSize.height - 10); 
        component.setPreferredSize(newSize); 
        component.setSize(newSize); 
       } 
      }); 
     } 
    } 

    public static void main(String[] args) { 
     JFrame window = new JFrame(); 

     JPanel mainView = new JPanel(); 
     JPanel top = new JPanel(); 
     top.setLayout(new BoxLayout(top, BoxLayout.Y_AXIS)); 
     JPanel bottom = new JPanel(); 
     bottom.setLayout(new BoxLayout(bottom, BoxLayout.Y_AXIS)); 

     final JSplitPane rightSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 

     JPanel topContent = new MyScrollable(200); 
     JPanel topFixed = new ShrinkGrow(topContent, rightSplit); 
     topFixed.setLayout(new BoxLayout(topFixed, BoxLayout.X_AXIS)); 

     JScrollPane topFlexible = new JScrollPane(topContent); 
     topFlexible.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 
     topFlexible.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 

     JPanel bottomContent = new MyScrollable(300); 
     JPanel bottomFixed = new ShrinkGrow(bottomContent, rightSplit); 
     bottomFixed.setLayout(new BoxLayout(bottomFixed, BoxLayout.X_AXIS)); 

     JScrollPane bottomFlexible = new JScrollPane(bottomContent); 
     bottomFlexible.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 
     bottomFlexible.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 

     mainView.setBackground(Color.red); 
     topFixed.setBackground(Color.green); 
     topContent.setBackground(Color.green.darker()); 
     bottomFixed.setBackground(Color.blue); 
     bottomContent.setBackground(Color.blue.darker()); 

     mainView.setMinimumSize(new Dimension(100, 100)); 
     mainView.setPreferredSize(new Dimension(400, 300)); 
     mainView.setMaximumSize(new Dimension(10000, 10000)); 

     topFixed.setMinimumSize(new Dimension(topFixed.getMinimumSize().width, 30)); 
     topFixed.setPreferredSize(new Dimension(topFixed.getPreferredSize().width, 30)); 
     topFixed.setMaximumSize(new Dimension(topFixed.getMaximumSize().width, 30)); 

     bottomFixed.setMinimumSize(new Dimension(bottomFixed.getMinimumSize().width, 40)); 
     bottomFixed.setPreferredSize(new Dimension(bottomFixed.getPreferredSize().width, 40)); 
     bottomFixed.setMaximumSize(new Dimension(bottomFixed.getMaximumSize().width, 40)); 

     topContent.setPreferredSize(new Dimension(100, 500)); 
     bottomContent.setPreferredSize(new Dimension(100, 400)); 

     top.add(topFixed); 
     top.add(topFlexible); 
     bottom.add(bottomFixed); 
     bottom.add(bottomFlexible); 
     rightSplit.setLeftComponent(top); 
     rightSplit.setRightComponent(bottom); 

     rightSplit.setMinimumSize(new Dimension(0, 0)); 

     final JSplitPane mainSplit = new MySplitPane(JSplitPane.HORIZONTAL_SPLIT, mainView, rightSplit); 

     window.add(mainSplit); 
     window.pack(); 
     window.setVisible(true); 
    } 
} 

ответ

5

Не уверен, если это возможно, чтобы поймать dragging события, но уверен, что вы можете поймать propertyChange события. Ловкие события после перемещения делителя JSplitPane могут стать возможными благодаря классу JSplitPane PropertyChangeListener. Убедитесь, что вы указали параметр DIVIDER_LOCATION_PROPERTY в качестве параметра, чтобы этот слушатель подал отчет о событиях изменения местоположения. Если вы не указали это как первый параметр в методе addPropertyChangeListener(), вы всегда можете разместить условный оператор, если возвращает dividerLocation как значение.

jSplitPane1.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() { 
@Override 
public void propertyChange(PropertyChangeEvent pce) { 
    // do here 
} 
}); 
+1

Спасибо, я уже пробовал это. Но проблема в том, что невозможно узнать, было ли изменено свойство в результате перетаскивания разделителя или из-за изменения размера компонента JSlitPane. Если в первом случае я хочу уважать выбор пользователя и просто округлить его до одной или другой из двух действительных позиций, а в последнем случае я хочу восстановить его в зависимости от того, что было до изменения. Проблема в том, что при изменении размера окна происходит 1-4 из этих изменений свойств. – nyholku

1

... если делитель не волочатся достаточно далеко права в этом случае право большинство компонента будет иметь нулевую ширину.

Для повторного отображения нужного компонента пользователь может перетащить разделитель достаточно далеко влево.

звучит как все, что вам нужно сделать, это отключить splitPane отключить перетаскивание,

затем setOneTouchExpandable() истина. Вы, возможно, потребуется удалить один из «расширяемый»

кнопки, чтобы отключить расширение неправильный путь

2

Добавить в MouseListener в делителем Панель с разделителем, чтобы определить, когда делитель тащат. При перетаскивании отвечайте на события изменения свойств.Пример:

https://community.oracle.com/thread/1352161?start=0&tstart=0

SplitPaneUI spui = splitPane.getUI(); 
    if (spui instanceof BasicSplitPaneUI) { 
     // Setting a mouse listener directly on split pane does not work, because no events are being received. 
     ((BasicSplitPaneUI) spui).getDivider().addMouseListener(new MouseAdapter() { 
     public void mouseClicked(MouseEvent e) { 
Смежные вопросы