So I have a program which intakes a few values through a Scanner and then changes a BufferedImage
on a JFrame
accordingly. The way it changes the frame continues indefinitely through an infinite while loop. This works quickly (clearing the entire 1920x1080 frame in a few seconds) and works fine without SwingWorker
or InvokeLater
or anything.
To update the program away from a Scanner, I decided to make another frame to input variables before the main program begins. The new frame takes the values, and once a JButton
is clicked, disposes of itself and sends the values to the main program.
The problem is, once these variables were passed to the main program, the main frame in that program would create itself but freeze, and be completely transparent. This originally caught me off guard, as I could see my Eclipse window but couldn't click anything since the frame was in the way, covering the whole screen.
I tried and succeeded at using SwingWorker
and InvokeLater
, but the time either of them took to cover the frame changed from a few seconds to around thirty minutes (I calculated, didn't actually wait that long). I'm not sure why I can't use a frame to get the variables instead of a Scanner, since either way the variables get passed to the main program, and the previous frame is disposed of. I'm not too familiar with the EDT or Swing Event Queue, so any help is appreciated.
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Colors {
public static void main(String[] args) {
/*
Scanner scanner = new Scanner(System.in);
System.out.println("Enter Color Choice (Red/Green/Blue)");
String colorInput = scanner.nextLine();
Color changingColor = new Color(0, 0, 0);
if (colorInput.equals("Red"))
changingColor = Color.RED;
else if (colorInput.equals("Green"))
changingColor = Color.GREEN;
else if (colorInput.equals("Blue"))
changingColor = Color.BLUE;
scanner.close();
changing(changingColor);
*/
//OR
/*
JFrame frame = newJFrame("Start // Menu");
String[] colors = {"Red", "Green", "Blue"};
JSpinner colorSpinner = new JSpinner(new SpinnerListModel(colors));
colorSpinner.setBounds(frame.getWidth()/2 - 40, frame.getHeight()/3 - 20, 80, 40);
frame.add(colorSpinner);
JButton okButton = new JButton("OK");
okButton.setBounds(frame.getWidth()/2 - 40, frame.getHeight()/2 - 20, 80, 40);
okButton.addActionListener(event -> {
Color changingColor = new Color(0, 0, 0);
if (colorSpinner.getValue().equals("Red"))
changingColor = Color.RED;
else if (colorSpinner.getValue().equals("Green"))
changingColor = Color.GREEN;
else if (colorSpinner.getValue().equals("Blue"))
changingColor = Color.BLUE;
frame.dispose();
changing(changingColor);
});
frame.add(okButton);
frame.setVisible(true);
*/
}
public static JFrame newJFrame(String title) {
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.setSize(1920, 1080);
frame.setLayout(null);
return frame;
}
public static void changing(Color changingColor) {
Color color = changingColor;
JFrame frame = newJFrame("Color Changer // Main");
BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_RGB);
JLabel imageL = new JLabel();
imageL.setBounds(frame.getBounds());
imageL.setIcon(new ImageIcon(image));
frame.add(imageL);
frame.setVisible(true);
int x = 0, y = 0;
while (true) {
image.setRGB(x, y, color.getRGB());
imageL.setIcon(new ImageIcon(image));
frame.repaint();
x++;
if (x >= frame.getWidth()) {
x = 0;
y++;
if (y >= frame.getHeight()) {
y = 0;
if (color.equals(Color.RED)) {
color = Color.GREEN;
} else if (color.equals(Color.GREEN)) {
color = Color.BLUE;
} else if (color.equals(Color.BLUE)) {
color = Color.RED;
}
}
}
}
}
}
A SwingWorker publishing the works of an infinite while loop in doInBackground() works great. For some reason earlier when I had tried a SwingWorker I ran it once and then ran it again once it finished. Again pretty new to Swing concurrency and SwingWorkers, obviously. Big thanks to @camickr and @sorifiend!!