Java组件在启动时未显示

时间:2015-03-05 09:48:46

标签: java swing

我有一个Class,它在TextField的东部添加一个ImageIcon,如果你把它传递给那个Class,它在运行时工作得很好,如果我按一个Button来改变帧,但是Image在启动时没有出现

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

public class TestStartFrame extends JFrame
{

/**
 * 
 */
private static final long serialVersionUID = 1L;
private JPanel contentPane;

public static void main(String[] args)
{
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            try
            {
                TestStartFrame frame = new TestStartFrame();
                frame.setVisible(true);
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public TestStartFrame()
{
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);

    JButton btnNewButton = new JButton("New button");
    contentPane.add(btnNewButton, BorderLayout.CENTER);
    btnNewButton.addActionListener(new ActionListener()
    {

        @Override
        public void actionPerformed(ActionEvent e)
        {
            SecondFrame fr = new SecondFrame();
            fr.setVisible(true);
            try
            {
                int r = 250;
                int g = 250;
                int b = 250;
                UIManager.put("control", new Color(r, g, b));
                UIManager
                        .setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                UIManager.put("control", new Color(r, g, b));
                SwingUtilities
                        .updateComponentTreeUI(SecondFrame.contentPane);
            } catch (Exception e1)
            {
                System.out.println(e1.getMessage());
            }
            dispose();
        }
    });

}

}

class SecondFrame extends JFrame
{
/**
 * 
 */
private static final long serialVersionUID = 1L;
public final static JPanel contentPane = new JPanel();

/**
 * Create the frame.
 */
public SecondFrame()
{
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(new BorderLayout());
    JTextField txt = new JTextField();
    contentPane.add(txt, BorderLayout.CENTER);
    txt = ClearImage.addImage(txt);

}
}

class ClearImage
{

public static JTextField addImage(final JTextField comp)
{

    Image image = new BufferedImage(10, 25, BufferedImage.TYPE_INT_RGB);
    Graphics graphics = image.getGraphics();
    graphics.setColor(Color.WHITE);
    graphics.fillRect(0, 0, 10, 25);
    graphics.setColor(Color.LIGHT_GRAY);
    graphics.fillOval(0, 7, 10, 10);
    graphics.setColor(Color.GRAY);
    graphics.drawLine(2, 9, 8, 15);
    graphics.drawLine(2, 15, 8, 9);

    JLabel lblClear = new JLabel(new ImageIcon(image));
    comp.setLayout(new BorderLayout());
    comp.add(lblClear, BorderLayout.EAST);

    lblClear.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    lblClear.addMouseListener(new MouseAdapter()
    {
        @Override
        public void mouseClicked(MouseEvent e)
        {
            comp.setText("");
        }
    });

    return comp;

}

public static JTextField removeImage(final JTextField comp)
{
    comp.removeAll();
    return comp;
}

}

如果我在框架可见之前放置UI更改,我没有那个问题,任何人都可以解释我为什么会这样?

1 个答案:

答案 0 :(得分:1)

您的问题是由JTextField上的UI工厂更改引起的(这是由安装Nimbus L& F和updateComponentTreeUI()触发的。)

当您执行第二次调用时,您会自动卸载JTextField的上一个L& F和UI工厂。默认情况下,这是扩展MetalTextFieldUI的Metal L& F Text UI(BasicTextUI)。这将调用方法javax.swing.plaf.basic.BasicTextUI.uninstallUI(JComponent),其内容如下:

public void uninstallUI(JComponent c) {
        // detach from the model
        editor.removePropertyChangeListener(updateHandler);
        editor.getDocument().removeDocumentListener(updateHandler);

        // view part
        painted = false;
        uninstallDefaults();
        rootView.setView(null);
        c.removeAll();
        LayoutManager lm = c.getLayout();
        if (lm instanceof UIResource) {
            c.setLayout(null);
        }

        // controller part
        uninstallKeyboardActions();
        uninstallListeners();

        editor = null;
    }

请注意调用c.removeAll(),它基本上会从层次结构中删除您的标签,从而导致您遇到的问题。

  1. 可以说,我们可以说向原始Swing小部件添加组件并不理想,这不是他们打算使用的方式。我个人认为这个论点相当薄弱,但我知道很多Swing爱好者都被发现了。

  2. 只需确保在添加JLabel或扩展JTextField之前更新用户界面,并在更新用户界面时重新安装JLabel { {1}}。

  3. 小例子(只是为了演示我的解释):

    JTextField