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

查看:125
本文介绍了自定义按钮不能在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天全站免登陆