2016-11-05 14 views
6

Dưới đây là mã cho bố cục đơn giản được tạo bằng cách sử dụng một số lồng nhau JSplitPanes.Cho phép JSplitPanes lồng nhau để kiểm soát JSplitPanes gốc

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JSplitPane; 

public class CDBurner extends JFrame { 
    private static final long serialVersionUID = -6027473114929970648L; 
    JSplitPane main, folder, rest; 
    JPanel centeral, folders, favourites, tasks; 
    JLabel label; 

    private CDBurner() { 
     super("Dan's CD Burner"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new GridLayout(1, 1)); 
     getContentPane().setBackground(Color.black); 

     createLayout(); 

     pack(); 
     setMinimumSize(getSize()); 
     setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH); 
     setVisible(true); 
     requestFocus(); 
    } 

    private void createLayout() { 
     createPanels(); 
     rest = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centeral, tasks); 
     rest.setResizeWeight(1); 
     rest.setContinuousLayout(true); 
     rest.setOneTouchExpandable(true); 
     folder = new JSplitPane(JSplitPane.VERTICAL_SPLIT, favourites, folders); 
     folder.setResizeWeight(0.35); 
     folder.setContinuousLayout(true); 
     folder.setOneTouchExpandable(true); 
     main = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, folder, rest); 
     main.setResizeWeight(0); 
     main.setContinuousLayout(true); 
     main.setOneTouchExpandable(true); 
     getContentPane().add(main); 
    } 

    private void createPanels() { 
     createFolders(); 
     createCenter(); 
     createTaskSpool(); 
     createFavourites(); 
    } 

    private void createFolders() { 
     folders = new JPanel(new GridLayout(1, 1)); 
     label = new JLabel("Folder"); 
     folders.setMinimumSize(new Dimension(300, 100)); 
     folders.add(label); 
    } 

    private void createCenter() { 
     centeral = new JPanel(new GridLayout(1, 1)); 
     label = new JLabel("Central"); 
     centeral.add(label); 
     centeral.setMinimumSize(new Dimension(300, 100)); 
    } 

    private void createTaskSpool() { 
     tasks = new JPanel(new GridLayout(1, 1)); 
     label = new JLabel("Task"); 
     tasks.setMinimumSize(new Dimension(300, 100)); 
     tasks.add(label); 
    } 

    private void createFavourites() { 
     favourites = new JPanel(new GridLayout(1, 1)); 
     label = new JLabel("Fav"); 
     favourites.setMinimumSize(new Dimension(300, 100)); 
     favourites.add(label); 
    } 

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

Do dòng rest.setResizeWeight(1); bạn có thể kéo chia main (JSplitPane) sang bên phải và nó sẽ thu nhỏ tasks JPanel cho đến khi cả hai JPanels trong rest là kích thước tối thiểu. Tuy nhiên, nếu bạn cố gắng làm điều ngược lại thì không có gì xảy ra. Xem hình ảnh bên dưới để xem sự cố.

Nếu gui trông như thế này, bạn có thể kéo bộ chia main.

enter image description here

Và bạn sẽ nhận được kết quả của việc này.

enter image description here

Tuy nhiên nếu nó trông như thế này và bạn cố gắng kéo rest chia có gì xảy ra.

enter image description here

Điều này là do cả hai mặt của rest JSplitPane đã ở kích thước tối thiểu của họ.

Các Câu hỏi
Làm thế nào tôi có thể làm cho nó để khi tôi kéo chia rest nó ảnh hưởng các main JSplitPane để cả hai hoạt động thể hiện trong những hình ảnh trên là có thể?

Trả lời

2

Theo như tôi biết hành vi bạn mô tả là hành vi bình thường cho các lượt xem được chia. Có một cái nhìn về cách phân chia của các ứng dụng chuyên nghiệp như Eclipse hành xử.

Dù sao tôi đã tạo giải pháp thay thế cho hành vi mong muốn của bạn bằng cách kiểm soát các chuyển động của phần còn lại của bạn theo cách lập trình JSplitPane. Bạn chỉ cần thêm các dòng mã sau khi tạo phần còn lại JSplitPane trong phương thức createLayout() của mình.

SplitPaneUI spui = rest.getUI(); 
if (spui instanceof BasicSplitPaneUI) {   
    ((BasicSplitPaneUI) spui).getDivider().addMouseMotionListener(new MouseAdapter(){   
     @Override 
     public void mouseDragged(MouseEvent E){ 
      int newPos = E.getPoint().x;      
      if(newPos < 0 && folder.getSize().width > 300 && centeral.getSize().width <= 300){ 
       main.setDividerLocation(main.getDividerLocation() + newPos); 
       validate();      
      } 
      if(centeral.getSize().width > 300 && tasks.getSize().width > 300){ 
       rest.setDividerLocation(rest.getDividerLocation() + newPos); 
       validate(); 
      } 
     } 
    }); 
} 

giải thích:
Trong dòng đầu tiên chúng ta hãy đối tượng giao diện người dùng của divider của JSplitPane và thêm một tùy chỉnh MouseMotionListener với nó. Chúng tôi cần đối tượng giao diện người dùng vì thực tế JSplitPane không trực tiếp nhận được bất kỳ sự kiện chuột nào.
Bên trong trình lắng nghe, chúng tôi ghi đè phương thức mouseDragged và nhận vị trí X thực tế của chuột trong khi nó đang kéo bộ chia.
Nếu giá trị âm của nó, chúng tôi sẽ kéo dải phân cách sang bên trái. Trong trường hợp này, chúng tôi cũng muốn bộ chia chính di chuyển nếu bảng điều khiển trung tâm đã bị thu nhỏ thành kích thước tối thiểu là 300 và bảng điều khiển thư mục bên trái vẫn lớn hơn kích thước tối thiểu của nó.
Dải phân cách còn lại sẽ có thể di chuyển được nếu trung tâm và bảng điều khiển bên phải vẫn lớn hơn kích thước tối thiểu 300.

+0

Cảm ơn bạn đã trả lời, tuy nhiên, dường như nó không hoạt động tốt. Phần chia tách còn lại hiện rất nhanh và ngẫu nhiên ngừng di chuyển và bạn phải nhấp lại vào đó. Mặc dù, điều này dường như là con đường đúng để đi xuống. Tôi sẽ xem xét nó – Dan

1
  • Dưới đây là một thực thể sử dụng JLayer
    • Ví dụ này chỉ xem xét trường hợp của JSplitPane.HORIZONTAL_SPLIT
    • Lưu ý: đây chỉ được trình bày như một ý tưởng, sẽ cần rất nhiều công việc để làm cho nó có thể sử dụng
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.plaf.*; 
import javax.swing.plaf.basic.BasicSplitPaneDivider; 

public class CDBurner2 extends JFrame { 
    JSplitPane main, folder, rest; 
    JPanel centeral, folders, favourites, tasks; 
    JLabel label; 

    private CDBurner2() { 
    super("Dan's CD Burner"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    createLayout(); 
    setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH); 
    setVisible(true); 
    } 

    private void createLayout() { 
    createPanels(); 
    rest = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centeral, tasks); 
    rest.setResizeWeight(1); 
    rest.setContinuousLayout(true); 
    rest.setOneTouchExpandable(true); 

    folder = new JSplitPane(JSplitPane.VERTICAL_SPLIT, favourites, folders); 
    folder.setResizeWeight(0.35); 
    folder.setContinuousLayout(true); 
    folder.setOneTouchExpandable(true); 

