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();
Related
I've been working on a console based program that acts as an inventory of Plant objects.
I have a parent class "Plant" that has child classes of "Flower", "Weed", etc... These objects are added, removed, displayed, searched through another class containing the main method and methods for the actions above.
The methods/actions are chosen by the user via console input processed with a switch statement.
My question is this: We are adding a GUI to this console based program using a JFrame, JPanels, etc... Would the proper way to go about this be to create a new class for the interface and a new main method in that class to run the program? I would of course change the former main method to a method called by the new main.
Moving from a console program requires a lot more than just changing main methods. GUI programs are event driven. So you're not going to be running endless loops like you would in a console program.
What I mean by event driven is, for example, a button get pressed, an event is fired. You as the programmer are responsible for coding what happens when that event is fired.
So some advice.
You should go through the tutorials and learn some of the basic components and how they work. Some of the basic ones are JLabel, JTextField, JButton
You will definitely need to focus on how to write event listeners. Some of the basic ones you may want to focus on are ActionListener for button presses MouseListener for mouse events.
Should learn to layout out components correctly. Some of the basic layouts you may want to focus on are GridLayout, BorderLayout, and FlowLayout
You want to learn about the basic containers like JFrame and JPanel and learn their capabilities
The Swing tutorials are always a good place to start. Once you pick up on the basics, then move on to some more complex material.
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.
I have a left Panel with multiples Jlabels which i use them as buttons to change a Main Panel's content which is layouted with a CardLayout.
I cant work perfectly with these events:
mouseEntered : to make highlight effect to the jlabel
mouseExited : to take off the highlight effect.
mouseClicked : to change the content of the main Panel and start some threads
The problem here that can't found an event or a method tell me that another Jlabel has been clicked so i can stop my threads started in the mouseClicked event,
OR
an event or method tell me that a JPanel in the CardLayout has been displayed or hidden.
Your problem is not finding an appropriate event. I think you are doing this using a visual GUI builder and expect to solve everything out-of-the-box. It's not going to work that way, you will need to write some real code. For example, write a method that you will call from the mouse click listener of each of the three JLabels. Thus you will have arranged for this method to be called for each JLabel click. Then in the method do the appropriate handling. This is just a rough outline, you haven't provided much detail to give any further advice.
It sounds like you need FocusEvents and FocusListeners. These are supported by all JComponents like JPanel, JLabel, and JButton, such as by calling addFocusListener();
Basically a FocusListener can tell you when a JComponent gains focus (such as by clicking on the JComponent) and when it looses focus (such as by clicking on a different JComponent).
Refer to http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/event/FocusListener.html for further information
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);
Hello my Japplet is using a JComboBox and 5 JRadioButtons to draw and paint on the applet. Currently everything works except for my JRadioButtons which doesn't call the itemStateChanged() when a button is selected. So on the applet I can click on a button, but it won't fire. My combobox is also using the itemlistener interface and it works, but no matter what I've tried I can't get the buttons to send information/fire.
I noticed that it requires two clicks to select a button, and hope that a problem lies within that.
This is for a homework problem and if I could use an actionperformed and actionlistener I would :(. I need to use itemlistener. Below are examples of how I'm calling my radiobuttons, adding them to the shapes buttongroup, and adidng the buttons to the container c.
Thanks for any help!
Sorry to anyone reading this but because it was homework I'm not 100% sure I can keep the code up, PM me if you need help understanding it!
The code you posted is NOT a SSCCE!
Your question is about an ItemListener, so why did you post code related to a MouseListener and a MouseMotionListener? What does the custom painting code have to do with your problem?
How do you know you the ItemListener code isn't being invoked? Did you add a System.out.println(...) statement to the listener code? Test your code first using the "appletviewer". Its easier than using the browser. From the command line all you do is:
appletviewer P6.html
Or I find it easer to test the applet without even creating an HTML file. YOu can add the following line of code to the top of your source file:
// <applet code="P6.class" width="800" height="600"></applet>
Now from the command you you can test the applet just by using:
appletviewer P6.java
The problem with you code is that your radio buttons are defined as both class and local variables. The ItemListener generates a NullPointerException, because the class variables are null.
JRadioButton jrbOval = new JRadioButton("Oval");
should be:
jrbOval = new JRadioButton("Oval");
Also, you should not be overriding the paint() method of JApplet. Custom painting is done by overriding the paintComponent() method of a JPanel. Then you add the panel to the applet.
In general it's a bad idea to use your Applet class for so many Listeners. It just adds to the confusion and you now have a God object that handles too many events. See this discussion for more info:
Advantages to Nested Classes For Listeners in GUIs
The second issue is that you are heavily mixing java.awt and javax.swing objects, which are known to cause problems when they are put in the same container. You should definitely try splitting your Applet into 2 JPanels, one for awt stuff (paint, shapes, etc) and one for swing stuff (buttons, boxes, etc).
You seem to be using the ItemListener class properly, but when I saw that it takes two clicks to select a button, that was an obvious sign of awt/swing mixing/painting problems.