Reputation: 988
I tried styling a custom-made Dialog
which allows the user to create a new folder. Until I loaded my custom Look and Feel, everything looked just fine:
Now I tried setting the Look and Feel and the texts of the buttons disappeared.
I set up an SSCCE which demonstrates this behaviour. Please note that the LNF class does nothing except for loading all values from UIManager.getDefaults()
. If this helps, I'm using Debian 8 (jessie) with Gnome 3.18.1 and the global dark theme toggled on.
Why does this happen and how can I fix the disappearing of those button texts?
Upvotes: 1
Views: 360
Reputation: 9833
Another common way is to use the UIDefaults#addResourceBundle(...) method:
//@see javax/swing/plaf/basic/BasicLookAndFeel.java
@Override
public UIDefaults getDefaults() {
UIDefaults defaults = new UIDefaults();
defaults.putAll(UIManager.getDefaults());
//defaults.addResourceBundle("com.example.swing.plaf.light.resources.light");
defaults.addResourceBundle("com.sun.swing.internal.plaf.basic.resources.basic");
return defaults;
}
Test2.java
import java.awt.*;
import java.io.File;
import java.util.*;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.GroupLayout.SequentialGroup;
public class Test2 {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new LightLookAndFeel());
DialogFactory.showCreateFolderDialog(null, new File("."));
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
}
class DialogFactory {
private DialogFactory() {}
public static void showCreateFolderDialog(Component component, File parent) {
JPanel panel = new JPanel();
JLabel message = new JLabel("Please enter a folder name.");
JLabel label = new JLabel("Folder name:");
final JLabel errorMessage = new JLabel();
JTextField folderName = new JTextField();
GroupLayout layout = new GroupLayout(panel);
layout.setHonorsVisibility(false);
layout.setAutoCreateContainerGaps(true);
layout.setAutoCreateGaps(true);
panel.setLayout(layout);
errorMessage.setVisible(false);
SequentialGroup hGroup = layout.createSequentialGroup();
SequentialGroup input = layout.createSequentialGroup().addComponent(label).addComponent(folderName);
hGroup.addGroup(layout.createParallelGroup().addComponent(message).addGroup(input).addComponent(errorMessage));
layout.setHorizontalGroup(hGroup);
SequentialGroup vGroup = layout.createSequentialGroup();
vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).addComponent(message));
vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).addComponent(label).addComponent(folderName));
vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).addComponent(errorMessage));
layout.setVerticalGroup(vGroup);
final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
final JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(component), "Create new folder", true);
dialog.setLocationRelativeTo(component);
dialog.setContentPane(optionPane);
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
optionPane.addPropertyChangeListener(event -> {
String property = event.getPropertyName();
if (dialog.isVisible() && event.getSource() == optionPane && property.equals(JOptionPane.VALUE_PROPERTY)) {
if (folderName.getText().isEmpty() && (int) event.getNewValue() != JOptionPane.CANCEL_OPTION) {
errorMessage.setText("<html><body><b style='color: red'>Please enter a valid folder name!</b></body></html>");
errorMessage.setVisible(true);
dialog.pack();
} else {
dialog.setVisible(false);
}
}
});
dialog.pack();
dialog.setVisible(true);
int response = ((Integer) optionPane.getValue()).intValue();
if (response != JOptionPane.OK_OPTION) return;
File newFolder = new File(parent, folderName.getText());
newFolder.mkdirs();
}
}
class LightLookAndFeel extends LookAndFeel {
private final UIDefaults defaults = new UIDefaults();
public LightLookAndFeel() {
defaults.putAll(UIManager.getDefaults());
}
@Override
public void initialize() {
}
@Override
public String getName() {
return "Light";
}
@Override
public String getID() {
return getClass().getName();
}
@Override
public String getDescription() {
return "Light Look and Feel";
}
@Override
public boolean isNativeLookAndFeel() {
return false;
}
@Override
public boolean isSupportedLookAndFeel() {
return true;
}
@Override
public UIDefaults getDefaults() {
//defaults.addResourceBundle("com.example.swing.plaf.light.resources.light");
defaults.addResourceBundle("com.sun.swing.internal.plaf.basic.resources.basic");
return defaults;
}
}
// package com.example.swing.plaf.light.resources;
// import java.util.*;
//
// public class light extends ListResourceBundle {
// @Override protected final Object[][] getContents() {
// return new Object[][] {
// //...
// { "OptionPane.cancelButtonMnemonic", "0" },
// { "OptionPane.cancelButtonText", "Cancel" },
// { "OptionPane.inputDialogTitle", "Input" },
// { "OptionPane.messageDialogTitle", "Message" },
// { "OptionPane.noButtonMnemonic", "78" },
// { "OptionPane.noButtonText", "No" },
// { "OptionPane.okButtonMnemonic", "0" },
// { "OptionPane.okButtonText", "OKkkk" },
// { "OptionPane.titleText", "Select an Option" },
// { "OptionPane.yesButtonMnemonic", "89" },
// { "OptionPane.yesButtonText", "Yessss" },
// //...
// };
// }
// }
// public class light_de extends ListResourceBundle { //...
// public class light_es extends ListResourceBundle { //...
// public class light_fr extends ListResourceBundle { //...
// public class light_it extends ListResourceBundle { //...
// public class light_ja extends ListResourceBundle { //...
// public class light_ko extends ListResourceBundle { //...
// public class light_pt_BR extends ListResourceBundle { //...
// public class light_sv extends ListResourceBundle { //...
// public class light_zh_CN extends ListResourceBundle { //...
// public class light_zh_HK extends ListResourceBundle { //...
// public class light_zh_TW extends ListResourceBundle { //...
Upvotes: 3
Reputation: 988
The values retrieved by UIManager.getDefaults()
do not include the texts for JOptionPane
buttons whose properties are OptionPane.cancelButtonText
and OptionPane.okButtonText
respectively. This causes the buttons to be displayed without any text, causing them to be as small as in the screenshot provided in the question. By setting OptionPane.cancelButtonText
and OptionPane.okButtonText
to the desired values, the JOptionPane
buttons will display the set text. This solution may also apply for the yes/no buttons.
Upvotes: 2