Компонент Java не отображается при запуске

1

У меня есть класс, который добавляет ImageIcon на восток от TextField, если вы передаете его этому классу, он работает очень хорошо во время выполнения, если я нажимаю кнопку для изменения кадров, но изображение не появляется при запуске.

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;
}

}

Если я поменю изменение пользовательского интерфейса до появления рамки, у меня нет этой проблемы, может ли кто-нибудь объяснить мне, почему так?

  • 1
    addImage() вызывается так, как в вашем фрагменте кода.
  • 0
    Да, не звонил туда, но при моем запуске. Я могу system.out.println и вижу, что макет установлен в начале, только этот компонент не отображается ...
Показать ещё 8 комментариев
Теги:
swing

1 ответ

1

Ваша проблема вызвана изменением фабрики пользовательского интерфейса на JTextField (это вызвано установкой Nimbus L & F и updateComponentTreeUI()).

Когда вы выполняете второй вызов, вы автоматически удаляете предыдущую фабрику L & F и UI JTextField. По умолчанию это текстовый пользовательский интерфейс Metal L & F (MetalTextFieldUI), который расширяет 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 или JLabel JTextField а после обновления пользовательского интерфейса переустановите JLabel в JTextField.

Маленький пример (просто для демонстрации моего объяснения):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
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.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class TestAddImageToTextField {

    private static class MyJTextField extends JTextField {
        @Override
        public void updateUI() {
            removeAll();
            super.updateUI();
            Image image = buildImage();

            JLabel lblClear = new JLabel(new ImageIcon(image));
            lblClear.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    MyJTextField.this.setText("");
                }
            });
            setLayout(new BorderLayout());
            add(lblClear, BorderLayout.EAST);
        }

        private Image buildImage() {
            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);
            return image;
        }
    }

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

    private JComponent contentPane;

    /**
     * Create the frame.
     * 
     * @throws UnsupportedLookAndFeelException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     */
    public TestAddImageToTextField() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 450, 300);
        contentPane = (JComponent) frame.getContentPane();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        MyJTextField comp = new MyJTextField();

        contentPane.add(comp);
        frame.setVisible(true);
        installNimbusLAF();

    }

    private void installNimbusLAF() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        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(contentPane);
    }

}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню