自定义按钮不能在mac上工作(ButtonUI)

我有一个应用程序,它使用遍布文本和图标的自定义按钮。 适用于Windows和Linux,但现在OSX用户抱怨。 文本不会显示在Mac上,只是’…’。 代码看起来很简单,但是对于mac来说我很无能为力。 我怎样才能解决这个问题?

测试用例:

package example.swingx; import example.utils.ResourceLoader; import com.xduke.xlayouts.XTableLayout; import javax.swing.*; import javax.swing.plaf.ComponentUI; import java.awt.*; import java.awt.event.ActionEvent; public class SmallButton extends JButton { private static ComponentUI ui = new SmallButtonUI(); public SmallButton() { super(); /* final RepaintManager repaintManager = RepaintManager.currentManager(this); repaintManager.setDoubleBufferingEnabled(false); setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);*/ } public SmallButton(AbstractAction action) { super(action); } public SmallButton(String text) { super(text); } public SmallButton(Icon icon) { super(icon); } public void updateUI() { setUI(ui); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final JPanel buttonPanel = new JPanel(new XTableLayout()); SmallButton firstSmallButton = new SmallButton("One"); SmallButton secondSmallButton = new SmallButton("Two"); SmallButton thirdSmallButton = new SmallButton(); ImageIcon cameraIcon = (ImageIcon) ResourceLoader.getIcon("camera"); SmallButton fourth = new SmallButton(); fourth.setAction(new AbstractAction() { public void actionPerformed(ActionEvent e) { System.out.println("Fourth button pressed!"); } }); fourth.setIcon(cameraIcon); buttonPanel.add(firstSmallButton, "+"); buttonPanel.add(secondSmallButton, "+"); buttonPanel.add(thirdSmallButton, "+"); buttonPanel.add(fourth, "+"); final Container container = frame.getContentPane(); container.add(buttonPanel); frame.pack(); frame.setVisible(true); } } 

