我是Java的新手,所以我希望我不要过于复杂化我的问题。
基本上我正在尝试将两个JToolbar垂直添加到一个边框布局的北容器中。但是,我不认为你可以在边框布局中添加多个JToolbar到单个位置容器,所以我想到的可能解决方案是在borderlayout中嵌入一个borderlayout并将一个置于北方,另一个位于中心,但我不知道如何实现这一目标。任何有关实现这一目标的最佳解决方案的建议将不胜感激。
以下是我的程序的源代码。为了让我的程序运行,我想要的第二个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();
}
答案 0 :(得分: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);
答案 1 :(得分:0)
基于 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
中有一个拼写错误,它还扩展了 BorderLayout 继承了一些方法(即 public Component getLayoutComponent(Object constraints)
)或对这种情况没有意义的假设。