JOptionPane 没有带有自定义 LNF 的按钮文本
JOptionPane no button text with custom LNF
我尝试设计一个定制的 Dialog
样式,它允许用户创建一个新文件夹。在我加载自定义外观之前,一切看起来都很好:
现在我尝试设置外观,但按钮的文本消失了。
我设置了一个 SSCCE 来演示这种行为。请注意,LNF class 除了从 UIManager.getDefaults()
加载所有值外什么都不做。如果这有帮助,我将使用 Debian 8 (jessie) 和 Gnome 3.18.1 并打开全局深色主题。
为什么会发生这种情况,如何解决这些按钮文本消失的问题?
UIManager.getDefaults()
检索到的值不包括 JOptionPane
按钮的文本,其属性分别为 OptionPane.cancelButtonText
和 OptionPane.okButtonText
。这会导致按钮显示时没有任何文本,导致它们与问题中提供的屏幕截图一样小。通过将 OptionPane.cancelButtonText
和 OptionPane.okButtonText
设置为所需的值,JOptionPane
按钮将显示设置的文本。此解决方案也适用于 yes/no 按钮。
另一种常用的方法是使用UIDefaults#addResourceBundle(...)方法:
//@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 { //...
我尝试设计一个定制的 Dialog
样式,它允许用户创建一个新文件夹。在我加载自定义外观之前,一切看起来都很好:
现在我尝试设置外观,但按钮的文本消失了。
我设置了一个 SSCCE 来演示这种行为。请注意,LNF class 除了从 UIManager.getDefaults()
加载所有值外什么都不做。如果这有帮助,我将使用 Debian 8 (jessie) 和 Gnome 3.18.1 并打开全局深色主题。
为什么会发生这种情况,如何解决这些按钮文本消失的问题?
UIManager.getDefaults()
检索到的值不包括 JOptionPane
按钮的文本,其属性分别为 OptionPane.cancelButtonText
和 OptionPane.okButtonText
。这会导致按钮显示时没有任何文本,导致它们与问题中提供的屏幕截图一样小。通过将 OptionPane.cancelButtonText
和 OptionPane.okButtonText
设置为所需的值,JOptionPane
按钮将显示设置的文本。此解决方案也适用于 yes/no 按钮。
另一种常用的方法是使用UIDefaults#addResourceBundle(...)方法:
//@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 { //...