WindowsLookAndFeel неожиданное поведение в отношении окраски кнопок

Используя WindowsLookAndFeel, который выбирается

UIManager.getSystemLookAndFeelClassName()

так как я работаю на Windows приводит к неожиданному поведению. Цвет фона кнопок меняется. Иногда они не в моем текущем проекте, но я не могу определить разницу.

Кнопки с неправильным поведением:

https://stackru.com/images/4ed878a124ab5819c7a7812a6e0058835ef6d881.png

Кнопки со стандартным LookAndFeel:

https://stackru.com/images/3e1c0dfdadbd4434c15d53ec2b469524b97e2d6e.png

Я приведу рабочий пример, приводящий к неожиданному поведению:

import javax.swing.UIManager;

public class Context {
    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        new VocableEditor();
    }
}

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class VocableEditor extends JFrame implements WindowListener, ActionListener {
    private static final long serialVersionUID = -6209345602005762300L;
    private Button b_save, b_discard;
    private GridBagLayout layout;

    public VocableEditor() {

        setTitle("vocableEditorTitle");
        setSize(600, 400);
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        addWindowListener(this);

        layout = new GridBagLayout();
        setLayout(layout);
        GridBagConstraints c = new GridBagConstraints();
        c.gridwidth = 1;
        c.gridheight = 1;

        b_discard = new Button("discardAndLeave");
        b_discard.addActionListener(this);
        c.gridwidth = 1;
        c.gridx = 2;
        add(b_discard, c);
        b_save = new Button("saveAndExit");
        b_save.addActionListener(this);
        c.gridx = 3;
        add(b_save, c);

        setVisible(true);
    }

    public void end(boolean save) {
        System.out.println(save);
        dispose();
    }

    @Override
    public void windowOpened(WindowEvent e) {
    }

    @Override
    public void windowClosing(WindowEvent e) {
    }

    @Override
    public void windowClosed(WindowEvent e) {
    }

    @Override
    public void windowIconified(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    @Override
    public void windowActivated(WindowEvent e) {
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == b_save) {
            end(true);
        } else if (e.getSource() == b_discard) {
            end(false);
        }
    }
}

import java.awt.Color;

import javax.swing.JButton;

public class Button extends JButton {
    private static final Color BACKGROUND_COLOR = new Color(60, 90, 180);

    public Button(String name) {
        super(name);
        setBackground(BACKGROUND_COLOR);
        setForeground(Color.WHITE);
    }
}

1 ответ

Решение

После нескольких часов исследований я нашел решение. Oracle говорит, что показанное поведение желательно, даже если я не могу понять, почему LAF должен быть таким прозрачным. Решение заключается в добавлении следующих строк в конструктор кнопки:

setContentAreaFilled(false);
setOpaque(true);

Первая строка отключает рисование фона, а вторая включает его снова, но пропускает часть, в которой LAF меняет внешний вид.

Другие вопросы по тегам