Switching JPanels and keyListeners - java

I am developing a game, where you first get to the main screen, there are multiple selections to go, for example, Singleplayer, Twoplayer, Credits, etc.
I have one big problem. If I click a button in the menu, (not JButton) the JPanels switch, but the keyListener is lost. The Keylistener is in the same class as the game code, which implements JPanel. I tried everything to get the Keylistener to work, but it just won't.
Here is how the things are called: Main class --> Menu --> Game. I tried adding the keylistener to the main class, but it's not working.
So, JPanel switching is ok, but the Keylisteners are gone. I was developing the game before with new JFrames, so when I clicked a menu, a new frame was created. I didn't insert a code here, because it's too long (2000+ lines), and the KeyListener is working, but only when it is in a new JFrame. I set the mode int in the Menu class, by clicking a button.
This is currently my panel switch:
public void setJPanel() {
switch (mode) {
case 1:
getContentPane().add(s);
validate();
break;
case 2:
getContentPane().removeAll();
getContentPane().add(sp);
validate();
break;
}
}
Thanks for your help in advance!

Rather than use a KeyListener, have you given thought to or tried using Key Bindings? KeyListeners require that the component being listened to has focus, and focus may be lost for many reasons, especially when swapping views (are you using a CardLayout for this?). Key Bindings on the other hand can be set to be responsive even if the bound component doesn't have focus but when it is only held within a window that has focus. Tutorial: Using a CardLayout
Edit
I see that you're not using a CardLayout, and I suggest that you use this as it can make your view swapping cleaner and easier.
Edit 2
I agree that you don't want to post your entire 2000+ line program here as no one will have the time to read it, but consider condensing your question/problem into a single small class that is compilable and runnable by any and all of us, and demonstrates your problem. In other words, a Short, Self Contained, Compilable, Example or SSCCE .
Remember, the code should be compilable and runnable for many of us to be able to understand it fully.

Cardlayout actually is screwy while refocusing.
#op, try calling requestFocusInWindow() after the new jpanel was added

Try using myPanel.requsetFocusInWindow();
before using setVisible(true);

Related

Two JPanels, requesting focus and Keyboard input

Learning GUIs for an assignment, and would appreciate some advice...no code, for the aforementioned reason.
I have a programme with a JFrame, and a single JPanel, that contains methods that take keyboard input using the KeyEvent class.
My class that extends JPanel, has the following in it:
setFocusable(true);
requestFocus();
I've since modified the programme, to include a second JPanel (to add a control panel to the right containing 4 JButtons).
The problem is that the keyboard input no longer works on the first JPanel when I run the programme (it did before).
The keyboard input on the right JPanel only works before the second JPanel has been added to the programme. If I remove the second JPanel, keyboard input works, when it is there it doesn't....
I realised that I had setFocusable(true); and requestFocus(); in both panels, so I deleted it from the second panel (with the JButtons), but it still doesn't work. I sense it's a focus issue.....any advice?
Do I need to look at KeyBindings (don't know what this is yet, but a few similar threads suggest it)....
We can't tell you what is wrong based on two lines of code. We have no idea what panel1 and panel2 do or what components they contain.
My class that extends JPanel, has the following in it:
A couple of problems with that:
You should NOT be using the requestFocus() method. Read the API for that method and it will tell you the appropriate method to use.
Even if you do use the appropriate method, you can't use that method in the constructor of a class. Requesting focus on a component can only be done to visible components on a GUI.
Do I need to look at KeyBindings
Yes, Swing has newer and better API's than AWT. In AWT you didn't have a choice. In Swing you should be using Key Bindings. All Swing components do use Key Bindings and Actions. One of the main reasons is you don't have the focus issue.
Start by reading the Swing tutorial for Swing basics. There are sections on:
How to Use Key Bindings
How to Use Actions to get you started.
A Key Binding is simply the process of mapping a KeyStroke to an Action.
Also, in the future, when you ask a question post a proper SSCCE that demonstrates the problem.
If you mean with "pass back and force" that the focus should move on tab keypress between those two, use a FocusTraversalPolicy where you define who should get focus in which order.
When you click on a button, that button receives the keyboard focus. If you want the focus to revert back to the first JPanel, then you should add an ActionListener to each button, and in the actionPerformed() method of the listener just add the line:
firstPanel.requestFocusINnWindow();

Have KeyListener listen to different JFrame

Okay so long story short, here is what is happening and what I am trying to do.
I have a class called GameGUI, this is a JFrame.
This JFrame is populated with tiles(JLabels with ImageIcons)
I use my arrow keys to move my guy around the JFrame (just updates the JLabel Images)
I made a settings option, this is a new JFrame that I setVisbile(true), make changes, then setVisible(false)
After I setVisible(false) my arrow keys no longer make my character move on GameGUI.
I have tried the following, oh which none work: (all guesses based off Googling my problem)
GameGUI gg = new GameGUI();
gg.setFocusable(true);
gg.addKeyListener(null);
gg.requestFocusInWindow();
I cannot seem to find a way to get my KeyListener to move back to the GameGUI after I open (make visible) this settings menu then close it (make invisible). I do have radio buttons within the settings menu which is why I believe it gains focus, due to a physical mouse click.
Any help on getting focus back onto GameGUI would be much appreciated!
Thanks!
5.After I setVisible(false) my arrow keys no longer make my character move on GameGUI.
Don't use a KeyListener. Swing was designed to be used with Key Bindings.
See Motion Using the Keyboard, which will explain your probable problem and give the solution using Key Bindings.

Why do I have to use setvisible() on my JFrame when I change components?

So for the sake of simplicity I set up a little test code just to figure out this problem. Basically I have a JFrame and I added 'this' to it (I just extended my main class from JComponent to save time). this component fills in a red background. Then I have it sleep for 2 seconds and then type this.
f.remove(this);
thing t = new thing();
f.add(t);
f.setVisible(true);
f being my JFrame object and 'thing' is just another class extending JComponent that paints a blue background..
when I comment out setvisible() it no longer changes to blue.. I've tried using t.setVisible(true) but it seems I have to make the frame visible again, not the component
does anyone know why I have to call that... or if there is another way to change components within a single frame?
"Basically I have a JFrame and I added 'this' to it (I just extended my main class from JComponent to save time). this component fills in a red background. Then I have it sleep for 2 seconds and then type this."
Don't "sleep" your program. Instead use a java.swing.Timer to perform repeated tasks on the GUI or for animation. See more at How to Use Swing Timers. You can see a bunch of Timer examples here and here and here and here and here
Instead of trying to add and remove panels look into using a CardLayout which allows you to switch between views. It will help you avoid a lot of problems that come with with adding and removing components/containers. See more at How to Use CardLayout. Also see a simple example here.
To answer your main question, whenever you remove and add components from your frame, you need to revalidate() it. setVisible() takes care of that for you.
Side Note
Seems like a lot adding an removing background panels) just to change the background. Why not just setBackround()? You can switch colors with the use of the Timer
Calling setVisible(true) makes the frame appear onscreen. Sometimes you might see the show method used instead. The two usages are equivalent, but we use setVisible(true) for consistency's sake.

JPanel data getting changed on mouse click

I am using three JButtons in my swing application. When I click on each button, the corresponding data (formatted in JTable with JScrollPane) will display on JPanel.
Problem: when I resize the JFrame, the JPanel is replacing with default button (the button which i was clicked first) information instead of current JButton information.
My sample code:
jbutton1.addActionListener(this);
jbutton2.addActionListener(this);
public void actioPerformed(ActionEvent e){
if(e.getActionCommand.equals("button1"))
JPanel.add(table1);
}
if(e.getActionCommand.equals("button2"))
JPanel.add(table1);
}.......
Resizing the JPanel will not suddenly replace components or add other components to the panel.
My best guess (and it is a guess due to the limited information in the question) is that none of your buttons actually work and just show the wrong information.
The code you posted only contains an add without any revalidation of the layout. Consult the javadoc of the Container#add method. When you resize, the layout gets revalidated and you see what is actually contained in the JPanel.
Possible solutions:
Call invalidate and repaint on your panel as well in your ActionListener
Use a CardLayout to switch between the different components
I personally prefer the CardLayout option, but it might depend a bit on the situation.
Note that in the code you posted, you add table1 for both buttons. Might be a copy-paste problem, or a problem with your actual code.
I was unable express problem clearly.Sorry for your inconvenience.
JPanel.removeAll() method has fixed my problem.
I added this method before adding any new component to JPanel. That fixes JPanel unexpected behavior.

how to start, developing swing based application with few panels with next buttons for each

I'm new to java.I'm creating a swing based UI. I've created 2 frames, each one in separate .java file inside same package.
These two frames represents 2 screens (panels) of application. When Next button in first frame is clicked, it should move to second frame.
When I checked, these two classes are having main method, I think it should be correct way for creating applications. there should be only one main method.
When Next is clicked, I'm trying to make setVisible(false) for main panel of first frame and setVisible(true) for main panel of second frame. But this cannot be done, since the panels within a class are private. Any resolution for the above problem?
As I'm beginner, Can somebody suggest me in how to start up with these kind of applications? what are the guidelines that need to be followed? And please help me in finding documentation related to starting up with the development of such applications.
After going through the answers, My comments are:
I used the following code to go to next panel from first panel, but didn't worked.
private void gotoNextPanel(){
// jPanelFirstScreen.setVisible(false);
JPanelSecondScreen jpanelSecondScreen= new JPanelSecondScreen();
jpanelSecondScreen.setVisible(true);
UpgradeUtilityGUI upgradeUtilityGUI = new UpgradeUtilityGUI();
upgradeUtilityGUI.removeAll();
validate();
repaint();
// upgradeUtilityGUI.add(jpanelSecondScreen);
upgradeUtilityGUI.getContentPane().add(jpanelSecondScreen, "card2");
jpanelSecondScreen.setVisible(true);
validate();
repaint();
}
I'm using netbeans, and 've added two panels to the cardlayout of frame. And when I use the above code to change panels, Nothing is happening, the first panel is still appearing. Can somebody tell me, how to write code for moving from one panel to another when both the panels 've been added to cardlayout of jFrame ?
Use a CardLayout, as shown here (and one frame) as mentioned by others.
When Next is clicked, I'm trying to make setVisible(false) for main panel of first frame and setVisible(true) for main panel of second frame. But this cannot be done, since the panels within a class are private. Any resolution for the above problem?
Make the panels public access level and they will be available from other packages.
One problem in that code snippet is implied by the line:
UpgradeUtilityGUI upgradeUtilityGUI = new UpgradeUtilityGUI();
It goes out of scope before ever being added to a container. Also, their should be no need to remove anything when adding a new card to the layout, and no need to call repaint().
If your application is as simple as having only two panels you shouldn't create two JFrames. You should create a JFrame with two JPanel each of them contains the neccessary information for you. If you are ready with your first panel you can call setVisible(false) on it, and call setVisible(true) on the 2nd frame. It is the one of the most easy-to-understand solution.
But, it only depends on you if it is good for you or you would like to use some more detailed solution.
Don't use two or more JFrames, nor with separated and compiled Jar files, this is road to the hell, better would be look at CardLayout,
What you should do is have a single JFrame for the application, then you add and remove JPanels as you want to move between screens.
Each of your JPanels should basically have the following...
1. A JButton called "Next"
2. A ButtonListener for each button, that tells the JFrame to load panel2, panel3, etc.
As part of the ButtonListener, you basically just want to call something like JFrame.removeAll() to remove the existing panel, then JFrame.add(JPanel) to add the next panel.
By having 1 JFrame, you also only have 1 main() method.

Categories

Resources