    main = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, folder, rest); 
    main.setResizeWeight(0); 
    main.setContinuousLayout(true); 
    main.setOneTouchExpandable(true); 

    //getContentPane().add(main); 
    getContentPane().add(new JLayer<JSplitPane>(
     main, new SplitPaneDividerDragLayerUI())); 
    } 

    private void createPanels() { 
    createFolders(); 
    createCenter(); 
    createTaskSpool(); 
    createFavourites(); 
    } 

    private void createFolders() { 
    folders = new JPanel(new GridLayout(1, 1)); 
    label = new JLabel("Folder"); 
    folders.setMinimumSize(new Dimension(300, 100)); 
    folders.add(label); 
    } 

    private void createCenter() { 
    centeral = new JPanel(new GridLayout(1, 1)); 
    label = new JLabel("Central"); 
    centeral.add(label); 
    centeral.setMinimumSize(new Dimension(300, 240)); 
    centeral.setPreferredSize(new Dimension(600, 240)); 
    } 

    private void createTaskSpool() { 
    tasks = new JPanel(new GridLayout(1, 1)); 
    label = new JLabel("Task"); 
    tasks.setMinimumSize(new Dimension(300, 240)); 
    tasks.setPreferredSize(new Dimension(600, 240)); 
    tasks.add(label); 
    } 

    private void createFavourites() { 
    favourites = new JPanel(new GridLayout(1, 1)); 
    label = new JLabel("Fav"); 
    favourites.setMinimumSize(new Dimension(300, 100)); 
    favourites.add(label); 
    } 

    public static void main(String... args) { 
    EventQueue.invokeLater(() -> new CDBurner2()); 
    } 
} 

class SplitPaneDividerDragLayerUI extends LayerUI<JSplitPane> { 
    private int dividerLocation; 
    private final Point startPt = new Point(); 
    @Override public void installUI(JComponent c) { 
    super.installUI(c); 
    if (c instanceof JLayer) { 
     ((JLayer) c).setLayerEventMask(
      AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); 
    } 
    } 
    @Override public void uninstallUI(JComponent c) { 
    if (c instanceof JLayer) { 
     ((JLayer) c).setLayerEventMask(0); 
    } 
    super.uninstallUI(c); 
    } 
    @Override protected void processMouseEvent(
     MouseEvent e, JLayer<? extends JSplitPane> l) { 
    super.processMouseEvent(e, l); 
    JSplitPane splitPane = l.getView(); 
    Component c = e.getComponent(); 
    if (e.getID() == MouseEvent.MOUSE_PRESSED && c instanceof BasicSplitPaneDivider) { 
     JSplitPane sp = (JSplitPane) SwingUtilities.getUnwrappedParent(c); 
     if (!splitPane.equals(sp) && sp.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { 
     startPt.setLocation(SwingUtilities.convertPoint(c, e.getPoint(), sp)); 
     dividerLocation = splitPane.getDividerLocation(); 
     } 
    } 
    } 
    @Override protected void processMouseMotionEvent(
     MouseEvent e, JLayer<? extends JSplitPane> l) { 
    super.processMouseEvent(e, l); 
    JSplitPane splitPane = l.getView(); 
    Component c = e.getComponent(); 
    if (e.getID() == MouseEvent.MOUSE_DRAGGED && c instanceof BasicSplitPaneDivider) { 
     JSplitPane sp = (JSplitPane) SwingUtilities.getUnwrappedParent(c); 
     if (!splitPane.equals(sp) && sp.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { 
     Point pt = SwingUtilities.convertPoint(c, e.getPoint(), sp); 
     int delta = pt.x - startPt.x; 
     startPt.setLocation(pt); 
     if (delta < 0 && sp.getMinimumDividerLocation() == sp.getDividerLocation()) { 
      //System.out.println("delta: " + delta); 
      dividerLocation = Math.max(
       splitPane.getMinimumDividerLocation(), dividerLocation + delta); 
      splitPane.setDividerLocation(dividerLocation); 
      EventQueue.invokeLater(() -> { 
      sp.setDividerLocation(sp.getMinimumDividerLocation()); 
      }); 
     } 
     } 
    } 
    } 
} 
+0

Giống như bạn đã nói và câu trả lời khác đây là đúng hướng nhưng vẫn cần công việc. Cảm ơn bạn đã trả lời – Dan

+0

Vâng, tôi cho rằng đây là câu trả lời gần nhất, tốt nhất không để 50 điểm đi đến chất thải – Dan

Các vấn đề liên quan