Swing/MenuBarLayout のバックアップの現在との差分(No.1)
TITLE:JMenuBarのJMenuを折り返し
Posted by terai at 2010-12-27
JMenuBarのJMenuを折り返し
JMenuBarのレイアウトマネージャーを変更して、JMenuを折り返して表示します。- category: swing folder: MenuBarLayout title: JMenuBarのJMenuを折り返し tags: [JMenuBar, JMenu, LayoutManager, FlowLayout] author: aterai pubdate: 2010-12-27T11:25:50+09:00 description: JMenuBarのレイアウトマネージャーを変更して、JMenuを折り返して表示します。 image:
概要
JMenuBar
のレイアウトマネージャーを変更して、JMenu
を折り返して表示します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
#screenshot
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
JMenuBar menuBar = new JMenuBar();
#spandel
menuBar.setLayout(new FlowLayout(FlowLayout.LEFT,2,2) {
#spanend
#spanadd
menuBar.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2) {
#spanend
@Override public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
int targetWidth = target.getSize().width;
if (targetWidth == 0) targetWidth = Integer.MAX_VALUE;
targetWidth = targetWidth == 0 ? Integer.MAX_VALUE : targetWidth;
Insets insets = target.getInsets();
int hgap = getHgap();
int vgap = getVgap();
int maxWidth = targetWidth - (insets.left + insets.right);
int height = vgap;
int rowWidth = hgap, rowHeight = 0;
int nmembers = target.getComponentCount();
for(int i = 0; i < nmembers; i++) {
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if(m.isVisible()) {
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
if(rowWidth + d.width > maxWidth) {
if (rowWidth + d.width > maxWidth) {
height += rowHeight;
rowWidth = hgap;
rowHeight = 0;
}
rowWidth += d.width + hgap;
rowHeight = Math.max(rowHeight, d.height + vgap);
}
}
height += rowHeight + insets.top + insets.bottom;
return new Dimension(targetWidth, height);
}
}
#spandel
};
#spanend
#spanadd
});
#spanend
解説
上記のサンプルでは、JMenuBar(デフォルトのレイアウトマネージャーはBoxLayout)に、FlowLayoutを継承して折り返しを行うレイアウトマネージャを設定して、JMenuがフレームの幅に収まらない場合は折り返して表示するようにしています。解説
上記のサンプルでは、JMenuBar
にFlowLayout
を継承して折り返しを行うLayoutManager
を設定して(JMenuBar
のデフォルトLayoutManager
はBoxLayout
)、内部のJMenu
などがフレームの幅に収まらない場合は折り返して表示しています。
- - 上記のサンプルでは、BorderLayoutを設定したJPanelにadd(menubar, BorderLayout.NORTH)としてJMenuBarを追加していますが、JFrame#setJMenuBar メソッドを使用した場合、以下のような不具合?があります。
- JFrameの最大化、最小化で折り返しが更新されない
- 以下のように、FlowLayout#layoutContainerをオーバーライドすることで回避
-
BorderLayout
を設定したJPanel#add(menubar, BorderLayout.NORTH)
としてJMenuBar
を追加してJFrame#setJMenuBar(...)
メソッドを使用した場合、以下のような不具合が存在する?-
JFrame
の最大化、最小化で折り返しが更新されない - 以下のような
WindowStateListener
をJFrame
に追加し、ContentPane
をrevalidate()
して回避#spandel //http://tips4java.wordpress.com/2008/11/06/wrap-layout/ #spanend #spandel //WrapLayout.java #spanend #spandel //Rob Camick on November 6, 2008 #spanend #spanadd frame.addWindowStateListener(new WindowStateListener() { #spanend @Override public void windowStateChanged(final WindowEvent e) { EventQueue.invokeLater(new Runnable() { @Override public void run() { System.out.println("windowStateChanged"); JFrame f = (JFrame) e.getWindow(); ((JComponent) f.getContentPane()).revalidate(); } }); } #spanadd }); #spanend #spanadd // frame.getContentPane().addComponentListener(new ComponentAdapter() { #spanend #spanadd // @Override public void componentResized(ComponentEvent e) { #spanend #spanadd // ((JComponent) e.getSource()).revalidate(); #spanend #spanadd // } #spanend #spanadd // }); #spanend #spanadd
-
FlowLayout#layoutContainer
をオーバーライドすることで回避
#spanend
#spanadd
// https://tips4java.wordpress.com/2008/11/06/wrap-layout/
#spanend
#spanadd
// WrapLayout.java
#spanend
#spanadd
// Rob Camick on November 6, 2008
#spanend
private Dimension preferredLayoutSize;
@Override public void layoutContainer(Container target) {
Dimension size = preferredLayoutSize(target);
if(size.equals(preferredLayoutSize)) {
if (size.equals(preferredLayoutSize)) {
super.layoutContainer(target);
}else{
} else {
preferredLayoutSize = size;
Container top = target;
while(!(top instanceof Window) && top.getParent() != null) {
while (!(top instanceof Window) && top.getParent() != null) {
top = top.getParent();
}
top.validate();
}
}
- JFrame#setSize(...)に変更することで回避
-
JFrame#pack()
してもJFrame
のサイズが変更されない-
JFrame#setSize(...)
に変更することで回避
-