如何在Java中创建带有连接按钮的ButtonGroup?

我目前正在尝试创建一组切换按钮,这些按钮类似于Eclipse的格式化程序首选项中使用的切换按钮:

Eclipse的Formatter首选项

目前我已通过以下方式尝试此操作:

public class Exercise extends JFrame { private String[] buttonNames = {"A", "B", "C", "D", "E"}; Exercise() { final JPanel topPanel = new JPanel(); topPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); int tabCount = 0; final ButtonGroup topButtonGroup = new ButtonGroup(); for (String buttonName : buttonNames) { JToggleButton tabButton = new JToggleButton(buttonName); topButtonGroup.add(tabButton); c.fill = GridBagConstraints.HORIZONTAL; c.insets = new Insets(0, -6, 0, -7); // Questionable line c.gridx = tabCount; c.gridy = 0; topPanel.add(tabButton, c); tabCount++; } this.add(topPanel); this.setVisible(true); this.pack(); } public static void main(String[] args) { new Exercise(); } } 

结果如下:

结果没有间距

我的代码有几个问题。 首先,我不明白为什么我必须让插图消极。 根据Oracle的教程 “默认情况下,每个组件都没有外部填充。” 因此,默认情况下不应该没有空格吗? 没有负面插图,结果如下所示:

结果没有设置负插入

其次,我希望切换按钮变暗而不是转为蓝色并切换为“打开”。 有没有简单的方法通过Java Swing做到这一点? 最后,总的来说有没有更好的方法? 我很想知道Eclipse是如何设法让切换按钮看起来好像是完美连接的。

更新

我尝试过按照建议使用BoxLayout。 不幸的是,这似乎没有解决问题。 结果几乎与上图相同。 这是修改后的构造函数:

 Exercise() { final JPanel topPanel = new JPanel(); topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS)); final ButtonGroup topButtonGroup = new ButtonGroup(); for (String buttonName : buttonNames) { JToggleButton tabButton = new JToggleButton(buttonName); // tabButton.setBorder(BorderFactory.createBevelBorder( // BevelBorder.RAISED, Color.LIGHT_GRAY, Color.DARK_GRAY)); topButtonGroup.add(tabButton); topPanel.add(tabButton); } this.add(topPanel); this.setVisible(true); this.pack(); } 

有趣的是,当我尝试添加上面注释的边框时,按钮之间的额外间距不知何故消失了。 结果如下:

使用BoxLayout

我希望尽可能保持按钮的一般外观,但是边缘要更加矩形,以便切换按钮看起来更加连接。

您可以使用BoxLayout之类的布局来消除空间。 GridBagLayout不是唯一的布局。 推荐阅读: http : //docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

您还可以调用JButton函数,如setBorder()和setBackground()来实现您提到的效果。 一如既往,API是您最好的朋友: http : //docs.oracle.com/javase/7/docs/api/

我似乎犯了一个令人尴尬的错误。 我尝试了dic19的建议,即使用Seaglass的外观和感觉以及JTabbedPane,我几乎得到了我想要的东西:

标签窗格与Seaglass

但后来我意识到JTabbedPane的默认外观正是我想要的:

默认外观

我使用的代码类似于Oracle的JTabbedPane教程中使用的代码:

 public class SeaGlassExercise { public static void initWindow() { JFrame frame = new JFrame("Application Name"); CustomTabbedPane content = new CustomTabbedPane(); frame.setContentPane(content); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setLocationByPlatform(true); // try { // UIManager.setLookAndFeel( // "com.seaglasslookandfeel.SeaGlassLookAndFeel"); // } catch (Exception e) { // e.printStackTrace(); // } // SwingUtilities.updateComponentTreeUI(frame); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { initWindow(); } }); } } class CustomTabbedPane extends JPanel { public CustomTabbedPane() { super(new GridLayout(1, 1)); JTabbedPane tabbedPane = new JTabbedPane(); JComponent panel1 = makeTextPanel("Panel #1"); tabbedPane.addTab("AAA", panel1); JComponent panel2 = makeTextPanel("Panel #2"); tabbedPane.addTab("BBB", panel2); JComponent panel3 = makeTextPanel("Panel #3"); tabbedPane.addTab("CCC", panel3); JComponent panel4 = makeTextPanel("Panel #4"); tabbedPane.addTab("DDD", panel4); add(tabbedPane); tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); } protected JComponent makeTextPanel(String text) { JPanel panel = new JPanel(); JLabel filler = new JLabel(text); filler.setHorizontalAlignment(JLabel.CENTER); panel.setLayout(new GridLayout(1, 1)); panel.add(filler); return panel; } } 

虽然我知道Java Swing在各种平台上的默认平台依赖外观和感觉是不同的,但我从未想过JTabbedPane看起来与教程中显示的有很大不同:

Oracle的JTabbedPane图像