ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

为什么Java repaint()方法不起作用?

2019-10-14 01:03:57  阅读:749  来源: 互联网

标签:repaint java swing paint


下面的代码是涉及图像的非常简单的测试.
每当我向System.in发送“ a”时,它应该重新绘制图像,而当我发送“ q”时,它应该退出程序.

问题在于只有出口有效:
永远不会调用paint()方法,我也不为什么.

我检查了对“ super.paint()”的调用,尝试用paintCompoenent(Graphics g)替换paint(Graphics g),但似乎没有任何效果:根本没有电话.

问题是否与main()中的扫描仪有关?

程序中的路径与我使用的路径不同,并且第一个画图正确,因此问题不应该存在.

注意:如果有用,我正在使用Eclipse Oxygen和Java9 SE

谢谢大家!

代码粘贴:

public class TestImagePanel extends JPanel {

    private BufferedImage image;
    private int xpos = 0;
    private int ypos = 0;
    private String _imagePath = "//myFolder//image.png";

    public TestImagePanel() {
        try {
            image = ImageIO.read(new File(_imagePath));
        } catch (IOException ex) {}
    }

    public void paint(Graphics g) {
        super.paint(g);
        System.out.println("painting LOG");
        g.drawImage(image, this.xpos++, this.ypos++, this);
    }

    public void update(String a) {
        System.out.print("Receiving:" + a + "---" + xpos + ":" + ypos);
        if (a.equals("a"))
            repaint();
        else if (a.equals("q")) {
            System.out.println("LOGOUT");
            System.exit(0);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("test");
        TestImagePanel testimg = new TestImagePanel();
        frame.add(new TestImagePanel());
        frame.setSize(new Dimension(600, 600));
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Scanner in = new Scanner(System.in);
        while (true)
            testimg.update( in .next());
    }
}

解决方法:

所以,这里有一些错误…

让我们从这里开始…

JFrame frame = new JFrame("test");
TestImagePanel testimg = new TestImagePanel();
frame.add(new TestImagePanel());

//...

Scanner in = new Scanner(System.in);
while (true)
    testimg.update( in .next());

您正在创建两个TestImagePanel实例,并且只更新了不在屏幕上的实例.

就像是…

JFrame frame = new JFrame("test");
TestImagePanel testimg = new TestImagePanel();
frame.add(testimg);

//...

Scanner in = new Scanner(System.in);
while (true)
    testimg.update( in .next());

会有所帮助.

下一个…

public void paint(Graphics g) {
    super.paint(g);
    System.out.println("painting LOG");
    g.drawImage(image, this.xpos++, this.ypos++, this);
}

好的,您应该避免覆盖paint,作为一般首选项,建议改为覆盖paintComponent.

由于绘画可能会出于多种原因随时发生,因此您绝不可以通过绘画方法来更新或修改UI的状态,绘画是用于绘画当前状态

因此,应该更像是…

protected void paintComponent(Graphics g) {
    super.paint(g);
    g.drawImage(image, this.xpos, this.ypos, this);
}

好的,那我们如何更新xpos和ypos值?就您而言,更新方法可能是显而易见的选择.

public void update(String a) {
    xpos++;
    ypos++;
    System.out.print("Receiving:" + a + "---" + xpos + ":" + ypos);
    if (a.equals("a"))
        repaint();
    else if (a.equals("q")) {
        System.out.println("LOGOUT");
        System.exit(0);
    }
}

现在,这引起了一个问题. paintComponent方法需要xpos和ypos,这意味着这些值不应在事件调度线程的上下文外部进行更新.

一个简单的解决方法可能是做类似…

public void update(String a) {
    if (!EventQueue.isDispatchThread()) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                update(a);
            }
        });
    }
    xpos++;
    ypos++;
    System.out.print("Receiving:" + a + "---" + xpos + ":" + ypos);
    if (a.equals("a")) {
        repaint();
    } else if (a.equals("q")) {
        System.out.println("LOGOUT");
        System.exit(0);
    }
}

这样可以确保在EDT的上下文中执行update方法的内容.

恕我直言,这有点混乱.更好的解决方案是使用SwingWorker

SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
    @Override
    protected Void doInBackground() throws Exception {
        Scanner in = new Scanner(System.in);
        while (true) {
            publish(in.next());
        }
    }

    @Override
    protected void process(List<String> chunks) {
        for (String text : chunks) {
            testimg.update(text);
        }
    }

};

这有助于将更新内容放入我们的EDT中.

这产生了一个看起来像这样的解决方案…

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class TestImagePanel extends JPanel {

    private BufferedImage image;
    private int xpos = 0;
    private int ypos = 0;
    private String _imagePath = "//myFolder//image.png";

    public TestImagePanel() {
        try {
            image = ImageIO.read(new File(_imagePath));
        } catch (IOException ex) {
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println("painting LOG");
        g.drawImage(image, this.xpos, this.ypos, this);
    }

    public void update(String a) {
        System.out.print("Receiving:" + a + "---" + xpos + ":" + ypos);
        if (a.equals("a")) {
            xpos++;
            ypos++;
            repaint();
        } else if (a.equals("q")) {
            System.out.println("LOGOUT");
            System.exit(0);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("test");
        TestImagePanel testimg = new TestImagePanel();
        frame.add(new TestImagePanel());
        frame.setSize(new Dimension(600, 600));
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
            @Override
            protected Void doInBackground() throws Exception {
                Scanner in = new Scanner(System.in);
                while (true) {
                    publish(in.next());
                }
            }

            @Override
            protected void process(List<String> chunks) {
                for (String text : chunks) {
                    testimg.update(text);
                }
            }

        };

    }
}

现在的问题是,为什么要在GUI程序中从控制台获取输入?您应该通过GUI输入数据吗?以上可能是从文件或其他自动源中读取内容的很好的解决方案,但应避免用户输入…这不是GUI的预期工作方式.

标签:repaint,java,swing,paint
来源: https://codeday.me/bug/20191013/1911538.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有