【问题标题】:How to correctly update an Image in a JLabel?如何正确更新 JLabel 中的图像?
【发布时间】:2012-05-31 13:00:12
【问题描述】:

我是法国人,所以我的英语很糟糕,但我对 java 有一个真正的问题: 我正在尝试显示使用一些 fillRect & co 手动构建的图像。

它有效。接下来,我想根据在文本字段中输入的文本来更新此图像。还有一个问题:它并没有改变任何东西,如果我手动重新缩放JFrame 的窗口,图像显示完全变形或缩放严重。

我是一个初学者,我在使用 GUI 时遇到了困难,所以当我想将它与图像结合起来时。

你能帮帮我吗?为什么它不能按我的意愿工作?这是我下面的代码,有点长但实际上很简单!谢谢:)


我稍微改了一下,这是2e版本。

现在的问题是我无法更改条件以修改简单矩形的颜色,请在输入字段中尝试“lol”!

代码版本 2

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;

public class Fenetre extends JFrame {
    private JFrame frame;
    private JPanel container = new JPanel();
    private JTextField jtf;
    private JLabel label = new JLabel("Commandes   ");
    private JButton b = new JButton ("OK");
    private Graphics graph;
    private Image img;
    private JLabel screen;
    private boolean color;

    /**
     * Constructeur de l'objet 
     */
    public Fenetre(){
        color = true;


        frame = new JFrame();
        frame.setTitle("Animation");
        frame.setSize(1000, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

        container.setBackground(Color.white);
        container.setLayout(new BorderLayout());


        JPanel top = new JPanel();

        jtf = new JTextField();

        jtf.setPreferredSize(new Dimension(800, 30));

        b.addActionListener(new BoutonListener());

        frame.setContentPane(top);
        frame.setVisible(true); 

        paintComponent(graph);

        screen = new JLabel( new ImageIcon(img));

        top.add(screen);
        top.add(label);
        top.add(jtf);
        top.add(b);

        frame.setContentPane(top);
     }      


    class BoutonListener implements ActionListener{ 
        public void actionPerformed(ActionEvent e) {
                if(jtf.getText().equals("lol")) lol();
                System.out.println("Entry  : " + jtf.getText());
        }  
    }

    public void paintComponent(Graphics g)
    {
        if(img == null) {
            img = frame.createImage(1000,300);
            g = img.getGraphics();
        }
        g.setColor(Color.white);
        g.fillRect(0,0,1000,300);
        if(color) g.setColor(Color.orange); else g.setColor(Color.blue);
        g.fillRect(8,25,200,100);
        g.setColor(Color.green);
        g.drawString("Text",10,10);
    }

    public void lol()
    {
        if(color) color = false; else color = true;
    }
}

以前的代码

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;

public class Fenetre extends JFrame {

    private JPanel container = new JPanel();
    private JTextField jtf;
    private JLabel label = new JLabel("Commandes   ");
    private JButton b = new JButton ("OK");
    private Graphics g;
    private Image img;
    private JLabel screen;

    /**
     * Constructeur de l'objet 
     */
    public Fenetre(){

        this.setTitle("Animation");
        this.setSize(1000, 400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);

        container.setBackground(Color.white);
        container.setLayout(new BorderLayout());


        JPanel top = new JPanel();

        jtf = new JTextField();

        jtf.setPreferredSize(new Dimension(800, 30));

        b.addActionListener(new BoutonListener());

        this.setContentPane(top);
        this.setVisible(true); 

        paint(g);

        screen = new JLabel( new ImageIcon(img));

        top.add(screen);
        top.add(label);
        top.add(jtf);
        top.add(b);


        this.setContentPane(top);
     }      


    class BoutonListener implements ActionListener{ 
        public void actionPerformed(ActionEvent e) {
                System.out.println("Entry  : " + jtf.getText());
                if(jtf.getText().equals("lol")) lol();
        }  
    }

    @Override
    public void paint(Graphics g)
    {
        if(img == null) {
            img = createImage(1000,300);
            g = img.getGraphics();
        }
        g.setColor(Color.white);
        g.fillRect(0,0,1000,300);
        g.setColor(Color.orange);
        g.fillRect(8,25,200,100);
        g.setColor(Color.green);
        g.drawString("Text",10,10);
    }

    @Override
    public void update(Graphics g)
    {
        g.setColor(Color.blue);
        g.fillRect(8,25,300,100);
    }

    public void lol()
    {
        g.setColor(Color.blue);
        g.fillRect(8,25,200,100);
    }
}

【问题讨论】:

    标签: java image swing awt jlabel


    【解决方案1】:

    我在您的代码中发现了几个问题:

    1. 您将g 成员变量与paint 方法的g 参数混淆了。当lol 被调用时,gnull,你会得到一个NullPointerException
    2. 你永远不应该抓住Graphics(仅在极少数情况下)。相反,您可以正确覆盖 paintComponent() 并使用 Graphics 参数来绘制您想要的内容。当你想更新组件时,你调用repaint()
    3. 不要覆盖paint,而是覆盖paintComponent()
    4. 不要覆盖paintJFrame。为此使用专用组件。无需为此使用 JLabel,一个简单的 JComponent 就足够了。
    5. 如果您不扩展其功能,请勿扩展 JFrame
    6. 将组件添加到组件层次结构后,调用revalidate()

    解决这些问题,如果仍有问题,请返回另一个问题。

    您可能应该考虑阅读this tutorial 以及接下来的几个步骤。它将向您展示与您正在尝试做的事情类似的事情的基本示例。

    编辑: 我拿走了你的 V2 代码并尽可能地对其进行了修补。这远非完美,但您应该了解如何做到这一点:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class Fenetre extends JComponent {
    
        private boolean color;
    
        /**
         * Constructeur de l'objet
         */
        public Fenetre() {
            color = true;
            setPreferredSize(new Dimension(1000, 300));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.white);
            g.fillRect(0, 0, 1000, 300);
            if (color) {
                g.setColor(Color.orange);
            } else {
                g.setColor(Color.blue);
            }
            g.fillRect(8, 25, 200, 100);
            g.setColor(Color.green);
            g.drawString("Text", 10, 10);
        }
    
        public void lol() {
            if (color) {
                color = false;
            } else {
                color = true;
            }
            repaint();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    initUI();
                }
            });
        }
    
        protected static void initUI() {
            JFrame frame = new JFrame();
            frame.setTitle("Animation");
            frame.setSize(1000, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
    
            JPanel container = new JPanel();
            final JTextField jtf = new JTextField();
            final Fenetre fenetre = new Fenetre();
            JLabel label = new JLabel("Commandes   ");
            JButton b = new JButton("OK");
            container.setBackground(Color.white);
            container.setLayout(new BorderLayout());
    
            JPanel top = new JPanel();
            jtf.setPreferredSize(new Dimension(800, 30));
            class BoutonListener implements ActionListener {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (jtf.getText().equals("lol")) {
                        fenetre.lol();
                    }
                    System.out.println("Entry  : " + jtf.getText());
                }
            }
            b.addActionListener(new BoutonListener());
    
            top.add(fenetre);
            top.add(label);
            top.add(jtf);
            top.add(b);
            top.revalidate();
            frame.setContentPane(top);
            frame.setVisible(true);
        }
    }
    

    【讨论】:

    • 恭喜,你触摸到了 10,000 的神奇数字 :-)
    • 非常感谢!现在图像已正确显示,唯一的问题是当我在输入字段中使用命令“lol”启动lol() 时,我只是尝试更改矩形的颜色,但它没有,它返回错误作为 NullPointerException(没有文本?) PS:我让扩展 JFrame 用于 repaint() 方法。没看懂方法revalidate的意思
    • @Mizur revalidate 需要被调用,以便布局添加到层次结构中的组件。永远不要自己调用paintComponent,只需调用repaint()。我会将你的代码的更新版本添加到我的帖子中,因为你的代码中确实存在很多问题。
    • @Mizur:你应该通过点击它左边的大复选标记来“接受”这个答案。
    • 其实还有一个问题:InitUI(()方法是静态的,所以我所有的方法也必须是静态的,有点烦人!
    【解决方案2】:

    您的 Swing 图形编程有几个重大问题,我强烈建议您阅读这些教程以了解如何更好地做到这一点。例如,你是

    • 直接调用paint方法——除非在非常特殊的情况下(这不是其中之一),否则您几乎不应该这样做
    • 直接在 JFrame 的paint(...) 方法中绘图。相反,您将需要绘制从 JComponent 派生的类(例如 JPanel)的 paintComponent(...) 方法覆盖。
    • 不必要地调用更新,就好像这是一个 AWT 程序。除非您更改外观和感觉,否则不要在 Swing 中执行此操作。

    再一次,看看这方面的教程——你不会后悔这样做的,相信我。

    编辑——太慢了! 1+ 给纪尧姆

    【讨论】:

    • 谢谢!我也按照您的建议回答另一个答案:D
    猜你喜欢
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多