有点奇怪,如果我做以下事情就看到了:
import javax.swing.*;
public class FunkyButtonLayout {
public static void main(String[] args) {
JFrame frame = new JFrame("");
JPanel j0 = new JPanel(); // j0 gets added to the root pane
j0.setLayout(null);
JPanel j1 = new JPanel(); // j1 gets added to j0
j1.setLayout(null);
JButton b1 = new JButton(""); // b1 gets added to j1
j1.add(b1);
b1.setBounds(0, 0, 40, 32); // b1 is big
j0.add(j1);
j1.setBounds(0, 0, 32, 32); // j1 is not so big - b1 gets 'trimmed'
frame.getContentPane().setLayout(null); // <- seems to be needed :-(
frame.getContentPane().add(j0);
j0.setBounds(10, 10, 32, 32); // end result: a 32x32 button with
frame.setSize(125, 125); // a trimmed right border
frame.setVisible(true); // in the top-left corner
}
}
除了能够使用布局管理器在根窗格中定位j0之外,我得到了我正在寻找的东西。如果我改变了
frame.getContentPane().setLayout(null);
行到
frame.getContentPane().setLayout(new java.awt.FlowLayout());
我在屏幕中间看到j0绘制为1x1像素: - (
任何想法为什么?请注意,这不仅仅是一个FlowLayout事情 - 几乎每个布局管理器都会混淆它。
我真的希望得到'边框修剪一边'按钮的净效果 - 它允许我做工具栏 - 按钮 - 群集的事情(cage fighter试图摆脱的那种事情)具有原生外观的按钮控件 - 由于操作系统级别的皮肤,我无法看到另一种方法。所以任何想法都赞赏: - )
答案 0 :(得分:4)
如果将布局管理器设置为null,则必须明确设置容器的首选大小(这就是它显示如此之小的原因)。
如果在组件上使用setBounds,则会占用父容器的布局管理器所做的工作。
我将删除对setBounds的所有调用以及对setLayout(null)的所有调用,并尝试实现仅使用布局管理器后的效果。
答案 1 :(得分:1)
......任何想法为什么?
是。发生这种情况是因为当您删除布局管理器(通过将其设置为null)时,您对计算机说“我将完成所有铺设工作”;使用任何其他LayoutManager时,将尝试...根据您的需要(根据要放置的对象的属性)布置组件
所以,我认为尝试创建一个Border实例并将其设置为JButton而不是尝试调整它周围的所有对象会更好。
我会看看能否快速提出一些事情。
修改强>
哎呀,它不是很快,但它就在这里(我弄乱了一条令我讨厌的1px线) alt text http://img22.imageshack.us/img22/8933/capturaby8.png
正如我之前所说,将布局设置为null并不是最好的方法。更好的方法是创建自定义边框并将其设置为按钮(或设置空边框)。
以下是代码:
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.awt.geom.*;
/**
* Sample usage of swing borders.
* @author <a href="http://stackoverflow.com/users/20654">Oscar Reyes</a>
*/
public class ButtonBorderSample {
public static void main( String [] args ) {
// Pretty standard swing code
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel panel = new JPanel( new FlowLayout(
FlowLayout.CENTER, 0, 5 ) );
panel.add( createButton( "F I R S T" ) );
panel.add( createButton( "S E C O N D" ) );
panel.add( createButton( "T H I R D " ) );
frame.add( panel , BorderLayout.NORTH );
frame.pack();
frame.setVisible( true );
}
/**
* Utility method to create a button.
* Creates the button, make it square, and add our custom border.
*/
private static JButton createButton( String s ) {
JButton b = new JButton( s );
b.setPreferredSize( new Dimension( 100, 100 ) );
b.setBorder( new NoGapBorder() );
return b;
}
}
/**
* This border implementation. It doesn't have insets and draws only a
* few parts of the border
* @author <a href="http://stackoverflow.com/users/20654">Oscar Reyes</a>
*/
class NoGapBorder implements Border {
private final Insets insets = new Insets( -1, -1 , -1, -1 );
/**
* Defines in Border interface.
* @return The default insets instace that specifies no gap at all.
*/
public Insets getBorderInsets(Component c ) {
return insets;
}
/**
* Defines in Border interface.
* @return false always, it is not relevant.
*/
public boolean isBorderOpaque() {
return false;
}
/**
* Paint the border for the button.
* This creates the difference between setting the border to null
* and using this class.
* It only draws a line in the top, a line in the bottom and a
* darker line
* in the left, to create the desired effect.
* A much more complicated strtegy could be used here.
*/
public void paintBorder(Component c, Graphics g,
int x, int y, int width, int height) {
Color oldColor = g.getColor();
int h = height;
int w = width;
g.translate(x, y);
// Color for top and bottom
g.setColor( c.getBackground().brighter() );
// draw top line
g.drawLine(1, 0, w-2, 0);
// draw bottom line
g.drawLine(0, h-1, w-1, h-1);
// change the color to make it look as a division
g.setColor( c.getBackground().darker() );
// draw the left line
g.drawLine(0, 0, 0, h-2);
// set the graphics back to its original state.
g.translate(-x, -y);
g.setColor(oldColor);
}
}
编辑
Dave Carpeneto写道:
** Oscar&gt; ***不幸的是,一旦你UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); ,这也是我的需求的核心(我希望尽可能让这看起来像本地人一样)。*
好吧,我没有尝试过你的工作,但回答你的问题,你认为你的问题与LayoutManagers有关,我说这不是问题。
也许我应该停在那里,但我的“程序员”痒让我继续这个样本。 :)
我很高兴你最终解决了你的问题;)
答案 2 :(得分:1)
有关布局管理器如何工作的非常好的解释,请查看我在Sun写的一篇旧文章
http://developer.java.sun.com/developer/onlineTraining/GUI/AWTLayoutMgr/
它已经过时了,但谈到preferredSize和布局很好。
享受, - 斯科特
答案 3 :(得分:0)
Dan&gt; 这是您对首选布局的评论让我开始工作 - 只需添加j0.setPreferredSize(new java.awt.Dimension(32, 32));
就可以实现这一点。
奥斯卡&gt; 不幸的是,一旦你UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
,这就停止了工作,这也是我需要的核心(我希望尽可能让它看起来像本机一样)。
例如,这是我在XP上用3个按钮看起来的样子:
alt text http://img19.imageshack.us/img19/8595/minems5.png
...这就是你看起来像XP外观的样子:
alt text http://img102.imageshack.us/img102/5412/yoursod4.png
......不幸的是,这不是同一件事 - 抱歉我的要求不清楚: - (
FWIW,这是代码(图像是与按钮大小相同的透明图标,垂直线作为图标的一部分):
import java.awt.*;
import javax.swing.*;
public class FunkyButtonLayout {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
}
JFrame frame = new JFrame("x");
Container y = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
y.setLayout(new FlowLayout());
JPanel uberButton = new JPanel();
uberButton.setLayout(null);
uberButton.setSize(98, 32);
uberButton.setPreferredSize(new Dimension(98, 32));
JButton record = new JButton(new ImageIcon("img/record.png"));
record.setBounds(0, 0, 40, 32);
record.setEnabled(true);
record.setFocusPainted(false);
JPanel _record = new JPanel();
_record.setLayout(null);
_record.setBounds(0, 0, 33, 32);
JButton pause = new JButton(new ImageIcon("img/pause.png"));
pause.setBounds(-4, 0, 44, 32);
pause.setEnabled(true);
pause.setFocusPainted(false);
JPanel _pause = new JPanel();
_pause.setLayout(null);
_pause.setBounds(33, 0, 33, 32);
JButton stop = new JButton(new ImageIcon("img/stop.png"));
stop.setBounds(-4, 0, 36, 32);
stop.setEnabled(true);
stop.setFocusPainted(false);
JPanel _stop = new JPanel();
_stop.setLayout(null);
_stop.setBounds(66, 0, 32, 32);
_record.add(record);
_pause.add(pause);
_stop.add(stop);
uberButton.add(_record);
uberButton.add(_pause);
uberButton.add(_stop);
y.add(uberButton);
frame.pack();
frame.setVisible(true);
}
}
Scott&gt; 我受过教育:-) thanks