JOptionPane没有自定义LNF的按钮文本

时间:2015-11-01 16:42:43

标签: java swing joptionpane look-and-feel

我尝试了定制的Dialog样式,允许用户创建新文件夹。在我加载自定义外观之前,一切看起来都很好:

Dialog without custom Look and Feel

现在我尝试设置外观并且按钮的文本消失了。

Dialog with custom Look and Feel

我设置了SSCCE来演示此行为。请注意,除了从UIManager.getDefaults()加载所有值之外,LNF类不执行任何操作。如果这有帮助,我将使用Debian 8(jessie)和Gnome 3.18.1以及全局黑暗主题切换。

为什么会发生这种情况?如何解决这些按钮文本的消失?

2 个答案:

答案 0 :(得分:3)

另一种常见方法是使用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 { //...

答案 1 :(得分:2)

UIManager.getDefaults()检索到的值不包括属性分别为JOptionPaneOptionPane.cancelButtonText的{​​{1}}按钮的文本。这会导致按钮显示没有任何文本,导致它们与问题中提供的屏幕截图一样小。通过将OptionPane.okButtonTextOptionPane.cancelButtonText设置为所需的值,OptionPane.okButtonText按钮将显示设置的文本。此解决方案也可能适用于是/否按钮。