I'm trying to open a JFrame that will eventually display values from the code itself but I need the application to continue to run and print things to console after opening the JFrame. At the moment, my application just stops.
Here is my code implementing my JFrame class:
public void start(){
gameWindow window = new gameWindow();
Scanner scanner = new Scanner(System.in);
char[] letterSelect = new char[9];
List <String> previousGuesses = new ArrayList<String>();
wordMethods methods = new wordMethods();
methods.randomSelect(letterSelect);
while(true){
etc...
And the code stops as soon as I create the gameWindow object 'window'
Here is my gameWindow class:
public class gameWindow extends JFrame{
gameWindow(){
super("Word Wheel");
setSize(600,600);
setResizable(false);
setDefaultCloseOperation(HIDE_ON_CLOSE);
setLayout(new FlowLayout());
}
public void paint(Graphics wheel){
wheel.setColor(Color.BLACK);
wheel.drawOval(100, 100, 200,200);
}
public static void main(String[] args){
new gameWindow().setVisible(true);
gameWindow w = new gameWindow();
}
I have tried changing the default close operation to the different options available as I feel that this is the key to my problem, but I just can't see how to progress.
Any guidance would be appreciated!
Your app does keep running. The GUI will be kept alive by the Event Dispatch Thread, but if your main method ends, one thread will die.
Your first snippet of code is very unclear, you have some random method start() and you don't ever seem to even set the frame to be visible.
Your main method in the gameWindow class (btw, the name should be GameWindow) creates two frames, one which will stay hidden.
If you want good answers, ask a good question. At the moment you're not showing all the relevant code or even showing how you're running your program. Are you running the main method of gameWindow or some other class?
Related
I'm currently trying to build a small program for school. If you click on a checkbox it should show other elements. I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked but if i put a loop the whole program won't start. I don't understand why.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test extends JFrame {
private JCheckBox moredetailscheck;
private JTextField inputfielduser;
public static void main(String[] args) {
test venster = new test();
venster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
venster.setSize(800, 600);
venster.setVisible(true);
venster.setTitle("true");
venster.setResizable(false);
}
public test() {
setLayout(new FlowLayout());
moredetailscheck = new JCheckBox("checkbox", false);
add(moredetailscheck);
inputfielduser = new JTextField(15);
while(true) { // you want to let the program keep going over these lines
if(moredetailscheck.isSelected()) {
add(inputfielduser);
}
}
}
If you click on a checkbox it should show other elements.
So, you would attach a listener to the JCheckBox, here an ItemListener, that responds when the state of the JCheckBox changes.
I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked
This is called "polling" and is needed for linear console programs where you need to continually obtain input from the user, again in a "linear" fashion. In these types of programs, you the programmer are in complete control over program code flow, but that's not what you want here.
but if i put a loop the whole program won't start. I don't understand why.
That's because you're now using an event-driven GUI library, there the Swing library, and by calling a while (true) loop on the event thread, you completely block it, rendering your GUI useless. Your program is starting, but it can't construct the GUI, draw itself or listen for events.
Solution:
Get rid of the while (true) loop. Again, it is useful for simple console programs but not in this situation.
Add an ItemListener to your JCheckBox. You can find out how to do that in the check box tutorial
Don't keep adding items to your GUI. Use a CardLayout to swap views. The tutorial can be found here: CardLayout tutorial.
Or even better, have all the GUI items on the GUI at startup, but use the JCheckBox state to enable/disable an item.
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
For example:
import java.awt.event.ItemEvent;
import javax.swing.*;
public class TestCheckBox extends JPanel {
private static final long serialVersionUID = 1L;
private JCheckBox moreDetailsCheck = new JCheckBox("More Details", false);
private JTextField inputFieldUser = new JTextField(15);
public TestCheckBox() {
inputFieldUser.setEnabled(false);
add(moreDetailsCheck);
add(inputFieldUser);
// add a listener to the JCheckBox
moreDetailsCheck.addItemListener(e -> {
// if checkbox selected, enable the text field. else disable it
inputFieldUser.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
});
}
private static void createAndShowGui() {
TestCheckBox mainPanel = new TestCheckBox();
JFrame frame = new JFrame("Test CheckBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
In Java, the AWT starts a thread to handle events automatically; you just let main finish and the program keeps running anyway until you call System.exit. You do need event handlers, though, for which any number of tutorials exist.
(Incidentally, your infinite loop comes before even showing your JFrame.)
Question: Ok, so this is going to sound slightly confusing due to my lack of total understanding on the subject. Currently, I am creating a game following a youtube tutorial (to understand the basics of game development in java).
After following some of the tutorials, I am confused as to what is the real purpose of the main method and the class that contains it. I thought that the main method's job was to call all the methods of its own class and the desired methods in other classes. However in my main method in my main "Game" class, here is all I have:
public static void main (String[] args) {
JFrame frame = new JFrame(title);
frame.add(game);
frame.setSize(WIDTH,HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.pack();
game.start();
}
Does frame.add(game) (game is an instance of Game) "call" all the other methods in other classes? Whatl the exactly does frame.add() do? Also, I am still trying to understand threads despite reading a lot of explanations. When I write game.start(); to "start" the thread, what exactly does this imply? Does it call all the methods in the game class only?
Here is my thread code if its needed:
private synchronized void start() {
if(running) {
return;
} else {
running = true;
}
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running) {
return;
} else {
running = false;
}
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit((0));
}
Here are the variables I initialized:
private static final long serialVersionUID = -8921419424614180143L;
public static final int WIDTH = 640;
public static final int HEIGHT = WIDTH / 4*3;
public static String title = "Game";
public static Game game = new Game();
public static GameState state = GameState.MENU;
private boolean running = false;
private Thread thread;
private Renderer gfx;
public static Game getInstance(){
I am just unsure of how all other methods in the game class and my other classes are being called if this is all I have in my main method. Any help would be GREATLY appreciated. I am really struggling here as you can probably tell.
The purpose of the main() method is to give an entry point for stand alone execution.
In your case (you did not show how game is initialized but I guess it was a static Game game = new Game(); initialized field) what happens is that first the static fields are initialized (which will call the Game() constructor).
Then the main method is started. It will set the initialized game as the content of the frame (which means the Frame will call various UI related methods like paint() from that moment on. Threading in Gui is a quite complicated topic, but for the sake of your question you can ignore it).
The rest of the methods in main are used to set up the containing frame. That's unusual for bigger applications but quite common for such small examples. (It does cause methods on game being called, for example for layout or drawing).
So finally main calls game.start() (which is the start() method on Game you have shown). It does create a new thread, which executes (by definition) the run() method on the Runable given to the new Thread(this) constructor (this, which is at this point the same instance as game).
The main() method is like any other method with respect to what it executes. Only what you explicitly execute (call) will be executed.
There is no method to automatically call all the other methods, because there is no purpose for such method. If, for some weird reason, you want such a method, just write it and from within it, do call the other methods.
A thread is a separate execution path in your program. When you call start() it begins and practically it goes to its special run() method, which is executed in parallel.
Any good introductory Java book should have detailed explanations to your questions.
The shortest answers that get at your bolded questions are:
frame.add(...) adds a component (like a button or label) to a frame or panel.
game.start() creates a new thread and calls the run() method of the game class in that thread.
So other methods you've written are called from game.run(). If they aren't in there (and they aren't in main(...)), they aren't being called.
I have to agree with the comment from PM77 though. It sounds like you're beginning in java, and Threading and GUIs are both pretty complex topics. There are basic games you can design (ie tic-tac-toe) that don't require either of them. Try those out before you tackle something as challenging as this.
The goal is a GUI where in a window, having the play button pressed will release the GUI resources and start to run my game (the game is done outside of Swing, in LWJGL).
This is the first way I can see myself doing it. To me the safer option looks like this:
public static void main(String[] args) {
// setup gui objects
JFrame frame = ...;
frame.setVisible(true);
// wait for the play button to be pressed
synchronized(frame) {
frame.wait();
}
// free the gui objects, start the game
frame.dispose();
startGame();
}
// by the way, this method is called from the button's action listener
public void onPlayButtonPress(JFrame parent) {
// end the UI
synchronized(parent) {
parent.notify();
}
}
The reason this seems 'safe' to me is that the cleanup for the GUI and the game execution is done inside the main thread. Here is the second way I can see myself doing it, but I'm not sure how I feel about it:
public static void main(String[] args) {
// setup gui objects
JFrame frame = ...;
frame.setVisible(true);
}
public void onPlayButtonPress(JFrame parent) {
// free the gui objects
parent.dispose();
startGameInNewThread();
}
This second way of doing it seems more preferrable in that it is simpler, but I am worried of some problems coming up. For example:
Disposing the frame in the Event Dispatch Thread could mess things up?
Starting a new thread for the game while the main thread has already terminated?
So the reason I'm asking this question is because I'm looking for the best way to implement this, but I'm also kind of curious if and why any wierd things will happen if I implement my program the second way.
I am making a Java gui project and it consists of two frames.
The problem is that when I call the secondframe from the firstframe, I have set it such that the firstframe visibility is set to false. The problem is how do I make the firstframe visible again by using a button from the second frame.
should i ditch this method and create a new jpanel instead??? Does jpanel have similar capabilities as jframe?
Consider using CardLayout. This way you can switch via multiple UIs without needing another frame. Here's how to use it.
Edit: As Guillaume posted in his comment, this answer from Andrew also covers how to use the layout.
Edit2:
As you requested a little more information about my latest post, here's how such a class may look like:
import javax.swing.JFrame;
public abstract class MyFrameManager {
static private JFrame startFrame,
anotherFrame,
justAnotherFrame;
static public synchronized JFrame getStartFrame()
{
if(startFrame == null)
{
//frame isnt initialized, lets do it
startFrame = new JFrame();
startFrame.setSize(42, 42);
//...
}
return startFrame;
}
static public synchronized JFrame getAnotherFrame()
{
if(anotherFrame == null)
{
//same as above, init it
}
return anotherFrame;
}
static public synchronized JFrame getJustAnotherFrame()
{
//same again
return justAnotherFrame;
}
public static void main(String[] args) {
//let's test!
JFrame start = MyFrameManager.getStartFrame();
start.setVisible(true);
//want another window
JFrame another = MyFrameManager.getAnotherFrame();
another.setVisible(true);
//oh, doenst want start anymore
start.setVisible(false);
}
}
This way you would only instantiate every JFrame once, but you could always access them via your manager class. What you do with them after that is your decision.
I also just made it thread-safe, which is crucial for singletons.
Can anyone tell me why does this timer run only once?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerTest implements ActionListener{
private Robot r;
private Timer t;
private int i;
public TimerTest(){
i = 0;
try {
r = new Robot();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t = new Timer(1000, this);
t.setRepeats(true);
t.start();
}
public static void main(String [] args){
new TimerTest();
}
#Override
public void actionPerformed(ActionEvent arg0) {
i++;
System.out.println("Action..." + i);
}
The funny thing is that, if I decrease the delay in the Timer to just 100, it works as expected. And what's even funnier is that if I delete the code in which I initialize the Robot, it doesn't work at all, the program terminates as soon as I run it.
I've tried this on Windows 7 and on Ubuntu (although on Ubuntu I couldn't use the Robot at all, since I get an exception. Something related to rights, maybe).
Your main is processed so the program stops. You can test it by using this code, adding it to TimerTest()
JFrame testFrame = new JFrame();
testFrame.setVisible(true);
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
That JFrame keeps your main not from finshing, when you close the Frame the TimerTest ends. Which concludes your main which causes the main to finsh. Ending the program and stoping your swing timer.
See "main exits before javax.swing.Timer's start() can start" at the bug database.
Evaluation
Described behavior - when application exits before Swing timer is started - is correct. Here is what's going then:
Swing timer is created.
Separate thread for swing timer is started. It will notify attached actionListeners when the timeout is passed by posting an instance of InvocationEvent to EDT.
Main thread exits.
At this moment there is no non-daemon threads running in JVM. Application is terminated.
..the evaluator goes on to add..
..This looks like a RFE rather than a defect.
One surefire way to make it behave is to create a GUI element and display it. Which is why I asked earlier..
..why exactly are you creating the timer without any GUI elements? Is this for repeated screen-shots?
To handle that situation, I would typically create and show a frame to allow the user to configure the rate and area for screenshots, then minimize the frame and begin processing when the user clicks:
Screen Capture!