SwingUtilities.updateComponentTreeUI() not changing JFrames titlebar - java

Environment:
Using Netbeans 8.1
Oracle JDK 1.8
Win 10 pro
Context:
A GUI with a JCheckBoxMenuItem to change LookAndFeel(LAF) at runtime.
darkLAF=JTattoo's HiFi LAF
defaultLAF=Sun's Windows LAF(com.sun.java.swing.plaf.windows.WindowsLookAndFeel)
Problem:
GUI launches(in EDT) with defaultLAF. User changes to darkLAF..the title bar should have changed..it doesn't.
When the user switches back to defaultLAF, the JMenuItems(File and Edit) show greyer backgrounds not the defaultLAF style.
Screenshots:
The launched defaultLAF
upon switching to darkLAF
user switched back to defaultLAF
expected look for darkLAF
Code:
Inside the itemStateChangeListener for JCheckBoxMenuItem
try{
if (checkBox.isSelected())
UIManager.setLookAndFeel(darkLookAndFeel);
else
UIManager.setLookAndFeel(defaultLookAndFeel);
} catch (UnsupportedLookAndFeelException ex) {
//handle err
}
//GUI is a class extending JFrame
SwingUtilities.updateComponentTreeUI(this);
//some JFileChooser
SwingUtilities.updateComponentTreeUI(fc);
pack();
Catch:
User shouldn't be asked to do a GUI restart.

It was a little bit hard, but I've found a solution.
Steps you need to switch to the JTatto L&F
Dispose window
Set L&F
Set window style of root pane to JRootPane.FRAME
Update UI
Make Frame undecorated
Make Frame visible
Steps you need to switch back to Windows L&F
Dispose window
Set L&F
Update UI
Make Frame decorated
Make Frame visible
Here is the code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MinFrame extends JFrame {
public MinFrame() {
super("Minimal-Frame-Application");
// setup menu
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.setMnemonic('F');
JMenuItem menuItem = new JMenuItem("Exit");
menuItem.setMnemonic('x');
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.ALT_MASK));
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
menu.add(menuItem);
menuBar.add(menu);
setJMenuBar(menuBar);
// setup widgets
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));
JScrollPane westPanel = new JScrollPane(new JTree());
JEditorPane editor = new JEditorPane("text/plain", "Hello World");
JScrollPane eastPanel = new JScrollPane(editor);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, westPanel,eastPanel);
splitPane.setDividerLocation(148);
contentPanel.add(splitPane, BorderLayout.CENTER);
AbstractButton winLF = new JButton("Windows");
winLF.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
MinFrame.this.dispose();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(MinFrame.this.getRootPane());
MinFrame.this.setUndecorated(false);
MinFrame.this.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
AbstractButton customLF = new JButton("JTatto");
customLF.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
MinFrame.this.dispose();
UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
MinFrame.this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
SwingUtilities.updateComponentTreeUI(MinFrame.this.getRootPane());
MinFrame.this.setUndecorated(true);
MinFrame.this.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
JPanel buttons = new JPanel();
buttons.add(winLF);
buttons.add(customLF);
contentPanel.add(buttons, BorderLayout.SOUTH);
setContentPane(contentPanel);
// add listeners
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// show application
setLocation(32, 32);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
} // end CTor MinFrame
public static void main(String[] args) {
try {
// select Look and Feel
// UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
// start application
new MinFrame();
}
catch (Exception ex) {
ex.printStackTrace();
}
} // end main
}

Related

Why won't KeyListeners work when a JButton is selected?