用户界面:

 package example.swingx; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicButtonUI; import java.awt.*; public class SmallButtonUI extends BasicButtonUI { private static final Color FOCUS_COLOR = new Color(0, 0, 0); private static final Color BACKGROUND_COLOR = new Color(173, 193, 226); private static final Color SELECT_COLOR = new Color(102, 132, 186); private static final Color DISABLE_TEXT_COLOR = new Color(44, 44, 61); private static final Insets DEFAULT_SMALLBUTTON_MARGIN = new Insets(2, 4, 2, 4); private final static SmallButtonUI smallButtonUI = new SmallButtonUI(); public static ComponentUI createUI(JComponent component) { return smallButtonUI; } protected Color getSelectColor() { return SELECT_COLOR; } protected Color getDisabledTextColor() { return DISABLE_TEXT_COLOR; } protected Color getFocusColor() { return FOCUS_COLOR; } public void paint(Graphics g, JComponent c) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); super.paint(g, c); } protected void paintButtonPressed(Graphics graphics, AbstractButton button) { if (button.isContentAreaFilled()) { Dimension size = button.getSize(); graphics.setColor(getSelectColor()); graphics.fillRect(0, 0, size.width, size.height); } } public Dimension getMinimumSize(JComponent component) { final AbstractButton button = ((AbstractButton) component); // Handle icon buttons: Icon buttonIcon = button.getIcon(); if (buttonIcon != null) { return new Dimension( buttonIcon.getIconWidth(), buttonIcon.getIconHeight() ); } // Handle text buttons: final Font fontButton = button.getFont(); final FontMetrics fontMetrics = button.getFontMetrics(fontButton); final String buttonText = button.getText(); if (buttonText != null) { final int buttonTextWidth = fontMetrics.stringWidth(buttonText); return new Dimension(buttonTextWidth + 15, fontMetrics.getHeight() + 5); } return null; } protected void installDefaults(AbstractButton button) { super.installDefaults(button); button.setMargin(DEFAULT_SMALLBUTTON_MARGIN); button.setBackground(getBackgroundColor()); } private Color getBackgroundColor() { return BACKGROUND_COLOR; } public Dimension getPreferredSize(JComponent component) { return getMinimumSize(component); } public Dimension getMaximumSize(JComponent component) { return super.getMinimumSize(component); } public SmallButtonUI() { super(); } } 

编辑:调试后,似乎两个平台上的getMinimumSize()是相同的。 此外,当我停在使用Graphics的任何地方时,似乎mac的transY值为47,而linux为0.这47似乎也适用于剪辑区域。 那可能在哪里设置?

您的首选大小计算不正确。

BasicButtonUI使用SwingUtilities.layoutCompoundLabel , 在这里检查。 在标签中,如果字符串太长则添加省略号,但按钮的大小通常适合其整个文本。

如果没有更好地理解你的上下文,我会使用sizeVariant ,如下所示。 我还展示了一个使用较小的派生Font的简单BasicButtonUI示例。 UI菜单可与Quaqua结合使用进行测试。

图片

 import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractButton; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.plaf.basic.BasicButtonUI; /** * @see https://stackoverflow.com/a/14599176/230513 * @see https://stackoverflow.com/a/11949899/230513 */ public class Test { private void display() { JFrame f = new JFrame("Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setBackground(new Color(0xfff0f0f0)); f.setLayout(new GridLayout(0, 1)); f.add(createToolBar(f)); f.add(variantPanel("mini")); f.add(variantPanel("small")); f.add(variantPanel("regular")); f.add(variantPanel("large")); JPanel customPanel = new JPanel(); customPanel.add(createCustom("One")); customPanel.add(createCustom("Two")); customPanel.add(createCustom("Three")); f.add(customPanel); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } private static JPanel variantPanel(String size) { JPanel variantPanel = new JPanel(); variantPanel.add(createVariant("One", size)); variantPanel.add(createVariant("Two", size)); variantPanel.add(createVariant("Three", size)); return variantPanel; } private static JButton createVariant(String name, String size) { JButton b = new JButton(name); b.putClientProperty("JComponent.sizeVariant", size); return b; } private static JButton createCustom(String name) { JButton b = new JButton(name) { @Override public void updateUI() { super.updateUI(); setUI(new CustomButtonUI()); } }; return b; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new Test().display(); } }); } private static class CustomButtonUI extends BasicButtonUI { private static final Color BACKGROUND_COLOR = new Color(173, 193, 226); private static final Color SELECT_COLOR = new Color(102, 132, 186); @Override protected void paintText(Graphics g, AbstractButton b, Rectangle r, String t) { super.paintText(g, b, r, t); g.setColor(SELECT_COLOR); g.drawRect(rx, ry, r.width, r.height); } @Override protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { super.paintFocus(g, b, viewRect, textRect, iconRect); g.setColor(Color.blue.darker()); g.drawRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height); } @Override protected void paintButtonPressed(Graphics g, AbstractButton b) { if (b.isContentAreaFilled()) { g.setColor(SELECT_COLOR); g.fillRect(0, 0, b.getWidth(), b.getHeight()); } } @Override protected void installDefaults(AbstractButton b) { super.installDefaults(b); b.setFont(b.getFont().deriveFont(11f)); b.setBackground(BACKGROUND_COLOR); } public CustomButtonUI() { super(); } } private static JToolBar createToolBar(final Component parent) { final UIManager.LookAndFeelInfo[] available = UIManager.getInstalledLookAndFeels(); List names = new ArrayList(); for (UIManager.LookAndFeelInfo info : available) { names.add(info.getName()); } final JComboBox combo = new JComboBox(names.toArray()); String current = UIManager.getLookAndFeel().getName(); combo.setSelectedItem(current); combo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { int index = combo.getSelectedIndex(); try { UIManager.setLookAndFeel( available[index].getClassName()); SwingUtilities.updateComponentTreeUI(parent); } catch (Exception e) { e.printStackTrace(System.err); } } }); JToolBar bar = new JToolBar("L&F"); bar.setLayout(new FlowLayout(FlowLayout.LEFT)); bar.add(combo); return bar; } }