自定义按钮在 mac 上不起作用(ButtonUI) [英] Custom button not working on mac (ButtonUI)

查看:32
本文介绍了自定义按钮在 mac 上不起作用(ButtonUI)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,它在文本和图标的各个地方使用自定义按钮.适用于 windows 和 linux,但现在 OSX 用户抱怨.Mac 上不显示文本,仅显示...".代码看起来很简单,但我对 mac 一无所知.我该如何解决这个问题?

I've got an application that uses custom buttons all over the place for text and icons. Works great for windows and linux, but now OSX users are complaining. Text doesn't display on the mac, just '...'. The code seems simple enough, but I'm clueless when it comes to macs. How can I fix this?

测试用例:

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 似乎也进入了剪辑区域.可以在哪里设置?

After debugging, it seems getMinimumSize() is the same on both platforms. Also, when I stop on anywhere Graphics is used, it seems that the mac has a transY value of 47, while linux has 0. This 47 seems to feed into the clipping regions as well. Where could that be getting set?

推荐答案

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

Your calculation of preferred size is incorrect.

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

BasicButtonUI uses SwingUtilities.layoutCompoundLabel, examined here. In a label, the ellipsis is added if the string is too long, but a button is typically sized to fit its entire text.

如果没有更好地了解您的上下文,我将使用 sizeVariant,如下所示.我还展示了一个使用较小的派生 Font 的简单 BasicButtonUI 示例.UI 菜单可以与 Quaqua 用于测试.

Absent a better understanding of your context, I would use a sizeVariant, shown below. I've also shown a simple BasicButtonUI example using a smaller, derived Font. The UI menu can be used in conjunction with Quaqua for testing.

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(r.x, r.y, 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<String> names = new ArrayList<String>();
        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;
    }
}

这篇关于自定义按钮在 mac 上不起作用(ButtonUI)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