I am trying to remove from a specific frame panel#1 (which only contains a single JButton) and add to it panel#2, which contains some KeyEvents.
I was constantly getting a bug where the KeyEvents won't register, but while I was testing out some things, I found out that if I don't remove panel#1 and add panel#2 on top of the frame, the KeyListeners will register, only if the JButton on the panel#1 is not selected (only by pressing "TAB").
Can someone help me remove this bug?
This is panel#2:
public class paintTest extends JPanel implements KeyListener
{
public paintTest(){
addKeyListener(this);
setFocusable(true);
}
#Override
public void keyPressed(KeyEvent e) {}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyTyped(KeyEvent e) {}
}
And this is the Main class:
public static void main(String[] args)
{
JFrame mainMenu = new JFrame();
drawMainMenu(mainMenu);
mainMenu.setVisible(true);
mainMenu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void drawMainMenu(JFrame frame)
{
frame.setBounds(0, 0, 360, 300);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel();
frame.add(panel);
JButton newGame = new JButton();
newGame.setBounds(130, 120, 100, 30);
newGame.setText("NEW GAME");
newGame.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent arg0)
{
paintTest gamePlay = new paintTest();
// frame.remove(panel); **HERE IS THE LINE OF CODE I WANT TO REMOVE**
frame.add(gamePlay);
frame.setBounds(0,0,512,512);
frame.setLocationRelativeTo(null);
}
});
panel.setLayout(null);
panel.add(newGame);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
I managed to fix it, thank you all:
One way to fix this is to make the JButton non-focusable by using:
.setfocusable(false);
This way the JButton will not be focused and marked, but still, when entering Panel#2 you will need to press "TAB" to focus again on the new Panel, and for that java.awt.Robot can be of use:
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
} catch (AWTException e) {
e.printStackTrace();
}

How can I override the default listener for a JFrame close ('x') button?

I want 3 ways of exiting the application
Key stroke CTRL-Q
Select 'Exit' from menu bar
Close 'x' button on JFrame
What I've done so far is add the even listeners for the first two, but I cannot figure out how to have the JFrame close 'x' button to do the same thing. For now it just exits the application without prompting a confirmation, because it doesn't know how to get to that. I basically want all the frames to be disposed, after the user has confirmed that they want to exit. This happens in the first two cases, simply because their action listeners call an exit() method that confirms exiting, and then proceeds to dispose of all frames.
public class MainWindow extends JFrame {
...
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowListener() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
...
// this is part of the main menu bar (case #2)
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MainWindow.this.exit();
}
});
// this is case #1
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_Q && e.getModifiers() == InputEvent.CTRL_MASK) {
MainWindow.this.exit();
}
return false;
}
});
}
// the exit method
private void exit() {
int confirmed = JOptionPane.showConfirmDialog(this, "Are you sure you want to quit?", "Confirm quit", JOptionPane.YES_NO_OPTION);
if(confirmed == JOptionPane.YES_OPTION) {
Frame[] frames = Frame.getFrames();
for(Frame frame : frames) {
frame.dispose();
}
}
}
Is it possible to assign an action listener to the close button? If not, is there another way I should approach this?
Keep your JFrame's default close operation to JFrame.DO_NOTHING_ON_CLOSE, but listen for closing attempt with a WindowListener (or more succinctly, a WindowAdapter).
You could use the same AbstractAction for both the menu item and the button, and then call the action's method in a WindowListener. For example
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class ClosingJFrame {
public static void main(String[] args) {
final JFrame frame = new JFrame("My Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
final CloseAction closeAction = new CloseAction(frame);
JPanel panel = new JPanel();
panel.add(new JButton(closeAction));
JMenuItem exitMenuItem = new JMenuItem(closeAction);
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.add(exitMenuItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
closeAction.confirmClosing();
}
});
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
class CloseAction extends AbstractAction {
private JFrame mainFrame;
public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
this.mainFrame = mainFrame;
}
#Override
public void actionPerformed(ActionEvent e) {
confirmClosing();
}
public void confirmClosing() {
int confirmed = JOptionPane.showConfirmDialog(mainFrame,
"Are you sure you want to quit?", "Confirm quit",
JOptionPane.YES_NO_OPTION);
if (confirmed == JOptionPane.YES_OPTION) {
// clean up code
System.exit(0);
}
}
}
Edit
Oops, I forgot your ctrl-Q keystroke bit. Use the same Action for that, and bind it to the ctrl-q key using KeyBindings. The improved code:
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class ClosingJFrame {
public static void main(String[] args) {
final JFrame frame = new JFrame("My Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
final CloseAction closeAction = new CloseAction(frame);
JPanel panel = new JPanel();
panel.add(new JButton(closeAction));
JMenuItem exitMenuItem = new JMenuItem(closeAction);
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.add(exitMenuItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
closeAction.confirmClosing();
}
});
// also use the same Action in your ctrl-q key bindings
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = panel.getInputMap(condition);
ActionMap actionMap = panel.getActionMap();
KeyStroke ctrlQKey = KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK);
inputMap.put(ctrlQKey, ctrlQKey.toString());
actionMap.put(ctrlQKey.toString(), closeAction);
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
class CloseAction extends AbstractAction {
private JFrame mainFrame;
public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
this.mainFrame = mainFrame;
}
#Override
public void actionPerformed(ActionEvent e) {
confirmClosing();
}
public void confirmClosing() {
int confirmed = JOptionPane.showConfirmDialog(mainFrame,
"Are you sure you want to quit?", "Confirm quit",
JOptionPane.YES_NO_OPTION);
if (confirmed == JOptionPane.YES_OPTION) {
// clean up code
System.exit(0);
}
}
}
Edit 2
This statement has me concerned:
then proceeds to dispose of all frames
as it implies that you have multiple JFrames. If so, you should read this link as it will explain why this is often not desired: The Use of Multiple JFrames, Good/Bad Practice?
Edit 3
As per Rob Camick's comment:
You could also just set an accelerator for the CloseAction by doing something like:
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control Q"));
Then the menu item will do the key bindings for you.
This would go into the CloseAction's constructor, like so:
public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control Q"));
this.mainFrame = mainFrame;
}
In your windowClosing method, call your exit() method before System.exit().
That will automatically close out your java program when you click the X.

