当用户输入无效时,我想绘制一个图标。我找到了 Oracle 的一个示例,并出于我的目的对其进行了修改。Icon 的绘画工作正常,但是当我更改值以更正图标时,图标并非完全不可见:仍然显示在 JPanel 上绘制的部分。
这是我的代码:
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.LayerUI;
public class FieldValidator extends JPanel {
private static final int ICON_SIZE = 12;
private static final Icon ICON = createResizedIcon((ImageIcon) UIManager.getIcon("OptionPane.errorIcon"));
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createUI();
}
});
}
public static void createUI() {
final JFrame f = new JFrame ("FieldValidator");
final JComponent content = createContent();
f.add (content);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo (null);
f.setVisible (true);
}
private static JComponent createContent() {
final LayerUI<JPanel> panelUI = new ValidationLayerUI();
// Number field.
final JLabel numberLabel = new JLabel("Number:");
final NumberFormat numberFormat = NumberFormat.getInstance();
final JFormattedTextField numberField = new JFormattedTextField(numberFormat) {
/**
* {@inheritDoc}
*/
@Override
public void replaceSelection(String content) {
super.replaceSelection(content);
getParent().repaint();
}
};
numberField.setColumns(16);
numberField.setFocusLostBehavior(JFormattedTextField.PERSIST);
numberField.setValue(42);
final int i = (ICON_SIZE / 2) + (ICON_SIZE % 2);
final JPanel numberPanel = new JPanel();
numberPanel.add(numberLabel);
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints constr = new GridBagConstraints();
constr.insets = new Insets(i, i, i, i);
constr.weightx = 1;
constr.weighty = 1;
constr.fill = GridBagConstraints.BOTH;
panel.add(numberField, constr);
numberPanel.add(new JLayer<JPanel>(panel, panelUI));
return numberPanel;
}
//Icon resized to 12x12
private static Icon createResizedIcon(ImageIcon anIcon) {
final BufferedImage result = new BufferedImage(ICON_SIZE, ICON_SIZE, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g = result.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.drawImage(anIcon.getImage(), 0, 0, ICON_SIZE, ICON_SIZE, null);
g.dispose();
return new ImageIcon(result);
}
static class ValidationLayerUI extends LayerUI<JPanel> {
@Override
public void paint (Graphics g, JComponent c) {
super.paint (g, c);
final JLayer jlayer = (JLayer) c;
final JPanel panel = (JPanel) jlayer.getView();
final JFormattedTextField ftf = (JFormattedTextField) panel.getComponent(0);
if (!ftf.isEditValid()) {
ICON.paintIcon(panel, g, 0, panel.getHeight() - ICON.getIconHeight());
}
}
}
}
这是屏幕:初始一切都是正确的
当我绘制无效图标时,一切仍然正确
但是当值正确时,只会重新绘制文本字段
如何强制 JPanel 重新绘制???
PS 我已经找到了一种使用 JLayeredPane 的方法,它可以正常工作,但我想知道我的代码有什么问题?