【问题标题】:Making a JPanel manually resizable使 JPanel 手动调整大小
【发布时间】:2010-11-10 08:05:52
【问题描述】:

我有一个JFrame 和BorderLayout 作为布局管理器。

在南边,我有一个JPanel,我希望这个JPanel的大小可以由用户调整,即用户可以点击边框的边缘并向上拖动它使其变大.

你有什么方法知道我可以做到这一点吗?

【问题讨论】:

    标签: java swing jframe jpanel jsplitpane


    【解决方案1】:

    为了使框架中的面板可以单独调整大小,您需要将它们添加到JSplitPane。

    不要将它放在框架的南部,而是将JSplitPane 放在中心。拆分窗格将使拆分中的底部面板看起来像是在南方,而拆分中的顶部面板将位于框架的中心。

    确保使用setOrientation(JSplitPane.VERTICAL_SPLIT ) 设置两个面板的方向。

    然后,您可以调整窗格中的面板大小。

    【讨论】:

      【解决方案2】:

      我想你的意思是说 JPanel。您可以添加自定义 mouseListener 并处理鼠标单击、拖动和鼠标释放,然后以编程方式调整面板大小。

      这将证明这一点。请注意,jframe 不会使用 JPanel 自动调整大小。为了使效果更明显,我将面板涂成红色并添加了斜角边框:

      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.Graphics;
      import java.awt.Point;
      import java.awt.event.MouseAdapter;
      import java.awt.event.MouseEvent;
      import java.awt.event.MouseMotionAdapter;
      
      import javax.swing.BorderFactory;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.border.BevelBorder;
      
      @SuppressWarnings("serial")
      public class ResizablePanel extends JPanel {
      
          private boolean drag = false;
          private Point dragLocation  = new Point();
      
          public  ResizablePanel() {
              setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
              setPreferredSize(new Dimension(500, 500));
              final JFrame f = new JFrame("Test");
              addMouseListener(new MouseAdapter() {
                  @Override
                  public void mousePressed(MouseEvent e) {
                      drag = true;
                      dragLocation = e.getPoint();
                  }
      
                  @Override
                  public void mouseReleased(MouseEvent e) {
                      drag = false;
                  }
              });
              addMouseMotionListener(new MouseMotionAdapter() {
                  @Override
                  public void mouseDragged(MouseEvent e) {
                      if (drag) {
                          if (dragLocation.getX()> getWidth()-10 && dragLocation.getY()>getHeight()-10) {
                              System.err.println("in");
                              setSize((int)(getWidth()+(e.getPoint().getX()-dragLocation.getX())),
                                      (int)(getHeight()+(e.getPoint().getY()-dragLocation.getY())));
                              dragLocation = e.getPoint();
                          }
                      }
                  }
              });
              f.getContentPane().setLayout(new BorderLayout());
              f.getContentPane().add(this,BorderLayout.CENTER);
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              f.pack();
              f.setVisible(true);
          }
      
          public static void main(String[] args) {
              new ResizablePanel();
          }
      
          public void paintComponent(Graphics g) {
              g.setColor(Color.red);
              g.fillRect(0, 0, getWidth(), getHeight());
          }
      
      }
      

      【讨论】:

      • 这太过分了!一个简单的JSplitPane 即可完成工作。
      • 我知道。我刚刚回答了他的问题。
      • 这是一个有趣的解决方案。
      • 问题是 jframe 不会随面板自动调整大小。我在每次通话中都尝试了 pack() (我知道很贵),但没有奏效。也许不同的布局管理器可以解决问题?
      • 这是一个绝妙的解决方案,如果你想摆脱 JSplitPane 默认值(例如分隔符的边框大小),那就太好了。
      【解决方案3】:

      如果你想参加look,我为此开设了一个课程。还没完呢。

      package projetoSplitPainel;
      
      import java.awt.Component;
      import java.util.ArrayList;
      
      import javax.swing.JSplitPane;
      
      /**
       * This Components is based on the JSplitPane. JSplitPane is used to divide two
       * (and only two) Components. This class intend to manipulate the JSplitPane in
       * a way that can be placed as many Component as wanted.
       * 
       * @author Bode
       *
       */
      public class JSplitPaneMultiTabs extends JSplitPane {
          private ArrayList<JSplitPane> ecanpsulationList = new ArrayList<JSplitPane>();
          private int numberOfComponents = 1;
          private int sizeOfDivision = 6;
      
          /**
           * Builds the Pane
           */
          public JSplitPaneMultiTabs() {
              super();
              this.setLeftComponent(null);
              this.setBorder(null);
              ecanpsulationList.add(this);
              setAllBorders(sizeOfDivision);
          }
      
          /**
           * 
           * @param comp - adds a Component to the Pane
           */
          public void addComponent(Component comp) {
              JSplitPane capsule = new JSplitPane();
      
              capsule.setRightComponent(null);
              capsule.setLeftComponent(comp);
              capsule.setDividerSize(sizeOfDivision);
              capsule.setBorder(null);
      
              ecanpsulationList.get(numberOfComponents - 1).setRightComponent(capsule);
              ecanpsulationList.add(capsule);
              numberOfComponents++;
              this.fixWeights();
          }
      
          /**
           * 
           * @param orientation
           *            JSplitPane.HORIZONTAL_SPLIT - sets the orientation of the
           *            Components to horizontal alignment
           * @param orientation
           *            JSplitPane.VERTICAL_SPLIT - sets the orientation of the
           *            Components to vertical alignment
           */
          public void setAlignment(int orientation) {
              for (int i = 0; i < numberOfComponents; i++) {
                  ecanpsulationList.get(i).setOrientation(orientation);
      
              }
          }
      
          /**
           * 
           * @param newSize - resizes the borders of the all the Components of the Screen
           */
          public void setAllBorders(int newSize) {
              this.setDividerSize(newSize);
              for (int i = 0; i < numberOfComponents; i++) {
                  ecanpsulationList.get(i).setDividerSize(newSize);
              }
      
          }
      
          /**
           * each Component added needs to be readapteded to the screen
           */
          private void fixWeights() {
              ecanpsulationList.get(0).setResizeWeight(1.0);
              for (int i = 1; i < numberOfComponents; i++) {
                  double resize = (double) 1 / (double) (i + 1);
                  ecanpsulationList.get(numberOfComponents - i - 1).setResizeWeight(
                          resize);
              }
              ecanpsulationList.get(numberOfComponents - 1).setResizeWeight(0.0);
          }
      
      }
      

      【讨论】:

        【解决方案4】:

        所以我做了一个类,它主要做 OP 想要的。基本上它是一个可以在单击边框时调整大小的面板。它还(尝试)调整其中包含的所有组件的大小以适应新的大小。它还尝试检测父框架中其他组件之间的冲突,以尽可能防止重叠。

        不管怎样,你去:

        import java.awt.BasicStroke;
        import java.awt.Component;
        import java.awt.Container;
        import java.awt.Cursor;
        import java.awt.Dimension;
        import java.awt.Graphics;
        import java.awt.Graphics2D;
        import java.awt.Point;
        import java.awt.Rectangle;
        import java.awt.Stroke;
        import java.awt.event.MouseAdapter;
        import java.awt.event.MouseEvent;
        import java.awt.event.MouseMotionAdapter;
        
        import javax.swing.JDesktopPane;
        
        
        @SuppressWarnings("serial")
        public class ResizablePanel extends JDesktopPane {
        
            private boolean drag = false;
            private boolean top =false;
            private boolean bottom =false;
            private boolean left=false;
            private boolean right =false;
            private Point dragLocation  = new Point();
            public  ResizablePanel() {
                setMinimumSize(new Dimension(200, 200));
                addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        evaluateMousePress(e.getPoint());
                    }
        
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        drag = false;
                        setCursor(Cursor.getDefaultCursor());
                    }
                });
                addMouseMotionListener(new MouseMotionAdapter() {
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        evaluateMouseDrag(e.getPoint());
                    }
                    @Override
                    public void mouseMoved(MouseEvent e) {
                        evaluateMouseHover(e.getPoint());
                    }
                });
            }
            @Override
            public void setBounds(int x, int y, int width, int height) {
                Rectangle oldBounds=getBounds();
                Rectangle newBounds = new Rectangle(x, y, width, height);
                super.setBounds(x, y, width, height);
                resizeSingleComponent(this,oldBounds, newBounds);
            }
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g;
                Stroke stroke = g2.getStroke();
                g2.setStroke(new BasicStroke(5));
                g.drawRect(0, 0, getBounds().width, getBounds().height);
                g2.setStroke(stroke);
            }
            private void resizeSingleComponent(Component component , Rectangle oldBounds , Rectangle newBounds) {
                
                if(component instanceof Container) {
                    if(!component.equals(this)) {
                        Rectangle componentBounds = component.getBounds();
                        double x = getNew(componentBounds.getX(), oldBounds.getWidth(), newBounds.getWidth());
                        double y = getNew(componentBounds.getY(), oldBounds.getHeight(), newBounds.getHeight());
                        double width = getNew(componentBounds.getWidth(), oldBounds.getWidth(), newBounds.getWidth());
                        double height = getNew(componentBounds.getHeight(), oldBounds.getHeight(), newBounds.getHeight());
                        componentBounds.width = (int) Math.round(width);
                        componentBounds.height = (int) Math.round(height);
                        componentBounds.x = (int) Math.round(x);
                        componentBounds.y = (int) Math.round(y);
                        component.setBounds(componentBounds);
                    }
                    for(Component child:((Container) component).getComponents())
                        resizeSingleComponent(child, oldBounds, newBounds);
                }
                else {
                    Rectangle componentBounds = component.getBounds();
                    double x = getNew(componentBounds.getX(), oldBounds.getWidth(), newBounds.getWidth());
                    double y = getNew(componentBounds.getY(), oldBounds.getHeight(), newBounds.getHeight());
                    double width = getNew(componentBounds.getWidth(), oldBounds.getWidth(), newBounds.getWidth());
                    double height = getNew(componentBounds.getHeight(), oldBounds.getHeight(), newBounds.getHeight());
                    componentBounds.width = (int) Math.round(width);
                    componentBounds.height = (int) Math.round(height);
                    componentBounds.x = (int) Math.round(x);
                    componentBounds.y = (int) Math.round(y);
                    component.setBounds(componentBounds);
                }
            }
            
            
            private void evaluateMouseDrag(Point point) {
                if (drag) {
                    if (top || left || right || bottom) {
                        int heightIncrement=0;
                        int widthIncrement=0;
                        int posX = getBounds().x;
                        int posY = getBounds().y;
                        if(top || bottom) 
                            heightIncrement = (int) (point.getY()-dragLocation.getY());
                        if(left || right)
                            widthIncrement = (int) (point.getX()-dragLocation.getX());
                        if(top) {
                            posY = posY+heightIncrement;
                            heightIncrement=-heightIncrement;
                        }
                        if(left) {
                            posX=posX+widthIncrement;
                            widthIncrement=-widthIncrement;
                        }
                        if(right)
                            dragLocation.x=(int) point.getX();
                        if(bottom)
                            dragLocation.y=(int) point.getY();
                            
                        Rectangle bounds = new Rectangle(posX, posY, getWidth()+ widthIncrement,getHeight()+ heightIncrement);    
                        justifyCollision(bounds,point);
                    }
                }
            }
            private void evaluateMousePress(Point point) {
                 drag = true;
                 dragLocation = point;
                 top=dragLocation.getY() <=5;
                 left=dragLocation.getX() <=5;
                 bottom = dragLocation.getY() >=getHeight()-5;
                 right = dragLocation.getX() >=getWidth()-5;
                 setResizeCursor(point);
            }
            private void evaluateMouseHover(Point point) {
                if(!drag) {
                    top=point.getY() <=5;
                    left=point.getX() <=5;
                    bottom = point.getY() >=getHeight()-5;
                    right = point.getX() >=getWidth()-5;
                    setResizeCursor(point);
                }
           }
            
            private void justifyCollision(Rectangle bounds, Point point) {
                //justify undersizing
                if(bounds.width<getMinimumSize().width) {
                    if(left)
                        bounds.x= getBounds().x;
                    bounds.width=getWidth();
                }
                if(bounds.height<getMinimumSize().height) {
                    if(top)
                        bounds.y=getBounds().y;
                    bounds.height=getHeight();
                }
                Container parent = getParent();
                //justify parent container bounds
                if(bounds.x<0 ||bounds.width+bounds.x>parent.getWidth()) {
                    bounds.width = getWidth();
                    if(right &&!(bounds.width+bounds.x>parent.getWidth()))
                        dragLocation.x=(int) point.getX();
                    if(bounds.x<0)
                        bounds.x=0;
                }
                if(bounds.y<0 ||bounds.height+bounds.y>parent.getHeight()) {
                    bounds.height = getHeight();
                    if(bottom &&!(bounds.height+bounds.y>parent.getHeight()))
                        dragLocation.y=(int) point.getY();
                    if(bounds.y<0)
                        bounds.y=0;
                }
                //justify any other component in it's way
                for(Component c:parent.getComponents()) {
                    if(!c.equals(this) &&c.getBounds().intersects(bounds)) {
                        evaluateOverlaps(bounds, c,point);
                    }
                }
                setBounds(bounds);
            }
            private Rectangle evaluateOverlaps(Rectangle bounds , Component component,Point point) {
                if(bounds.intersects(component.getBounds())) {
                    if(component instanceof ResizablePanel) {
                        ResizablePanel panel=(ResizablePanel) component;
                        Rectangle panelBound=panel.getBounds();
                        if(top || bottom) {
                            panelBound.height = panelBound.height - bounds.intersection(panelBound).height;
                            if(panelBound.height<panel.getMinimumSize().height) {
                                panelBound.height=panel.getMinimumSize().height;
                                bounds.height = getHeight();
                                if(top) {
                                    bounds.y = component.getBounds().y+component.getHeight();
                                }
                            }
                            else if(bottom) {
                                panelBound.y = panelBound.y + bounds.intersection(panelBound).height;
                            }
                        }
                        else if(left || right) {
                            panelBound.width = panelBound.width - bounds.intersection(panelBound).width;
                            if(panelBound.width<panel.getMinimumSize().width) {
                                panelBound.width=panel.getMinimumSize().width;
                                bounds.width = getWidth();
                                if(left) {
                                    bounds.x = component.getBounds().x+component.getWidth();
                                }
                            }
                            else if(right) {
                                panelBound.x = panelBound.x + bounds.intersection(panelBound).width;
                            }
                        }
                        panel.setBounds(panelBound);
                        return bounds;
                    }
                    
                    if(left || right) {
                        bounds.width = getWidth();
                        if(left) {
                            bounds.x = component.getBounds().x+component.getWidth();
                        }
                    }
                    if(top || bottom) {
                        bounds.height = getHeight();
                        if(top) {
                            bounds.y = component.getBounds().y+component.getHeight();
                        }
                    }
                }
                return bounds;
            }
            private void setResizeCursor(Point point) {
                if(top) { 
                    if(left) 
                        setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
                    else if(right)  
                        setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
                    else 
                        setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
                }
                else if(bottom) { 
                    if(left)  
                        setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR));
                    else if(right) 
                        setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR));
                    else 
                        setCursor(new Cursor(Cursor.S_RESIZE_CURSOR));
                }
                else if (left) 
                    setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
                else if (right)
                    setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
                else
                    setCursor(Cursor.getDefaultCursor());
            }
            
            private long getNew(double size,double oldMax,double newMax) {
                double value = ((size/oldMax)*newMax);
                return Math.round(value);
            }
        }
        

        【讨论】:

          【解决方案5】:

          您可能必须在父 JFrame(具有边框布局的那个)和子 JFrame 上都指定 JFrame.setResizeable = true;。

          您可能还想在南部边界使用JPanel。

          【讨论】:

          • 他需要调整面板的大小,而不是框架
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-10
          • 2013-10-11
          • 2013-09-28
          • 1970-01-01
          相关资源
          最近更新 更多