Remove JButton rectangle white border

Does somebody know how to remove white rectangle border on JButton ? This issue is there only for windows look & feel when the button is a little bit rounded.
Please find attached the example on the image.
Setting the border to empty or null doesn't help. The same for margin.
The white margin/border dissapear only when I set the opacity of the button to false, but unfortunately in this case also the whole button is opaque on some versions of windows.
When I set opacity to false, it looks like:
Code example:
public class TestFrame extends javax.swing.JFrame {
/**
* Auto-generated main method to display this JFrame
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
TestFrame inst = new TestFrame();
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
public TestFrame() {
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.setLayout(null);
this.getContentPane().setBackground(Color.BLACK);
JButton button = new JButton();
button.setBounds(10, 10, 100, 50);
button.setBorder(BorderFactory.createEmptyBorder()); // not working
button.setBorder(null); // not working
button.setMargin(new Insets(0,0,0,0)); // not working
add(button);
pack();
setSize(400, 300);
}
}
Thanks,
Lubos
Seems like a painting problem. You can use:
button.setBackground( Color.BLACK );
EDIT: See comments below. This sample still shows the effect, even using a proper layout. Setting the background color seems to show the unwanted border. This effect doesn't show with Metal. It seems as if Windows L&F shows a rounded edge, but the button is still rectangular. The space between is only noticable if the BG color of the container is changed to something obvious, like black.
import java.awt.*;
import javax.swing.*;
public class TestFrame extends JFrame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e)
{
e.printStackTrace();
}
TestFrame inst = new TestFrame();
inst.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
public TestFrame()
{
JButton button = new JButton("One");
JButton button2 = new JButton("Two");
JPanel p = new JPanel();
p.setBackground(Color.BLACK);
p.setLayout(new FlowLayout());
p.add(button);
p.add(button2);
add(p);
setSize(400, 300);
}
}

Java switch between cards using jbutton

I'm using a cardlayout and I want to make it so that the first card has a button and when clicked it will take it to card 2 which has a button that will take it back to card 1. Here is my current code, and I've tried putting a few things in the actionPerformed method but I haven't had any success in getting it to work. Also, I receive a syntax error on "this" on the lines with button1.addActionListener(this); and button2.addActionListener(this); which I assume is because my actionPerformed method isn't setup correctly. Any help on getting the buttons setup would be greatly appreciated.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Main implements ItemListener {
JPanel cards;
public void addComponentToPane(Container pane) {
//create cards
JPanel card1 = new JPanel();
JPanel card2 = new JPanel();
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
button1.addActionListener(this);
button2.addActionListener(this);
card1.add(button1);
card2.add(button2);
//create panel that contains cards
cards = new JPanel(new CardLayout());
cards.add(card1);
cards.add(card2);
pane.add(cards, BorderLayout.CENTER);
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
}
public static void createAndShowGUI() {
//create and setup window
JFrame frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create and setup content pane
Main main = new Main();
main.addComponentToPane(frame.getContentPane());
//display window
frame.pack();
frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
}
public static void main(String[] args) {
//set look and feel
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
//turn off metal's bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
//schedule job for the event dispatch thread creating and showing GUI
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardTest implements ActionListener {
private JPanel cards;
private JButton button1;
private JButton button2;
public void addComponentToPane(Container pane) {
// create cards
JPanel card1 = new JPanel();
JPanel card2 = new JPanel();
button1 = new JButton("Button 1");
button2 = new JButton("Button 2");
button1.addActionListener(this);
button2.addActionListener(this);
card1.add(button1);
card2.add(button2);
// create panel that contains cards
cards = new JPanel(new CardLayout());
cards.add(card1, "Card 1");
cards.add(card2, "Card 2");
pane.add(cards, BorderLayout.CENTER);
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, (String) evt.getItem());
}
public static void createAndShowGUI() {
// create and setup window
JFrame frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create and setup content pane
CardTest main = new CardTest();
main.addComponentToPane(frame.getContentPane());
// display window
frame.pack();
frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == button1) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, "Card 2");
} else if (ae.getSource() == button2) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, "Card 1");
}
}
public static void main(String[] args) {
// set look and feel
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
// turn off metal's bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
// schedule job for the event dispatch thread creating and showing GUI
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

How to disable JButton without hiding its label?

I'm developing a project in Java using netbeans IDE and I need to disable a particular JButton. I use the following code for that.
IssuBtn.setEnabled(false);
But after it is disabled it doesn't show the text on the JButton. How can I keep that text on the JButton?
This experiment suggests one answer is 'Use a PLAF that is not Metal'.
import java.awt.*;
import javax.swing.*;
class LookOfDisabledButton {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel gui = new JPanel(new BorderLayout(3,3));
JPanel pEnabled = new JPanel(new GridLayout(1,0,2,2));
pEnabled.setBackground(Color.green);
gui.add(pEnabled, BorderLayout.NORTH);
JPanel pDisabled = new JPanel(new GridLayout(1,0,2,2));
pDisabled.setBackground(Color.red);
gui.add(pDisabled, BorderLayout.SOUTH);
UIManager.LookAndFeelInfo[] plafs =
UIManager.getInstalledLookAndFeels();
for (UIManager.LookAndFeelInfo plafInfo : plafs) {
try {
UIManager.setLookAndFeel(plafInfo.getClassName());
JButton bEnabled = new JButton(plafInfo.getName());
pEnabled.add(bEnabled);
JButton bDisabled = new JButton(plafInfo.getName());
bDisabled.setEnabled(false);
pDisabled.add(bDisabled);
} catch(Exception e) {
e.printStackTrace();
}
}
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
Alternately, adjust the values in the UIManager.
import java.awt.*;
import javax.swing.*;
class LookOfDisabledButton {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel gui = new JPanel(new BorderLayout(3,3));
JPanel pEnabled = new JPanel(new GridLayout(1,0,2,2));
pEnabled.setBackground(Color.green);
gui.add(pEnabled, BorderLayout.NORTH);
JPanel pDisabled = new JPanel(new GridLayout(1,0,2,2));
pDisabled.setBackground(Color.red);
gui.add(pDisabled, BorderLayout.SOUTH);
// tweak the Color of the Metal disabled button
UIManager.put("Button.disabledText", new Color(40,40,255));
UIManager.LookAndFeelInfo[] plafs =
UIManager.getInstalledLookAndFeels();
for (UIManager.LookAndFeelInfo plafInfo : plafs) {
try {
UIManager.setLookAndFeel(plafInfo.getClassName());
JButton bEnabled = new JButton(plafInfo.getName());
pEnabled.add(bEnabled);
JButton bDisabled = new JButton(plafInfo.getName());
bDisabled.setEnabled(false);
pDisabled.add(bDisabled);
} catch(Exception e) {
e.printStackTrace();
}
}
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
As pointed out by kleopatra..
it's not a solution but might be a pointer to the direction to search for a solution
Where 'it' is my answer. In fact, I suspect she hit upon the real cause with the comment:
guessing only: here it's due to violating the one-plaf-only rule.
I second that guess.

Categories