下面的代码是一个非常简单的测试,涉及一张图片。 每当我向 System.in 发送“a”时它应该重新绘制图像,而每当我发送“q”时它应该退出程序。
问题是只有导出有效: paint() 方法从未被调用,我也不知道为什么。
我检查了对“super.paint()”的调用,尝试用 paintCompoenent(Graphics g) 替换 paint(Graphics g) 但似乎没有任何效果:只是没有调用。
问题是否涉及 main() 中的 Scanner?
程序中的路径和我用的不一样,第一次画的是对的,应该不是问题所在。
注意,如果它有用,我正在使用 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
值呢?在您的情况下,update
方法可能是显而易见的选择....
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);
}
}
这确保 update
方法的内容在 EDT 的上下文中执行。
恕我直言,这有点乱。更好的解决方案是使用 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 应该工作的方式。
关于java - 为什么 Java repaint() 方法不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49542896/