Хорошо, я наконец понял, этот Windows интерфейс действительно трудно изменить. Поэтому, если вы хотите использовать Nimbus Look and Feel, вы должны выяснить, почему он заменен Windows Look and Feel. Но если вы хотите придерживаться Windows L & F, вы можете определить новый пользовательский интерфейс для класса Button, который похож на WindowsButtonUI
, но учитывает цвет фона. Для этого я создал класс пользовательского интерфейса, который вызывает Windows L & F, если доступно. Это было особенно сложно, потому что Windows L & F и все его классы не входят в стандартный дистрибутив и поэтому не могут использоваться в исходном коде, поэтому нет расширений с переопределениями, просто делегирование с отражением. Я расширил его, позволив рисовать WindowsButtonUI
в буфере, затем заменив цвет кнопки windows на заданный цвет фона, но оставив все эффекты нарисованными поверх фона (эти синие эффекты при выборе, нажмите et * 1023). *.). Также по-прежнему рисует немного более темную границу, но теперь с немного более темной версией вашего собственного цвета. В то время как код противоположен тому, что вы должны сделать (с большим количеством вызовов отражения) , а замена цвета, похоже, не делает точно того, что я ожидал (исправил проблему ) , я думаю, что результат выглядит довольно хорошо. Примечание: это может выглядеть действительно странно в любой операционной системе, кроме Windows. Чтобы установить новый пользовательский интерфейс и цвет, выполните:
UIManager.put("Button.background", Color.WHITE);
UIManager.put("ButtonUI", CustomWindowsButtonUI.class.getCanonicalName());
И исходный код CustomWindowsButtonUI
:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.metal.MetalButtonUI;
import com.sun.java.swing.plaf.windows.WindowsGraphicsUtils;
import sun.awt.AppContext;
@SuppressWarnings("restriction")
public class CustomWindowsButtonUI extends BasicButtonUI {
private final static Color WINDOWS_BUTTON_COLOR = new Color(225, 225, 225);
private BasicButtonUI delegateUI;
private Class<?> windowsUIClass = null;
private boolean isWindows = false;
private static final Object CUSTOM_WINDOWS_BUTTON_UI_KEY = "CUSTOM_WINDOWS_BUTTON_UI_KEY";
public CustomWindowsButtonUI() {
try {
windowsUIClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsButtonUI");
delegateUI = (BasicButtonUI) windowsUIClass.getConstructor().newInstance();
isWindows = true;
} catch (Throwable e) {
System.err.println("Failed to locate windows button ui, defaulting to MetalUI (Swing default).");
delegateUI = new MetalButtonUI();
}
}
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
CustomWindowsButtonUI customWindowsButtonUI = (CustomWindowsButtonUI) appContext.get(CUSTOM_WINDOWS_BUTTON_UI_KEY);
if (customWindowsButtonUI == null) {
customWindowsButtonUI = new CustomWindowsButtonUI();
appContext.put(CUSTOM_WINDOWS_BUTTON_UI_KEY, customWindowsButtonUI);
}
return customWindowsButtonUI;
}
@Override
public void update(Graphics g, JComponent c) {
paint(g, c);
}
@Override
public void paint(Graphics g, JComponent c) {
if (isWindows) {
int width = c.getWidth();
int height = c.getHeight();
BufferedImage paintBufferImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
delegateUI.paint(paintBufferImage.createGraphics(), c);
Color backgroundColor = c.getBackground();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
Color pixelColor = new Color(paintBufferImage.getRGB(x, y), true);
Color targetColor = new Color(getTargetColorValue(pixelColor.getRed(), WINDOWS_BUTTON_COLOR.getRed(), backgroundColor.getRed()),
getTargetColorValue(pixelColor.getGreen(), WINDOWS_BUTTON_COLOR.getGreen(), backgroundColor.getGreen()),
getTargetColorValue(pixelColor.getBlue(), WINDOWS_BUTTON_COLOR.getBlue(), backgroundColor.getBlue()), pixelColor.getAlpha());
paintBufferImage.setRGB(x, y, targetColor.getRGB());
}
}
g.drawImage(paintBufferImage, 0, 0, null);
} else {
delegateUI.paint(g, c);
}
}
private static int getTargetColorValue(int value, int subtract, int add){
return Math.min(255, Math.max(0, value - subtract + add));
}
protected void installDefaults(AbstractButton b) {
try {
Method method = windowsUIClass.getDeclaredMethod("installDefaults", AbstractButton.class);
method.setAccessible(true);
method.invoke(delegateUI, b);
} catch (Throwable e) {
System.err.println("Failed to call delegate installDefaults: " + e.getClass().getName() + " - " + e.getMessage());
super.installDefaults(b);
}
}
protected void uninstallDefaults(AbstractButton b) {
try {
Method method = windowsUIClass.getDeclaredMethod("uninstallDefaults", AbstractButton.class);
method.setAccessible(true);
method.invoke(delegateUI, b);
} catch (Throwable e) {
System.err.println("Failed to call delegate uninstallDefaults: " + e.getClass().getName() + " - " + e.getMessage());
super.uninstallDefaults(b);
}
}
// copied from WindowsButtonUI
protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
WindowsGraphicsUtils.paintText(g, b, textRect, text, getTextShiftOffset());
}
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
try {
Method method = windowsUIClass.getDeclaredMethod("paintFocus", Graphics.class, AbstractButton.class, Rectangle.class, Rectangle.class, Rectangle.class);
method.setAccessible(true);
method.invoke(delegateUI, g, b, viewRect, textRect, iconRect);
} catch (Throwable e) {
System.err.println("Failed to call delegate paintFocus: " + e.getClass().getName() + " - " + e.getMessage());
super.paintFocus(g, b, viewRect, textRect, iconRect);
}
}
// copied from WindowsButtonUI
protected void paintButtonPressed(Graphics g, AbstractButton b) {
setTextShiftOffset();
}
// copied from WindowsButtonUI
public Dimension getPreferredSize(JComponent c) {
Dimension d = super.getPreferredSize(c);
AbstractButton b = (AbstractButton) c;
if (d != null && b.isFocusPainted()) {
if (d.width % 2 == 0) {
d.width += 1;
}
if (d.height % 2 == 0) {
d.height += 1;
}
}
return d;
}
}