【问题标题】:Add two JToolBars to a border layout.将两个 JToolBar 添加到边框布局。
【发布时间】:2013-11-28 06:16:25
【问题描述】:

我对 Java 还很陌生,所以希望我的问题不会过于复杂。

基本上,我正在尝试将两个 JToolbar 垂直叠加到边框布局的北容器中。但是,我认为您不能将多个 JToolbar 添加到边框布局内的单个位置容器中,因此我认为可能的解决方案是在边框布局中嵌入一个边框布局,并将一个放在北部,另一个放在中心,但我不知道如何实现这一点。任何关于什么是实现这一目标的最佳解决方案的建议将不胜感激。

以下是我的程序的源代码。为了使我的程序运行,我想要的第二个 JToolbar 在“bar”JToolbar 下的位置已放置在南容器中。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FeedBar2 extends JFrame {

public FeedBar2() {
    super("FeedBar 2");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // create icons
    ImageIcon loadIcon = new ImageIcon("load.gif");
    ImageIcon saveIcon = new ImageIcon("save.gif");
    ImageIcon subscribeIcon = new ImageIcon("subscribe.gif");
    ImageIcon unsubscribeIcon = new ImageIcon("unsubscribe.gif");
    // create buttons
    JButton load = new JButton("Load", loadIcon);
    JButton save = new JButton("Save", saveIcon);
    JButton subscribe = new JButton("Subscribe", subscribeIcon);
    JButton unsubscribe = new JButton("Unsubscribe", unsubscribeIcon);

    //create help buttons
    JButton help = new JButton("Help");
    JButton about = new JButton("About");
    JButton contact = new JButton("Contact Us");

    // add buttons to toolbar
    JToolBar bar = new JToolBar();
    bar.add(load);
    bar.add(save);
    bar.add(subscribe);
    bar.add(unsubscribe);

    //add buttons to help toolbar
    JToolBar helpbar = new JToolBar();
    helpbar.add(help);
    helpbar.add(about);
    helpbar.add(contact);

    // create dropdown menu
    JMenuItem j1 = new JMenuItem("Load");
    JMenuItem j2 = new JMenuItem("Save");
    JMenuItem j3 = new JMenuItem("Subscribe");
    JMenuItem j4 = new JMenuItem("Unsubscribe");
    JMenuItem h1 = new JMenuItem("Help");
    JMenuItem h2 = new JMenuItem("About");
    JMenuItem h3 = new JMenuItem("Contact Us");
    JMenuBar menubar = new JMenuBar();
    JMenuBar helpmenubar = new JMenuBar();
    JMenu menu = new JMenu("Feeds");
    menu.add(j1);
    menu.add(j2);
    menu.addSeparator();
    menu.add(j3);
    menu.add(j4);


    JMenu helpmenu = new JMenu("Help");
    helpmenu.add(h1);
    helpmenu.add(h2);
    helpmenu.add(h3);
    menubar.add(menu);
    menubar.add(helpmenu);

    // prepare user interface
    JTextArea edit = new JTextArea(8, 40);

    JScrollPane scroll = new JScrollPane(edit);

   BorderLayout bord = new BorderLayout();


   //Looking for the "help bar" to be vertically placed under the "bar" 
   //toolbar.

    setLayout(bord); 
    add("North", bar);
    add("Center", scroll);
    add("South", helpbar);

    setJMenuBar(menubar);



    pack();
    setVisible(true);
}

public static void main(String[] arguments) {
    FeedBar2 frame = new FeedBar2();
}

【问题讨论】:

    标签: java swing jpanel border-layout jtoolbar


    【解决方案1】:

    我会使用 GridLayout:

    //setLayout(bord); // the default layout of a frame is a BorderLayout
    //add("North", bar); // don't use String literals, the API has variables for you to use
    //add("Center", scroll);
    //add("South", helpbar);
    
    
    JPanel toolbars = new JPanel( new GridLayout(0, 1) );
    toolbars.add(bar);
    toolbars.add(helpBar);
    
    add(toolBars, BorderLayout.NORTH)
    add(scroll, BorderLayout.CENTER);
    

    【讨论】:

      【解决方案2】:

      根据来自 Stanislav Lapitsky 的这段代码 (http://java-sl.com/tip_multiple_floatable_toolbars.html),这是一个新布局的工作实现,其行为类似于 BorderLayout,但您可以在每个位置添加多个子项,包括工具栏:

      
      import java.awt.BorderLayout;
      import java.awt.Component;
      import java.awt.Container;
      import java.awt.Dimension;
      import java.awt.Insets;
      import java.awt.LayoutManager2;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Vector;
      
      /**
       * Extends BorderLayout with multiple components in the northList, southList,
       * eastList, westList and centerList. Layout is used for correct working
       * multiple toolbars.
       *
       * @author Stanislav Lapitsky
       * @version 1.0
       */
      
      public class MultiBorderLayout implements LayoutManager2, java.io.Serializable {
        private int vgap;
        private int hgap;
        /**
         * list of the northList region components
         */
        private Vector<Component> northList = new Vector<>();
      
        /**
         * list of the southList region components
         */
        private Vector<Component> southList = new Vector<>();
      
        /**
         * list of the westList region components
         */
        private Vector<Component> westList = new Vector<>();
      
        /**
         * list of the eastList region components
         */
        private Vector<Component> eastList = new Vector<>();
      
        /**
         * list of the centerList region components
         */
        private Vector<Component> centerList = new Vector<>();
      
        /**
         * Constructs default layout instance.
         */
        public MultiBorderLayout() {
          this( 0, 0 );
        }
      
        /**
         * Constructs new layout instance with defined parameters.
         *
         * @param hgap the horizontal gap.
         * @param vgap the vertical gap.
         */
        public MultiBorderLayout( int hgap, int vgap ) {
          this.hgap = hgap;
          this.vgap = vgap;
        }
      
        /**
         * Returns the horizontal gap between components.
         *
         * @return the horizontal gap between components
         */
        public int getHgap() {
          return hgap;
        }
      
        /**
         * Sets the horizontal gap between components.
         *
         * @param hgap the horizontal gap between components
         */
        public void setHgap( int hgap ) {
          this.hgap = hgap;
        }
      
        /**
         * Returns the vertical gap between components.
         *
         * @return the vertical gap between components
         */
        public int getVgap() {
          return vgap;
        }
      
        /**
         * Sets the vertical gap between components.
         *
         * @param vgap the vertical gap between components
         */
        public void setVgap( int vgap ) {
          this.vgap = vgap;
        }
      
        private List<Component> getComponentList( Object constraint ) {
          if ( BorderLayout.CENTER.equals( constraint ) ) {
            return centerList;
          }
          if ( BorderLayout.NORTH.equals( constraint ) ) {
            return northList;
          }
          if ( BorderLayout.SOUTH.equals( constraint ) ) {
            return southList;
          }
          if ( BorderLayout.EAST.equals( constraint ) ) {
            return eastList;
          }
          if ( BorderLayout.WEST.equals( constraint ) ) {
            return westList;
          }
      
          throw new IllegalArgumentException( "Unknown constraint: " + constraint );
        }
      
        /**
         * Removes the specified component from this border layout. This method is
         * called when a container calls its <code>remove</code> or
         * <code>removeAll</code> methods. Most applications do not call this method
         * directly.
         *
         * @param comp the component to be removed.
         */
        public void removeLayoutComponent( Component comp ) {
          synchronized ( comp.getTreeLock() ) {
            southList.remove( comp );
            northList.remove( comp );
            centerList.remove( comp );
            westList.remove( comp );
            eastList.remove( comp );
          }
        }
      
        /**
         * Determines the minimum size of the <code>target</code> container using this
         * layout manager.
         * <p>
         *
         * This method is called when a container calls its <code>getMinimumSize</code>
         * method. Most applications do not call this method directly.
         *
         * @param target the container in which to do the layout.
         * @return the minimum dimensions needed to lay out the subcomponents of the
         *         specified container.
         */
        public Dimension minimumLayoutSize( Container target ) {
          synchronized ( target.getTreeLock() ) {
            Dimension dim = new Dimension( 0, 0 );
      
            Component c;
      
            if ( eastList.size() > 0 ) {
              for ( int i = 0; i < eastList.size(); i++ ) {
                c = (Component) eastList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getMinimumSize();
                dim.width += d.width + this.getHgap();
                dim.height = Math.max( d.height, dim.height );
              }
            }
            if ( westList.size() > 0 ) {
              for ( int i = 0; i < westList.size(); i++ ) {
                c = (Component) westList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getMinimumSize();
                dim.width += d.width + this.getHgap();
                dim.height = Math.max( d.height, dim.height );
              }
            }
            if ( centerList.size() > 0 ) {
              for ( int i = 0; i < centerList.size(); i++ ) {
                c = (Component) centerList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getMinimumSize();
                dim.width += d.width;
                dim.height = Math.max( d.height, dim.height );
              }
            }
            if ( northList.size() > 0 ) {
              for ( int i = 0; i < northList.size(); i++ ) {
                c = (Component) northList.get( i );
                if ( !c.isVisible() ) {
      
                  continue;
                }
                Dimension d = c.getMinimumSize();
                dim.width = Math.max( d.width, dim.width );
                dim.height += d.height + this.getVgap();
              }
            }
            if ( southList.size() > 0 ) {
              for ( int i = 0; i < southList.size(); i++ ) {
                c = (Component) southList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getMinimumSize();
                dim.width = Math.max( d.width, dim.width );
                dim.height += d.height + this.getVgap();
              }
            }
      
            Insets insets = target.getInsets();
            dim.width += insets.left + insets.right;
            dim.height += insets.top + insets.bottom;
      
            return dim;
          }
      
        }
      
        /**
         * Determines the preferred size of the <code>target</code> container using this
         * layout manager, based on the components in the container.
         * <p>
         *
         * Most applications do not call this method directly. This method is called
         * when a container calls its <code>getPreferredSize</code> method.
         *
         * @param target the container in which to do the layout.
         * @return the preferred dimensions to lay out the subcomponents of the
         *         specified container.
         */
      
        @Override
        public Dimension preferredLayoutSize( Container target ) {
          synchronized ( target.getTreeLock() ) {
            Dimension dim = new Dimension( 0, 0 );
      
            Component c;
      
            if ( eastList.size() > 0 ) {
              for ( int i = 0; i < eastList.size(); i++ ) {
                c = (Component) eastList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                dim.width += d.width + this.getHgap();
                dim.height = Math.max( d.height, dim.height );
              }
            }
      
            if ( westList.size() > 0 ) {
              for ( int i = 0; i < westList.size(); i++ ) {
                c = (Component) westList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                dim.width += d.width + this.getHgap();
                dim.height = Math.max( d.height, dim.height );
              }
            }
      
            if ( centerList.size() > 0 ) {
              for ( int i = 0; i < centerList.size(); i++ ) {
                c = (Component) centerList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                dim.width += d.width;
                dim.height = Math.max( d.height, dim.height );
              }
            }
      
            if ( northList.size() > 0 ) {
              for ( int i = 0; i < northList.size(); i++ ) {
                c = (Component) northList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                dim.width = Math.max( d.width, dim.width );
                dim.height += d.height + this.getVgap();
              }
            }
      
            if ( southList.size() > 0 ) {
              for ( int i = 0; i < southList.size(); i++ ) {
                c = (Component) southList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                dim.width = Math.max( d.width, dim.width );
                dim.height += d.height + this.getVgap();
              }
            }
      
            Insets insets = target.getInsets();
            dim.width += insets.left + insets.right;
            dim.height += insets.top + insets.bottom;
      
            return dim;
          }
        }
      
        /**
         * Lays out the container argument using this border layout.
         * <p>
         *
         * This method actually reshapes the components in the specified container in
         * order to satisfy the constraints of this <code>BorderLayout</code> object.
         * The <code>NORTH</code> and <code>SOUTH</code> components, if any, are placed
         * at the top and bottom of the container, respectively. The <code>WEST</code>
         * and <code>EAST</code> components are then placed on the left and right,
         * respectively. Finally, the <code>CENTER</code> object is placed in any
         * remaining space in the middle.
         * <p>
         *
         * Most applications do not call this method directly. This method is called
         * when a container calls its <code>doLayout</code> method.
         *
         * @param target the container in which to do the layout.
         */
        public void layoutContainer( Container target ) {
          synchronized ( target.getTreeLock() ) {
            Insets insets = target.getInsets();
            int top = insets.top;
            int bottom = target.getHeight() - insets.bottom;
            int left = insets.left;
            int right = target.getWidth() - insets.right;
      
            Component c;
      
            if ( northList.size() > 0 ) {
              for ( int i = 0; i < northList.size(); i++ ) {
                c = (Component) northList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                c.setSize( right - left, d.height );
                c.setBounds( left, top, right - left, c.getHeight() );
                top += d.height;
              }
            }
      
            if ( southList.size() > 0 ) {
              for ( int i = 0; i < southList.size(); i++ ) {
                c = (Component) southList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                c.setSize( right - left, d.height );
                c.setBounds( left, bottom - d.height, right - left, c.getHeight() );
                bottom -= d.height;
              }
            }
      
            if ( eastList.size() > 0 ) {
              for ( int i = 0; i < eastList.size(); i++ ) {
                c = (Component) eastList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                c.setSize( d.width, bottom - top );
                c.setBounds( right - d.width, top, c.getWidth(), bottom - top );
                right -= d.width;
              }
            }
      
            if ( westList.size() > 0 ) {
              for ( int i = 0; i < westList.size(); i++ ) {
                c = (Component) westList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                Dimension d = c.getPreferredSize();
                c.setSize( d.width, bottom - top );
                c.setBounds( left, top, c.getWidth(), bottom - top );
                left += d.width;
              }
            }
      
            if ( centerList.size() > 0 ) {
              for ( int i = 0; i < centerList.size(); i++ ) {
                c = (Component) centerList.get( i );
                if ( !c.isVisible() ) {
                  continue;
                }
                c.setBounds( left, top, right - left, bottom - top );
              }
            }
      
          }
        }
      
        public List<Component> getLayoutComponents( Object constraints ) {
          if ( ( constraints == null ) || ( constraints instanceof String ) ) {
            // Return copy, don't expose internal Vectors
            return new ArrayList<>( getComponentList( constraints == null ? BorderLayout.CENTER : (String) constraints ) );
          }
          throw new IllegalArgumentException( "Cannot get layout components: constraint must be a string (or null)" );
        }
      
        /**
         * Adds the specified component to the layout, using the specified constraint
         * object. For border layouts, the constraint must be one of the following
         * constants: <code>NORTH</code>, <code>SOUTH</code>, <code>EAST</code> ,
         * <code>WEST</code>, or <code>CENTER</code>.
         * <p>
         *
         * Most applications do not call this method directly. This method is called
         * when a component is added to a container using the <code>Container.add</code>
         * method with the same argument types.
         *
         * @param name The feature to be added to the LayoutComponent attribute.
         * @param comp the component to be added.
         */
      
        @Override
        public void addLayoutComponent( Component comp, Object constraints ) {
          synchronized ( comp.getTreeLock() ) {
            if ( ( constraints == null ) || ( constraints instanceof String ) ) {
              addLayoutComponent( (String) constraints, comp );
            } else {
              throw new IllegalArgumentException( "cannot add to layout: constraint must be a string (or null)" );
            }
          }
        }
      
        /**
         * Returns the maximum dimensions for this layout given the components in the
         * specified target container.
         * 
         * @param target the component which needs to be laid out
         * @see Container
         * @see #minimumLayoutSize
         * @see #preferredLayoutSize
         */
        @Override
        public Dimension maximumLayoutSize( Container target ) {
          return new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE );
        }
      
        /**
         * Returns the alignment along the x axis. This specifies how the component
         * would like to be aligned relative to other components. The value should be a
         * number between 0 and 1 where 0 represents alignment along the origin, 1 is
         * aligned the furthest away from the origin, 0.5 is centered, etc.
         */
        public float getLayoutAlignmentX( Container parent ) {
          return 0.5f;
        }
      
        /**
         * Returns the alignment along the y axis. This specifies how the component
         * would like to be aligned relative to other components. The value should be a
         * number between 0 and 1 where 0 represents alignment along the origin, 1 is
         * aligned the furthest away from the origin, 0.5 is centered, etc.
         */
        public float getLayoutAlignmentY( Container parent ) {
          return 0.5f;
        }
      
        @Override
        public void invalidateLayout( Container target ) {
        }
      
        @Override
        public void addLayoutComponent( String name, Component comp ) {
      
          synchronized ( comp.getTreeLock() ) {
            /*
             * Special case: treat null the same as "Center".
             */
            if ( name == null ) {
              name = "Center";
            }
      
            getComponentList( name ).add( comp );
      
          }
        }
      
      }
      

      原始代码在方法名称preferredLayoutSize 中有错字,它还扩展了继承某些方法(即public Component getLayoutComponent(Object constraints))的BorderLayout 或对这种情况没有意义的假设。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        • 2015-02-28
        相关资源
        最近更新 更多