The client has requested a Graphical Interface for their currently command-line driven program. (The program animates a flowchart in a separate window.) The commands activate loops which repaint the flowchart window.
The problem I am having is that when using my GUI, the flowchart does not animate. repaint() is not repainting the same way.
I have tried the solutions at How can I write to stdIn (JAVA) and JUnit testing with simulated user input but they all rely on System.setIn(in) which doesn't work for me.
Here is a minimal code that shows the problem. Enter commands via the standard input and you will see them animate. Do the same thing via the GUI and there is no animation. Both input methods run the same command, drawFakeData - so why do they produce different results??
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class FlowChart {
public GUImin gui;
private static int i;
public static void main(String[] args) {
FlowChart sdm = new FlowChart();
sdm.runInterpreter();
}
public FlowChart() {
EventQueue.invokeLater(() -> {
gui = new GUImin();
});
}
public void runInterpreter() {
Scanner takeCommand = new Scanner(System.in);
String userCommandLine;
do {
//capture all Standard Input from console
userCommandLine = takeCommand.nextLine();
processInput(userCommandLine);
} while (!userCommandLine.equals("quit"));
takeCommand.close();
}
public void processInput(String input) {
for (i = 0; i < 10; i++) { //emulate an animation loop
EventQueue.invokeLater(() -> {
gui.drawFakeData(input + i);
});
// pause for a given number of seconds
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class GUIpanelmin extends JPanel {
public String input = "^";
public int x;
public int y;
public GUIpanelmin() {
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g); //no idea what this does - draws background I think?
System.out.println("GUI: " + "Paint Component Reached.");
Graphics2D g2d = (Graphics2D) g; //or this
g2d.drawString(input, x, y); //just an example
}
}
public class GUImin extends JFrame {
public GUIpanelmin GUIpanel;
public GUImin() {
super("GUI");
super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
super.setVisible(true);
setSize(350, 250); //TBD
setLocationRelativeTo(null); //centers the panel
this.getContentPane().setLayout(new FlowLayout());
//input text box
JTextField inputField = new JTextField(10);
inputField.setPreferredSize(new Dimension(200, 30));
add(inputField);
//the button
JButton submitButton = new JButton("Submit Command");
submitButton.setPreferredSize(new Dimension(40, 30));
submitButton.addActionListener(e -> {
for (int i = 0; i < 10; i++) { //emulate animation loop
drawFakeData(inputField.getText());
// pause for a given number of seconds
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
inputField.setText("");
});
add(submitButton);
//the panel with all the pretties
GUIpanel = new GUIpanelmin(); //there's only one
GUIpanel.setPreferredSize(new Dimension(300, 300));
add(GUIpanel);
}
public void drawFakeData(String command) {
//just an example - real thing will be much more complicated
GUIpanel.x = (int) (Math.random() * 100 + 5);
GUIpanel.y = (int) (Math.random() * 100 + 5);
GUIpanel.input = command;
GUIpanel.repaint();
}
}
}
Any help explaining this puzzling behavior is appreciated.
Edit: here is what the GUI looks like (right image):
Text from standard input (left image) animates.
Text from text box does not animate, even though both text is processed by the same code.