下面的代码是涉及图像的非常简单的测试.

每当我向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 worker = new SwingWorker() {
@Override
protected Void doInBackground() throws Exception {
Scanner in = new Scanner(System.in);
while (true) {
publish(in.next());
}
}
@Override
protected void process(List 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 worker = new SwingWorker() {
@Override
protected Void doInBackground() throws Exception {
Scanner in = new Scanner(System.in);
while (true) {
publish(in.next());
}
}
@Override
protected void process(List chunks) {
for (String text : chunks) {
testimg.update(text);
}
}
};
}
}

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