java - oyaha - El botón personalizado no funciona en mac(ButtonUI)
native look and feel (1)
Su cálculo del tamaño preferido es incorrecto.
BasicButtonUI
usa SwingUtilities.layoutCompoundLabel
, que se examina aquí . En una etiqueta, los puntos suspensivos se agregan si la cadena es demasiado larga, pero un botón suele tener el tamaño adecuado para todo el texto.
En ausencia de una mejor comprensión de su contexto, utilizaría un sizeVariant
, que se muestra a continuación. También he mostrado un ejemplo simple de BasicButtonUI
usando una Font
derivada más pequeña. El menú de la interfaz de usuario se puede usar junto con Quaqua para realizar pruebas.
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;
}
}
Tengo una aplicación que usa botones personalizados por todo el lugar para texto e iconos. Funciona muy bien para Windows y Linux, pero ahora los usuarios de OSX se quejan. El texto no se muestra en el mac, solo ''...''. El código parece bastante simple, pero no tengo idea cuando se trata de Mac. ¿Cómo puedo arreglar esto?
Caso de prueba:
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);
}
}
UI:
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();
}
}
EDITAR: después de la depuración, parece que getMinimumSize () es el mismo en ambas plataformas. Además, cuando paro en cualquier lugar donde se use Graphics, parece que el mac tiene un valor de transY de 47, mientras que linux tiene 0. Este 47 parece alimentar también a las regiones de clipping. ¿Dónde podría estar eso arreglando?