So, there's a few mistakes...
Let's start here...
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());
You're creating two instances of TestImagePanel
and you're only updating the instance which is not on the screen
Something like...
JFrame frame = new JFrame("test");
TestImagePanel testimg = new TestImagePanel();
frame.add(testimg);
//...
Scanner in = new Scanner(System.in);
while (true)
testimg.update( in .next());
will help.
Next...
public void paint(Graphics g) {
super.paint(g);
System.out.println("painting LOG");
g.drawImage(image, this.xpos++, this.ypos++, this);
}
Okay, you should avoid overriding paint
, as a general preference it's recommend to override paintComponent
instead.
Because painting can occur at any time for any number of reasons, you should never update or modify the state of the UI from within paint methods, painting is for painting the current state
So, it should be something more like...
protected void paintComponent(Graphics g) {
super.paint(g);
g.drawImage(image, this.xpos, this.ypos, this);
}
Okay, so, then how do we update the xpos
and ypos
values? In your case, the update
method is probably the obvious choice....
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);
}
}
Now, this raises an issue. xpos
and ypos
are needed by the paintComponent
method, this means that these values should not be updated outside the context of the Event Dispatching Thread
A simple fix might be to do something like...
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);
}
}
This ensures that the contents of the update
method is executed within the context of the EDT.
This, IMHO, is kind of a mess. A better solution would be to use a 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);
}
}
};
This takes care of putting the updates onto the EDT for us.
This generates a solution which looks something like this...
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);
}
}
};
}
}
Now, the question is, why are you taking input from the console in a GUI program? You should be inputing data via the GUI? The above might be a good solution for reading content from a file or other automated source, but should be avoid for user input ... this isn't how GUIs are suppose to work.