I am working on a MVC based off of the code that I will be providing. I am having issues because I am fairly new to the subject. I am able to make the view, but when it comes to making the model it is a little more complicated for me. I need some guidance on how to turn the following code into a MVC so I can practice and learn. I been at this for several hours and I decided to come here for help.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class SayHi extends JFrame implements MouseListener{
// components
protected JLabel helloLabel = new JLabel("Hello");
protected JTextField userInputTextField = new JTextField(20);
private JButton sayHiBtn = new JButton("Say Hi");
/** Constructor */
SayHi() {
//... Layout the components.
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new JLabel("Enter your name"));
content.add(userInputTextField);
content.add(sayHiBtn);
content.add(helloLabel);
// Add a mouse listener to the button
sayHiBtn.addMouseListener(this);
//... finalize layout
this.setContentPane(content);
this.pack();
this.setTitle("Simple App - Not MVC");
// The window closing event should probably be passed to the
// Controller in a real program, but this is a short example.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Methods I am forced to implement because of the MouseListener
public void mouseClicked(MouseEvent e) {
helloLabel.setText("Hello " + userInputTextField.getText());
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
public static void main(String[] args){
SayHi s = new SayHi();
s.setVisible(true);
}
}
The View only controls the visuals, The Model only controls the data access and the Controller is in charge of the logic that glues the two.
You could split that class into 3 classes in order to make it a MVC.
All the Jpanel would be located in a View, in the Model you would have all your values, like setting a string to hello and such, while the controller needs to interact with both the Model and View.
private SayHiModel model;
private SayHiView view;
SayHiController(SayHiModel model, SayHiView view) {
this.model = model;
this.view = view;
this.model.setValue(model.INITIAL_VALUE);
view.totalTextField.setText(model.getValue());
//... Add listeners to the view.
view.addMultiplyListener(new MultiplyListener());
view.addClearListener(new ClearListener());
}
Just a little hint to get you going.
There isn't much of a model to work with.
Here's your example code, with one view class, one model class, and one controller class. The SayHi class is the view class. The SayHiModel class is the model class. The SayHiListener class is the controller class.
package com.ggl.testing;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class SayHi implements Runnable {
private JFrame frame;
private JLabel helloLabel;
private JTextField userInputTextField;
private SayHiModel model;
public static void main(String[] args) {
SwingUtilities.invokeLater(new SayHi());
}
public SayHi() {
this.model = new SayHiModel();
}
#Override
public void run() {
// ... Layout the components.
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new JLabel("Enter your name: "));
userInputTextField = new JTextField(20);
content.add(userInputTextField);
JButton sayHiBtn = new JButton("Say Hi");
// Add a mouse listener to the button
sayHiBtn.addMouseListener(new SayHiListener(this, model));
content.add(sayHiBtn);
helloLabel = new JLabel("Hello");
content.add(helloLabel);
// ... finalize layout
frame = new JFrame("MVC App");
// The window closing event should probably be passed to the
// Controller in a real program, but this is a short example.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
public JFrame getFrame() {
return frame;
}
public void setHelloLabel(String name) {
helloLabel.setText("Hello " + name);
}
public String getName() {
return userInputTextField.getText().trim();
}
public class SayHiModel {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class SayHiListener extends MouseAdapter {
private SayHi sayHi;
private SayHiModel sayHiModel;
public SayHiListener(SayHi sayHi, SayHiModel sayHiModel) {
this.sayHi = sayHi;
this.sayHiModel = sayHiModel;
}
#Override
public void mouseClicked(MouseEvent e) {
sayHiModel.setName(sayHi.getName());
sayHi.setHelloLabel(sayHiModel.getName());
JFrame frame = sayHi.getFrame();
frame.setVisible(false);
frame.pack();
frame.setVisible(true);
}
}
}
Related
In Java I have a simple window with a button. When I press the button I call the constructor of another class which opens a new window with a button again.
1) is correct to call a method of the View class from the Model class with the Observer Observable pattern?
2) is correct to delegate the call of the new window to the View class? or I have to do it in the Model class?
3) how can I set a listener for the new button in the Controller class? at the moment I call the constructor of the Controller class, I have an instance of the View (with the first button) but I still not have an instance of the sub-window class (and so the second button).
View:
import java.awt.*;
import java.util.Observable;
import java.util.Observer;
import javax.swing.*;
public class View implements Observer
{
JFrame frame;
JPanel panel;
JButton button;
Model model;
public View(Model model)
{
frame = new JFrame();
panel = new JPanel();
button = new JButton("Press");
this.model = model;
panel.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.add(panel);
frame.setVisible(true);
}
public void update(Observable ob, Object extra_arg)
{
switch(model.method_var)
{
case 0:
NewWindow newwindow = new NewWindow();
}
}
}
Model:
import java.util.Observable;
public class Model extends Observable
{
int method_var;
public void newwindow()
{
method_var = 0;
setChanged();
notifyObservers();
}
}
Controller:
import java.awt.event.ActionEvent;
public class Controller
{
Model model;
View view;
public Controller(Model model, View view)
{
this.model = model;
this.view = view;
view.button.addActionListener(new Action());
model.addObserver(view);
}
class Action implements java.awt.event.ActionListener
{
public void actionPerformed(ActionEvent e)
{
model.newwindow();
}
}
}
New-Window:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class NewWindow
{
JFrame frame;
JPanel panel;
JButton button;
Model model;
public NewWindow()
{
frame = new JFrame();
panel = new JPanel();
button = new JButton("Press again");
this.model = model;
panel.add(button);
frame.setSize(100,100);
frame.add(panel);
frame.setVisible(true);
}
}
Main:
public class Main
{
public static void main(String[] args)
{
Model model = new Model();
View view = new View(model);
Controller controller = new Controller(model, view);
}
}
IMHO, all the logic should be in the controllers of the components. That's their purpose. Doing so requires more effort, but it also avoids confusion as your design grows.
I didn't really know how else to phrase that but essentially:
-I have a few separate "pieces" that I am trying to add onto a master frame; to keep the code from getting unwieldy I have each "piece" be its own class.
-I'm getting stuck on adding the panells onto the master frame, because the classes themselves aren't panels, rather the method of the class creates the panel, which creates issues that I don't know how to solve.
PIECE (works on its own when I have it make a dialog instead of be a panel):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PieceThing3 extends JPanel //<switched from JDialog
{
//set up variables here
private ActionListener pieceAction = new ActionListener()
{
public void actionPerformed (ActionEvent ae)
{
// Action Listener (this also works)
}
};
private void createPiece()
{
//setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
//setLocationByPlatform(true);
// the above are commented out when I switch from dialog to panel
JPanel contentPane = new JPanel();
//something that uses pieceAction is here
//two buttons, b and s, with action listeners are here
contentPane.add(b);
contentPane.add(s);
add(contentPane);
//pack();
//again, commented out to switch from dialog
setVisible(true);
System.out.println("hi I'm done");
//just to check and make sure it's done
}
public static void main(String[] args)
{
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PieceThing3().createPiece();
}
});
}
}
Sorry that is very vague, but the intricacies are not as important as the general idea - it works perfectly when I have it create its own dialog box, but now I am trying to get it to make a panel within a master code, below:
MASTER:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CollectGUI extends JFrame{
private void createDialog(){
this.setSize(2000,1000);
this.setLocation(0,0);
this.setTitle("TITLE");
PieceThing3 pt = new PieceThing3();
//HERE, if I do pt.main(null); while it is in "dialog mode" (rather than panel) it pops up a dialog box and everything is hunky dory. But I don't know how to get it to add the method as a panel.
this.add(pt.main(null));
//this gives an error
this.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new CollectGUI().createDialog();
}
}
As I said in the comments, if I just do pt.main(null) when pt is set to make a dialog, it does it, but if I try to add pt.main(null) as a panel it throws an error. Can anybody give me some insight on how to add a method of a class rather than a class? I'm pretty stumped.
THANK YOU!!
You are definitely on the right track working to maintain separation of concerns and implement your gui in a number of distinct components. Try something like this:
Panel1
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Panel1 extends JPanel {
public Panel1() {
this.add(new JLabel("This is panel 1"));
}
}
Panel2
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Panel2 extends JPanel {
public Panel2() {
this.add(new JLabel("This is panel 2"));
}
}
JFrame
import java.awt.BorderLayout;
import javax.swing.JFrame;
import org.yaorma.example.jframe.panel.panel1.Panel1;
import org.yaorma.example.jframe.panel.panel2.Panel2;
public class ExampleJFrame extends JFrame {
public ExampleJFrame() {
super("Example JFrame Application");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400,400);
this.setLayout(new BorderLayout());
Panel1 pan1 = new Panel1();
Panel2 pan2 = new Panel2();
this.add(pan1, BorderLayout.NORTH);
this.add(pan2, BorderLayout.SOUTH);
this.setVisible(true);
}
}
main:
public class ExampleApplication {
public static void main(String[] args) throws Exception {
new ExampleJFrame();
}
}
EDIT:
Here's a Panel1 with a little more content.
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.yaorma.example.action.sayhello.SayHelloAction;
public class Panel1 extends JPanel {
//
// instance variables
//
private JButton pressMeButton;
//
// constructor
//
public Panel1() {
this.setLayout(new BorderLayout());
this.add(new JLabel("This is panel 1"), BorderLayout.NORTH);
this.initPressMeButton();
}
//
// button
//
private void initPressMeButton() {
this.pressMeButton = new JButton("Press Me");
this.pressMeButton.addActionListener(new PressMeButtonActionListener());
this.add(pressMeButton, BorderLayout.SOUTH);
}
//
// method to get the parent jframe
//
private JFrame getParentJFrame() {
Container con = this;
while(con != null) {
con = con.getParent();
if(con instanceof JFrame) {
return (JFrame)con;
}
}
return null;
}
//
// action listener for Press Me button
//
private class PressMeButtonActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JFrame jFrame = getParentJFrame();
SayHelloAction action = new SayHelloAction(jFrame);
action.execute();
}
}
}
Action called by button:
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class SayHelloAction {
private JFrame owner;
public SayHelloAction(JFrame owner) {
this.owner = owner;
}
public void execute() {
JOptionPane.showMessageDialog(owner, "Hello World");
}
}
I'm learning Swing to make GUI in java. My goal is to have 1 mainGUI class to initialize everything and another class that controls all the button.
What I'm doing now is I have a mainGUI which has:
public class mainGUI(){
.... (main and initialize things here) ....
protected JButton btnLogin;
public void initialize(){
btnLogin = new JButton("Login");
btnLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
_buttonLogin();
}
});
}
protected void _buttonLogin(){};
}
Then in my buttonControl I have:
public class buttonControl extends mainGUI{
#Override
protected void _buttonLogin(){
if (isLogin == true){
btnLogin.setEnabled(false);
} else {
// somthing else
}
}
}
The program actually works but not as i expected. When i click on the "login" button, the login button is not set to unclickable. If i don't have the _buttonLogin method in the mainGUI class then I cannot call it from buttonControl class.
I'm just wondering is my approach right in this situation? or any other neat way to have a separated listener class?
Thank you so much
For one you're misusing inheritance. You don't use inheritance to gain access to variables. For that you should use composition.
For example, ButtonControl (and note that the first letter of any class should start with an upper case letter), could have a MainGui field which is passed into it via its constructors. Then the control class can call Gui methods.
class ButtonControl extends AbstractAction {
MainGui gui;
public ButtonControl(MainGui gui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC, mnemmonic);
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
// ....
}
}
And it could be used like so:
ButtonControl btnCtrl = new ButtonControl(this, "My Button", KeyEvent.VK_M);
JButton myButton = new JButton(btnCtrl);
If you need a Single class for control all the buttons you have you can create a ButtonControl class which can register and de-register buttons to it and handle its events inside the control class. A Simple example code is given
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class MainUI extends JFrame{
ButtonController buttonController;
public MainUI() {
super();
buttonController=new ButtonController(this);
initialize();
}
private void initialize() {
JTextField userName=new JTextField();
JPasswordField passwordField=new JPasswordField();
JButton loginButton=new JButton("Login");
loginButton.setActionCommand(ButtonController.LOGIN_COMMAND);
JButton cancelButton=new JButton("Cancel");
cancelButton.setActionCommand(ButtonController.CANCEL_COMMAND);
JPanel contentPane=new JPanel();
contentPane.setLayout(new GridLayout(3,2));
contentPane.add(new JLabel("Username : "));
contentPane.add(userName);
contentPane.add(new JLabel("Password : "));
contentPane.add(passwordField);
contentPane.add(loginButton);
contentPane.add(cancelButton);
buttonController.registerButton(loginButton);
buttonController.registerButton(cancelButton);
setContentPane(contentPane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
/**
* #param args
*/
public static void main(String[] args) {
MainUI ui=new MainUI();
ui.setVisible(true);
}
}
class ButtonController implements ActionListener
{
private MainUI mainUI;
public static String LOGIN_COMMAND="Login";
public static String CANCEL_COMMAND="Cancel";
public ButtonController(MainUI mainUi ) {
this.mainUI=mainUi;
}
public void registerButton(JButton button)
{
button.addActionListener(this);
}
public void deRegisterButton(Button button)
{
button.removeActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals(LOGIN_COMMAND))
{
((JButton)e.getSource()).setEnabled(false);
}
if(e.getActionCommand().equals(CANCEL_COMMAND))
{
mainUI.dispose();
}
}
}
It's been a long time I've used swing, but we can only call the child class implementation by only from the child class object type :
mainGUI gui = new buttonControl();
we should pass buttonControl object type instance instead of mainGui instance if we want to let the caller use the implementation in buttonControl.
This related to Polymorphism with overidding.
Hopes this help..
a basic problem that i can't figure out, tried a lot of things and can't get it to work, i need to be able to get the value/text of the variable
String input;
so that i can use it again in a different class in order to do an if statement based upon the result
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class pInterface extends JFrame {
String input;
private JTextField item1;
public pInterface() {
super("PAnnalyser");
setLayout(new FlowLayout());
item1 = new JTextField("enter text here", 10);
add(item1);
myhandler handler = new myhandler();
item1.addActionListener(handler);
System.out.println();
}
public class myhandler implements ActionListener {
// class that is going to handle the events
public void actionPerformed(ActionEvent event) {
// set the variable equal to empty
if (event.getSource() == item1)// find value in box number 1
input = String.format("%s", event.getActionCommand());
}
public String userValue(String input) {
return input;
}
}
}
You could display the window as a modal JDialog, not a JFrame and place the obtained String into a private field that can be accessed via a getter method. Then the calling code can easily obtain the String and use it. Note that there's no need for a separate String field, which you've called "input", since we can easily and simply extract a String directly from the JTextField (in our "getter" method).
For example:
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class TestPInterface {
#SuppressWarnings("serial")
private static void createAndShowGui() {
final JFrame frame = new JFrame("TestPInterface");
// JDialog to hold our JPanel
final JDialog pInterestDialog = new JDialog(frame, "PInterest",
ModalityType.APPLICATION_MODAL);
final MyPInterface myPInterface = new MyPInterface();
// add JPanel to dialog
pInterestDialog.add(myPInterface);
pInterestDialog.pack();
pInterestDialog.setLocationByPlatform(true);
final JTextField textField = new JTextField(10);
textField.setEditable(false);
textField.setFocusable(false);
JPanel mainPanel = new JPanel();
mainPanel.add(textField);
mainPanel.add(new JButton(new AbstractAction("Get Input") {
#Override
public void actionPerformed(ActionEvent e) {
// show dialog
pInterestDialog.setVisible(true);
// dialog has returned, and so now extract Text
textField.setText(myPInterface.getText());
}
}));
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// by making the class a JPanel, you can put it anywhere you want
// in a JFrame, a JDialog, a JOptionPane, another JPanel
#SuppressWarnings("serial")
class MyPInterface extends JPanel {
// no need for a String field since we can
// get our Strings directly from the JTextField
private JTextField textField = new JTextField(10);
public MyPInterface() {
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
JTextComponent textComp = (JTextComponent) e.getSource();
textComp.selectAll();
}
});
add(new JLabel("Enter Text Here:"));
add(textField);
textField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window win = (Window) SwingUtilities.getWindowAncestor(MyPInterface.this);
win.dispose();
}
});
}
public String getText() {
return textField.getText();
}
}
A Good way of doing this is use Callback mechanism.
I have already posted an answer in the same context.
Please find it here JFrame in separate class, what about the ActionListener?.
Your method is a bit confusing:
public String userValue(String input) {
return input;
}
I guess you want to do something like this:
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
Also your JFrame is not visible yet. Set the visibility like this setVisible(true)
Description of the problem: I have a JFrame, inside this JFrame there is a JPanel with a button, when I press the button an action listener change the current JPanel with a new JPanel, which contains other two JPanels, those two have an inputMap that when the user press the key "up" make something on both of them. The problem is: when I change the JPanel with the new one the "up" key won't do anything.
Here is the code: is a SSCCE, so you just have to copy and paste to see what it does.
This modified code comes from another question that I "solved" sometimes ago. How to make two JPanels listen to the same event?
(the code is in the answer that I selected).
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class TwoPanelsTest extends JFrame {
private static MyPanel one = new MyPanel("One");
private static MyPanel two = new MyPanel("Two");
private static List<MyPanel> list = Arrays.asList(one, two);
private PanelsController panelsController;
public TwoPanelsTest() {
super("TwoPanelsTest");
panelsController= new PanelsController(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400,400);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private static class MyPanel extends JPanel {
private String string = " will be updated though its action.";
private Action action = new UpdateAction(this);
private String name;
private JLabel label;
public MyPanel(String name) {
this.name = name;
this.label = new JLabel(name + string, JLabel.CENTER);
this.setLayout(new GridLayout());
this.setFocusable(true);
this.add(label);
}
public Action getAction() {
return action;
}
private void update() {
label.setText(name + ": " + System.nanoTime());
}
private static class UpdateAction extends AbstractAction {
private MyPanel panel;
public UpdateAction(MyPanel panel) {
this.panel = panel;
}
#Override
public void actionPerformed(ActionEvent ae) {
panel.update();
}
}
}//MyPanel
private static class ButtonPanel extends JPanel{
private JButton button ;
private PanelsController panelsController;
public ButtonPanel(PanelsController panelsController){
this.panelsController=panelsController;
button = new JButton("Button");
button.setActionCommand("buttonPressed");
button.addActionListener(this.panelsController);
this.setFocusable(true);
add(button);
}
}//ButtonPanel
private static class PanelsController implements ActionListener {
private TwoPanelsTest twoPanelsTest;
public PanelsController(TwoPanelsTest twoPanelsTest){
this.twoPanelsTest=twoPanelsTest;
this.twoPanelsTest.getContentPane().add(new ButtonPanel(this));
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand().equals("buttonPressed")){
twoPanelsTest.getContentPane().removeAll();
twoPanelsTest.getContentPane().invalidate();
JPanel panel = new JPanel(new GridLayout(0, 1, 10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(one);
panel.add(two);
panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
panel.getActionMap().put("up", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
for (MyPanel panel : list) {
panel.getAction().actionPerformed(e);
}
}
});
twoPanelsTest.getContentPane().add(panel);
twoPanelsTest.validate();
twoPanelsTest.repaint();
}
}//ActionPerformed
}//PanelsController
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TwoPanelsTest t = new TwoPanelsTest();
}
});
}
}
Well, its pretty simple - if you have those two panels without any components inside and want them to listen the hotkey use:
panel.getInputMap ( JComponent.WHEN_IN_FOCUSED_WINDOW )
.put ( KeyStroke.getKeyStroke ( KeyEvent.VK_UP, 0 ), "up" );
JComponent.WHEN_IN_FOCUSED_WINDOW instead of JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Otherwise you need to have somthing focused inside the panel so it could catch the key events.
By the way, there is also another way to listen global hotkeys inside Java application windows:
Toolkit.getDefaultToolkit ().addAWTEventListener ( new AWTEventListener ()
{
public void eventDispatched ( AWTEvent event )
{
// All application key events will be passed here
}
}, AWTEvent.KEY_EVENT_MASK );