I'm writing my first GUI program that actually does something and I am having problems with the action listener. The program when complete will take a double input and make conversions from one unit to another based on some radio button selections which i haven't added yet. The problem right now is the Action listener doesn't recognize my text fields.
I have an input text field and an output text fields in separate panels. I created an action listener and I added the input text field to the listener.
ActionListener handler = new HandlerClass();
textField.addActionListener(handler);
then I created an in class definition for the handler class but when I write the action preformed method textField and output cannot be resolved by the program. Can anyone see what I'm doing wrong?
public class conversionDisplay extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel northPanel;
private JPanel southPanel;
private JPanel eastPanel;
private JPanel westPanel;
public conversionDisplay() {
super("Temperature Conversion");
northPanel = new JPanel(); //create northPanel
northPanel.setLayout(new GridLayout(1,2,5,5));
northPanel.add(new JPanel());
JPanel northLabelPanel = new JPanel(new BorderLayout()) ;
northLabelPanel.add(new JLabel("Input"), BorderLayout.EAST);
northPanel.add(northLabelPanel);
JTextField textField =new JTextField(10);
northPanel.add(textField);
northPanel.add(new JPanel());
southPanel = new JPanel(); //create southPanel
southPanel.setLayout(new GridLayout(1,2));
southPanel.add(new JPanel());
JPanel southLabelPanel = new JPanel(new BorderLayout());
southLabelPanel.add(new JLabel("Output "), BorderLayout.EAST);
southPanel.add(southLabelPanel);
JTextField output;
southPanel.add(output = new JTextField( 10));
output.setEditable(false);
southPanel.add(new JPanel());
add(northPanel,BorderLayout.NORTH); //add north panel
add(southPanel,BorderLayout.SOUTH); //add north panel
ActionListener handler = new HandlerClass();
textField.addActionListener(handler);
setSize(350, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private class HandlerClass implements ActionListener{
public void actionPerformed(ActionEvent e) {
double input = textField.getText();
if (input != 0)
{
output.setText(input); //Perform conversion
}
}
}
}
Your textField JTextField is declared inside of a constructor and is thus only visible within that block (again the constructor). You need to make it an instance field of the class.
i.e.,
public class Foo {
private Bar bar = new Bar(); // this field is visible throughout the object
public Foo() {
Baz baz = new Baz(); // this is only visible within this constructor
}
So just like the bar variable above is visible while the baz variable that is declared in the constructor is not, you'll want to move your JTextField variable declarations out of the constructor.
you must parse String to Double value
public void actionPerformed(ActionEvent e) {
double input = Double.parseDouble(textField.getText());
if (input != 0)
{
output.setText(input+""); //Perform conversion
}
}
and declare JTextField output,textField as Globel.
public class conversionDisplay extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel northPanel;
private JPanel southPanel;
private JPanel eastPanel;
private JPanel westPanel;
JTextField output = new JTextField(10);
public conversionDisplay() {
super("Temperature Conversion");
Related
I have a problem with this nested class of mine. I can't add my JComponents to my panels for some reason in the constructor. It gives an error of
The method of add(JComponent, String) is undefined for the HomePanel.inputFrame
The HomePanel is the outer class while inputFrame is my inner class. My methods return JComponents and I am able to add it to my outer class but my inner class just doesn't allow it so I decided to just use add.(enterButton(), BorderLayout.SOUTH) which doesn't give any errors but when I try to use this inner class from mainWindow class, it says
The method add(JComponent) in the type container is not applicable for the arguments (HomePanel.inputFrame)
But the problem is I can use the outer class from mainWindow class which makes it confusing as to what went wrong. Is it due to it being an inner class or my order is wrong?
mainWindow class
public class mainWindow extends JFrame{
CardLayout cl = new CardLayout();
private JFrame mainPage = new JFrame("Food Expiry");
private JPanel mainPanel = new JPanel(cl);
private static final String homePage = "HomePage";
private static final String expiryDateEntry = "Expiry Date Entry";
private JPanel card1 = new JPanel();
public JPanel card2 = new JPanel();
HomePanel getGui = new HomePanel();
HomePanel.inputFrame nextPane = getGui.new inputFrame();
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
public mainWindow(){
mainPage.setSize(500, 300);
mainPage.setLocationRelativeTo(null);
mainPage.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPage.add(mainPanel);
mainPage.setVisible(true);
}
protected void mainPanel(){
card1.add(getGui);
}
protected void getInput(){
card2.add(nextPane);
}
}
HomePanel
public class HomePanel extends JPanel{
private JButton inputButton, storeButton;
private JLabel label, itemLabel;
private JPanel textAreaPanel, buttonPanel, labelPanel;
private JTextField itemField, itemCategory, expiryDate;
public HomePanel(){
setLayout(new BorderLayout());
this.add(getLabelPanel("Home"), BorderLayout.NORTH);
this.add(getButtonPanel(), BorderLayout.CENTER);
}
protected JComponent getButtonPanel(){
//add some buttons to a buttonPanel
return buttonPanel;
}
protected JComponent getLabelPanel(String topText){
//labelPanel
return labelPanel;
}
class inputFrame {
private JLabel categoryLabel, expiryLabel;
private JButton enter, back;
protected JComponent getInputFrame(){
textAreaPanel = new JPanel();
textAreaPanel.setLayout(new BoxLayout(textAreaPanel,
BoxLayout.Y_AXIS));
itemLabel = new JLabel("Item Name: ");
itemField = new JTextField(15);
textAreaPanel.add(itemLabel);
textAreaPanel.add(itemField);
categoryLabel = new JLabel("Category Name: ");
itemCategory = new JTextField(33);
textAreaPanel.add(categoryLabel);
textAreaPanel.add(itemCategory);
expiryLabel = new JLabel("Expiry Date: ");
expiryDate = new JTextField(33);
textAreaPanel.add(expiryLabel);
textAreaPanel.add(expiryDate);
return textAreaPanel;
}
protected JComponent enterButton(){
buttonPanel = new JPanel();
enter = new JButton("Enter");
back = new JButton("Back");
enter.addActionListener(new getInput());
back.addActionListener(new previousFrame());
buttonPanel.add(back);
buttonPanel.add(enter);
return buttonPanel;
}
public inputFrame(){
setLayout(new BorderLayout());
add(getLabelPanel("Expiry Date Entry"),BorderLayout.NORTH);
add(getInputFrame(), BorderLayout.CENTER);
add(enterButton(), BorderLayout.SOUTH);
}
}
I couldn't find any duplicates on this question and if anyone is able to find any, please do link it in the comments or answer it. Thank you.
So, based on...
public class HomePanel extends JPanel{
//...
class inputFrame {
//...
}
}
inputFrame extends (by default) from Object, making it compatible with Container#add, which expects some class which extends from Component.
Based on the current implementation, inputFrame is actually modifying the state of the instance of HomePanel from which it was instantiated, rather then adding components to itself
Something like...
public class HomePanel extends JPanel{
//...
class inputFrame extends JPanel {
//...
}
}
should alleviate the most pressing issues
I am making a program which displays 3 buttons, and when user clicks on "single player", it activates mouse listener which creates new panel, and is supposed to replace the existing panel with that newly created panel. But all I get after I click "single player" is the new window with white empty background. Here is the code:
public class UserInterface extends JFrame {
private JLabel singlePlayer,multiPlayer,quit;
private Container menu;
public JPanel mainPanel,fieldPanel;
private Field field;
private Snake snake1,snake2;
private Food food;
public UserInterface(){
// Adjust window
mainPanel=new JPanel();
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
mainPanel.setSize(700, 500);
setSize(710, 510);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setTitle("Snake");
//add(mainPanel);
setVisible(true);
this.getContentPane().setBackground(Color.ORANGE);
//mainPanel.setBackground(Color.GREEN);
// Instantiate buttons
singlePlayer=new JLabel();
multiPlayer=new JLabel();
quit=new JLabel();
singlePlayer.setIcon(new ImageIcon("files/singleplayer.jpg"));
multiPlayer.setIcon(new ImageIcon("files/multiplayer.jpg"));
quit.setIcon(new ImageIcon("files/quit.jpg"));
quit.addMouseListener(new Mouse());
singlePlayer.addMouseListener(new Mouse());
multiPlayer.addMouseListener(new Mouse());
// Create menu panel
menu=new JPanel(new GridLayout(3,1,0,0));
menu.setBackground(Color.ORANGE);
menu.add(singlePlayer);
menu.add(multiPlayer);
menu.add(quit);
menu.setMaximumSize(new Dimension(164,150));
// Insert menu to the center
mainPanel.add(menu, gbc);
add(mainPanel);
}
public void singlePlayer(){
field=new Field("single player");
snake1=new Snake();
food=new Food();
setVisible(false);
removeAll();
mainPanel=field.getFieldPanel();
add(mainPanel);
//setContentPane(mainPanel);
invalidate();
validate();
setVisible(true);
Thread fieldThread=new Thread(field, "Field thread");
//fieldThread.start();
Thread snake1Thread=new Thread(snake1, "Snake thread");
//snake1Thread.start();
}
private class Mouse implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getSource()==quit){
System.exit(0);;
} else if(e.getSource()==singlePlayer){
singlePlayer();
} else if(e.getSource()==multiPlayer){
}
}
and here is the field class:
public class Field extends JFrame implements Runnable {
private JPanel fieldPanel;
private JPanel leftPanel;
private JPanel centralPanel;
private JPanel rightPanel;
private String type;
private JLabel leftScore,rightScore;
private int score;
private int foodX,foodY;
private JLabel [][] field;
private final int FIELD_WIDTH=50,FIELD_HEIGHT=50;
private static final long serialVersionUID = 1L;
public JPanel getFieldPanel(){return fieldPanel;}
public Field(String type){
fieldPanel=new JPanel(new GridLayout(1,3,0,0));
fieldPanel.setPreferredSize(new Dimension(700,500));
this.type=type;
// Adjust playground and score tables
leftPanel=new JPanel();
centralPanel=new JPanel();
rightPanel=new JPanel();
leftPanel.setMaximumSize(new Dimension(100,500));
leftPanel.setPreferredSize(new Dimension(100,500));
centralPanel.setMaximumSize(new Dimension(500,500));
centralPanel.setPreferredSize(new Dimension(500,500));
rightPanel.setMaximumSize(new Dimension(100,500));
rightPanel.setPreferredSize(new Dimension(100,500));
// Set leftPanel
score=0;
leftScore=new JLabel("Score:\n"+score);
leftPanel.add(leftScore);
// Adjust field
field=new JLabel[FIELD_WIDTH][FIELD_HEIGHT];
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
field[i][j]=new JLabel("");
field[i][j].setSize(new Dimension(10,10));
field[i][j].setOpaque(true);
field[i][j].setBackground(Color.LIGHT_GRAY);
}
}
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
if(i==0)
field[i][j].setBackground(Color.BLACK);
else if(j==0)
field[i][j].setBackground(Color.BLACK);
else if(i==FIELD_WIDTH-1)
field[i][j].setBackground(Color.BLACK);
else if(j==FIELD_HEIGHT-1)
field[i][j].setBackground(Color.BLACK);
}
}
// Adjust centralPanel
centralPanel.setLayout(new GridLayout(50,50,0,0));
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
centralPanel.add(field[i][j]);
}
}
// Adjust rightPanel
rightPanel.add(new JLabel("Player 2 score: "));
fieldPanel.setLayout(new BoxLayout(fieldPanel,BoxLayout.Y_AXIS));
fieldPanel.add(leftPanel);
fieldPanel.add(centralPanel);
fieldPanel.add(rightPanel);
}
", it activates mouse listener which creates new panel,
It won't solve your problem, but don't use a MouseListener. A JButton is designed to be used with an ActionListener.
after I click "single player" is the new window with white empty background.
When creating a GUI that is designed to share the same space with multiple panels then you should be using a CardLayout to control the visible panel. Read the section from the Swing tutorial on How to Use a CardLayout for more information and examples.
Otherwise if you attempt to mange the swapping of panels manually then the basic code should be:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to repaint the components
i am making a group of radiobuttons and a Panel in the centre should change the colour clicking the radiobuttons.
Everything seems correct but ... it does not work !
With the main class i see the panel but the colour does not change ...
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChoiceFrame extends JFrame
{
public ChoiceFrame()
{
class ChoiceListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
setTheColor();
}
}
buttonPanel = createButtonPanel();
add(buttonPanel, BorderLayout.SOUTH);
colorPanel = createColorPanel();
add(colorPanel, BorderLayout.NORTH);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
colorPanel.repaint();
}
public JPanel createButtonPanel()
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3,1));
redButton = new JRadioButton("Red Colour");
blueButton = new JRadioButton("Blue Colour");
greenButton = new JRadioButton("Green Colour");
redButton.addActionListener(listener);
blueButton.addActionListener(listener);
greenButton.addActionListener(listener);
ButtonGroup group = new ButtonGroup();
group.add(redButton);
group.add(blueButton);
group.add(greenButton);
panel.add(redButton);
panel.add(blueButton);
panel.add(greenButton);
return panel;
}
public JPanel createColorPanel()
{
JPanel panel = new JPanel();
return panel;
}
public void setTheColor()
{
if (redButton.isSelected())
colorPanel.setBackground(Color.RED);
else if (blueButton.isSelected())
colorPanel.setBackground(Color.BLUE);
else if (greenButton.isSelected())
colorPanel.setBackground(Color.GREEN);
}
private JPanel colorPanel;
private JPanel buttonPanel;
private JRadioButton redButton;
private JRadioButton blueButton;
private JRadioButton greenButton;
private ActionListener listener;
private static final int FRAME_WIDTH = 400;
private static final int FRAME_HEIGHT = 400;
}
Add in your constructor also initialization of ChoiceListener.
listener = new ChoiceListener()
In your createButtonPanel() method, you should initialize your listener with:
listener = new ChoiceListener();
There's no point creating a new ChoiceListener object when an ActionListener field exists.
You can make while loop and Every time while loop will check which radioButton is selected
I'm trying to learn Swing and JFrame, so I'm creating a really simple program that asks for your name and then displays a box telling you what you've entered.
I'm trying to use a separate class from the first to act as the ActionListener and display the name that was typed in. However it's not working for me. I tried creating a constructor in the second class that sets an instance variable to the value taken in the JTextfield but it's not showing up as I expected. Please have a look;
And here's my code (I've imported all libraries properly but omitted for space's sake)
This is the main class...
public class NamePrompt extends JFrame{
private static final long serialVersionUID = 1L;
String name;
public NamePrompt(){
setLayout(new BorderLayout());
JLabel enterYourName = new JLabel("Enter Your Name Here:");
JTextField textBoxToEnterName = new JTextField(21);
JPanel panelTop = new JPanel();
panelTop.add(enterYourName);
panelTop.add(textBoxToEnterName);
JButton submit = new JButton("Submit");
submit.addActionListener(new SubmitButton(textBoxToEnterName.getText()));
JPanel panelBottom = new JPanel();
panelBottom.add(submit);
//Add panelTop to JFrame
add(panelTop, BorderLayout.NORTH);
add(panelBottom, BorderLayout.SOUTH);
//JFrame set-up
setTitle("Name Prompt Program");
//setSize(300, 150);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
NamePrompt promptForName = new NamePrompt();
promptForName.setVisible(true);
}
}
And this is the ActionListener class:
public class SubmitButton implements ActionListener {
String nameInput;
public SubmitButton(String textfield){
nameInput = textfield;
}
#Override
public void actionPerformed(ActionEvent submitClicked) {
Component frame = new JFrame();
JOptionPane.showMessageDialog(frame , "You've Submitted the name " + nameInput );
}
}
You are passing in an empty String into the ActionListener class SubmitButton when it is created and it is never updated once the text changes in the JTextField textBoxToEnterName so nothing is ever displayed.
You could pass the textBoxToEnterName JTextField to gain access to the value when required:
class SubmitButtonListener implements ActionListener {
private JTextField textfield;
public SubmitButtonListener(JTextField textfield) {
this.textfield = textfield;
}
#Override
public void actionPerformed(ActionEvent submitClicked) {
Component frame = new JFrame();
JOptionPane.showMessageDialog(frame, "You've Submitted the name "
+ textfield.getText());
}
}
I think you should have the SubmitButton class as an inner class of the NamePrompt class. This way you can use the text field's variable without having to pass it along to a new class, which might complicate things.
class SubmitButton implements ActionListener {
// Do not need this
// public SubmitButton(String textfield){
// nameInput = textfield;
// }
#Override
public void actionPerformed(ActionEvent submitClicked) {
Component frame = new JFrame();
JOptionPane.showMessageDialog(frame , "You've Submitted the name " + textBoxToEnterName.getText());
}
But be sure to define the variables outside of the constructor so it can be used by the inner class:
public class NamePrompt extends JFrame{
private static final long serialVersionUID = 1L;
JLabel enterYourName;
JextField textBoxToEnterName;
JPanel panelTop;
JButton submit;
JPanel panelBottom;
String name;
public NamePrompt(){ ..... (set up the variables here)
The final class would look like:
public class NamePrompt extends JFrame{
private static final long serialVersionUID = 1L;
String name;
JLabel enterYourName;
JTextField textBoxToEnterName;
JPanel panelTop;
JButton submit;
JPanel panelBottom;
public NamePrompt(){
setLayout(new BorderLayout());
enterYourName = new JLabel("Enter Your Name Here:");
textBoxToEnterName = new JTextField(21);
panelTop = new JPanel();
panelTop.add(enterYourName);
panelTop.add(textBoxToEnterName);
submit = new JButton("Submit");
submit.addActionListener(new SubmitButton(textBoxToEnterName.getText()));
panelBottom = new JPanel();
panelBottom.add(submit);
//Add panelTop to JFrame
add(panelTop, BorderLayout.NORTH);
add(panelBottom, BorderLayout.SOUTH);
//JFrame set-up
setTitle("Name Prompt Program");
//setSize(300, 150);
pack();
setLocationRelativeTo(null);
}
class SubmitButton implements ActionListener {
#Override
public void actionPerformed(ActionEvent submitClicked) {
Component frame = new JFrame();
JOptionPane.showMessageDialog(frame , "You've Submitted the name " + textBoxToEnterName.getText());
}
}
public static void main(String[] args) {
NamePrompt promptForName = new NamePrompt();
promptForName.setVisible(true);
}
}
There is the problem:
submit.addActionListener(new SubmitButton(textBoxToEnterName.getText()))
To the listener you are passing a String instead of the textfield, change it to accept textfield :)
And at
public void actionPerformed(ActionEvent submitClicked) {
Component frame = new JFrame();
JOptionPane.showMessageDialog(frame , "You've Submitted the name " + nameInput );
}
ask the textfield current value
Ok say I have a JPanel "controls" and jpanel "graphPanel" within another jpanel
public class outer extends JPanel implements ActionListener{
private JPanel controls,graphPanel;
private JButton doAction
public outer(){
JPanel controls = new JPanel();
JButton doAction = new JButton("Do stuff");
doAction.addActionListener(this);
controls.add(doAction);
JPanel graphPanel = new JPanel();
this.add(controls);
this.add(graphPanel);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==doAction){
//How do I fire paintComponent of controls JPanel on this click
}
How do i make "graphPanel" repaint after my button is clicked
The doAction and graphPanel are declared twice - once at the class level, then again in the method:
private JPanel controls,graphPanel; // declared here first
private JButton doAction; // declared here first
public outer(){
JPanel controls = new JPanel(); // Whoops, declared here again
JButton doAction = new JButton("Do stuff"); // Whoops, declared here again
doAction.addActionListener(this);
controls.add(doAction);
JPanel graphPanel = new JPanel(); // Whoops, declared here again
...
In the method remove the declaration, and make them simple assignments, like this:
controls = new JPanel(); // no leading 'JPanel'
Do that and the additional repaint code won't throw a NPE