简体   繁体   中英

How do i remove and add components from jPanel? Java

Ok, i am just a beginner programmer, so i am having a lot of difficulty in figuring this out. Basically i am trying to create a one digit calculator(meaning that calculations only occur with single digits of numbers). I have created the buttons, assigned them action listener and their classes, and all those stuff. And then i try to display those numbers to a label. Now the problem i have is, that, i have a button, which when clicked, will use a class. From that class, what i want to do is, remove all the buttons form the panel, and add new buttons. But when i try to remove the buttons, something weird happens. If i click that button, the buttons instead of getting removed/disappering, they stay there, but i cant interact with them. Any help to fix that? I want to completely remove them from the panel. Then i want to add new buttons in their place.

Here is the code of the main class

package onecalculator;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class code {
static JLabel see = new JLabel("Int a");
static JLabel no = new JLabel("Int b");
static JLabel lol = new JLabel("Answer");
static JPanel area = new JPanel();
static JButton secn = new JButton("next");
static JButton one = new JButton("1");      
static JButton two = new JButton("2");
static JButton three = new JButton("3");
static JButton four = new JButton("4");
static JButton five = new JButton("5");
static JButton six = new JButton("6");
static JButton seven = new JButton("7");
static JButton eight = new JButton("8");
static JButton nine = new JButton("9");

static JButton bone = new JButton("1");     
static JButton btwo = new JButton("2");
static JButton bthree = new JButton("3");
static JButton bfour = new JButton("4");
static JButton bfive = new JButton("5");
static JButton bsix = new JButton("6");
static JButton bseven = new JButton("7");
static JButton beight = new JButton("8");
static JButton bnine = new JButton("9");
static JButton div = new JButton("div");
static JButton mul = new JButton("mul");
static JButton add = new JButton("add");
public int a;
public int b;
    public static void main(String[] args) {
        JFrame screen = new JFrame("One Digit Calculator");
        screen.setSize(400,600);
        screen.setResizable(false);
        screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        screen.add(area);
        area.add(see);
        area.add(no);
        area.add(lol);
        area.add(secn);
        area.add(one);
        area.add(two);
        area.add(three);
        area.add(add);
        area.add(four);
        area.add(five);
        area.add(six);
        area.add(mul);
        area.add(seven);
        area.add(eight);
        area.add(nine);
        area.add(div);
        
        secn.addActionListener(new secn());
        two.addActionListener(new Twoc());
        three.addActionListener(new Threec());
        four.addActionListener(new Fourc());
        five.addActionListener(new Fivec());
        six.addActionListener(new Sixc());
        seven.addActionListener(new Sevenc());
        eight.addActionListener(new Eightc());
        nine.addActionListener(new Ninec());
        one.addActionListener(new Onec());
        area.setLayout(new GridLayout(4,4));
        screen.setVisible(true);
        
        
        }

}

Then here is the code of the class that removes the buttons in the panel


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class secn implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent arg0) {
        
        code.area.remove(code.one);
        code.area.remove(code.two);
        code.area.remove(code.three);
        code.area.remove(code.four);
        code.area.remove(code.five);
        code.area.remove(code.six);
        code.area.remove(code.seven);
        code.area.remove(code.eight);
        code.area.remove(code.nine);
        
        code.area.add(code.bone);
        code.area.add(code.btwo);
        code.area.add(code.bthree);
        code.area.add(code.bfour);
        code.area.add(code.bfive);
        code.area.add(code.bsix);
        code.area.add(code.bseven);
        code.area.add(code.beight);
        code.area.add(code.bnine);
    }

}

Please help.

What you would want to do is to call repaint() and revalidate() on the container (ie 'JPanel area') that holds you buttons. If you want to know exactly what repaint and revalidate do, have a look at this answer.

Below your code where you add your new buttons inside of the actionPerformed method, add the following to update the container:

code.area.repaint();
code.area.revalidate();

Keep in mind that this will cause your new elements to be added to the end of the elements that weren't deleted and in the order that you add them. You can use GridBagConstraints to select where which button is placed.


But I would say that removing the old buttons just to create new ones only for the purpose of entering the second value seems like a bad idea. Additionally, having separate ActionListeners for each button also seems a little wasteful.

I would propose having a global variable (boolean for example) to indicate whether you're using the first or second value.

static boolean isFirst = true;

When the 'next button' is pressed, you could then change this variable to 'false' and not remove any of the buttons. In your ActionListener you would just look at this variable to know whether to assign the pressed number to value a or value b.

For your ActionListener for the number buttons, I would propose to reuse one for all of them like this:

class MyListener implements ActionListener{
    int value;

    //when creating new instances of MyListener, you give each listener 
    //an int equivalent to the buttons value
    MyListener(int value){
        this.value = value;
    }

    @Override
    public void actionPerformed(ActionEvent arg0){
        if(isFirst){  //first value
            a = value; //add value to your first number in any way you like
        } else {      //second value
            b = value; //add value to your second number in any way you like
        }
    }
}

You would assign your ActionListener as follows:

two.addActionListener(new MyListener(2));
three.addActionListener(new MyListener(3));

I hope this is helpful and understandable. There are probably better ways to do it, but this would be my suggestion. I'm open to feedback on this.

The easiest solution would be to create a new JPanel instead of deleting the old buttons.

JPanel newArea= new JPanel();

//Add new buttons

code.area = newArea;

However i think you should consider redesigning your code. First of all you should not use static variables for your code class. Instead make them private and make a objekt of your code class.

public class code{
    private JLabel see = new JLabel("Int a");
    private JLabel no = new JLabel("Int b");
    //...

    public static void main(String[] args){
    code mainClass = new code();
}

This allows you to use multiple instances of your code class instead of just one. Secondly you should not make a new class for every Actionlistener. Ecspecially since i think they are all doing the same. Also i dont think you even need to remake all the buttons. If you just want to save 2 values you can check if the first one has been set already:

class ButtonListener implements ActionListener{
    int buttonValue;
    code callingClass;

    //Save the buttonn number and the calling class
    MyListener(int buttonValue, code callingClass){
        this.buttonValue = buttonValue;
        this.callingClass = callingClass;
    }

    //If a is null set a, otherwise set b
    public void actionPerformed(ActionEvent arg0){
        if(callingClass.a == null){  
            callingClass.a = buttonValue; 
        } else {      
            callingClass.b = buttonValue; 
        }
    }
}

In your code class you should then initialize a and b with null in your constructor, alongside all the stuff you preivously initialized in your main and use the ButtonListener class as your new actionlistener.

public code(){
    a = null;
    b = null;
    //Initialize all the other stuff
    secn.addActionListener(new ButtonListener(2, this));
}

Whenever you add or remove elements to a visible Swing component, you should use revalidate() (to recalculate its layout now that children have changed) and repaint() (to repaint the component itself), as suggested by Custos' answer .

However, there is the question of why you need to do this. You have two visually identical sets of digit-buttons, that only differ in how they handle clicks. There is no need to replace the buttons - just handle those differences by keeping a little bit of extra state ( hasA and hasB varibales in my code below).

Since the introduction of lambdas (inline, anonymous functions), writing handler code for Java UIs has become much more readable and less verbose: note how my code below has 1-line handlers to bind the interface with actual logic, and how easy it would be to, say, add a new operator to the code below.

Note also that you do not need expose all graphical elements of a class as fields - here, digits and operators are only used to call digitPressed and operatorPressed , and lead to a smaller set of fields in the Calc class.

Also, by making Calc a subclass of JPanel , and avoiding any and all static fields, I can easily create multiple calculators operating side-by-side, independent of each other.

package one;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;

public class Calc extends JPanel {
    private JLabel labelA = new JLabel();
    private JLabel labelB = new JLabel();
    private JLabel labelAnswer = new JLabel();
    
    private int a;
    private int b;
    private boolean hasA = false;
    private boolean hasB = false;

    
    public Calc() {
        setLayout(new GridLayout(0, 4));

        add(labelA);
        add(labelB);
        add(labelAnswer);
        reset(); // rewrites labels, resets state

        JButton reset = new JButton("reset");
        add(reset);
        reset.addActionListener((e) -> reset());

        for (int i=1; i<10; i++) {
            JButton b = new JButton("" + i);
            add(b);
            final int index = i; // for use in lambda
            b.addActionListener((e) -> digitPressed(index));
        }

        for (String op : new String[] {"add", "mul", "div"}) {
            JButton b = new JButton(op);
            add(b);
            final String index = op; // for use in lambda
            b.addActionListener((e) -> operatorPressed(index));
        }
    }

    private void reset() {
        labelA.setText("value A: ?");
        labelB.setText("value B: ?");
        labelAnswer.setText("no operator");
        hasA = hasB = false;
    }

    private void digitPressed(int i) {
        if ( ! hasA) {
            hasA = true; 
            a = i; 
            labelA.setText("value A:" + a);
        } else if ( ! hasB) {
            hasB = true; 
            b = i; 
            labelB.setText("value B:" + b);
        }
    }

    private void operatorPressed(String operator) {
        String answer = "???";
        if (operator.equals("mul")) {
            answer = "= " + (a * b);
        } else if (operator.equals("div")) {
            answer = "= " + (a / b);
        } else if (operator.equals("add")) {
            answer = "= " + (a + b);
        }
        labelAnswer.setText(answer);
    }

    public static void main(String[] args) {        
        JFrame screen = new JFrame("One Digit Calculator");
        screen.setSize(400,600);
        screen.setResizable(false);
        screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        screen.add(new Calc());
        screen.setVisible(true);                                
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM