I am new to java swing. I have a code that generates checkboxes. I want to have a button somewhere in my frame, which on clicking, should delete the selected checkbox entries. Here is what I have so far.
public class Scroll extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("JFrame with ScrollBar");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ResultButtonBar();
newContentPane.setOpaque(true);
JScrollPane scrollPane = new JScrollPane(newContentPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.getContentPane().add(scrollPane);
frame.setSize(800, 800);
frame.setVisible(true);
JButton startButton = new JButton("Start");
frame.add(startButton, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null, "basdsadad");
}
});
}
}
and the new ResultButtonBar().java
public class ResultButtonBar extends JPanel {
private HashMap<JCheckBox, ArrayList<Integer>> map = new HashMap<>();
private JLabel _label;
private static final int MAX_CHECKS = 1000;
public ResultButtonBar() {
super();
JButton btn = new JButton();
btn.setVisible(true);
JCheckBox checkBox;
Random r = new Random();
JPanel checkPanel = new JPanel(new GridLayout(0, 1));
_label = new JLabel("You selected nothing");
checkPanel.add(_label);
for (int i = 0; i < MAX_CHECKS; i++) {
StringBuilder sb = new StringBuilder();
ArrayList<Integer> a = new ArrayList<>();
for (int j = 0; j < 2; j++) {
Integer temp = (r.nextInt()) % 100;
a.add(temp);
sb.append(temp).append(" ");
}
checkBox = new JCheckBox(sb.toString().trim());
checkBox.setName("CheckBox" + i);
map.put(checkBox, a);
checkPanel.add(checkBox);
}
add(checkPanel);
}
}
First of all, keep all your check boxes in an ArrayList so you will have a reference to them when you need it.
Then, add a JButton wherever you need. Then iterate over this ArrayList and call invalidate() on the component which contains your check boxes. Next statement would be to call the remove() method on the container; the checkPanel.
Alternatively, you may call removeAll() if all the components in the container are check boxes and you want to remove them.
The alternative pointed by StanislavL is also a good one if you have a lot of different components along with check boxes
I can think of two approaches:
if You are maintaining one JPanel instance which contains only the instances of JCheckBox, then you can first get all the checkbox's using panel.getComponents() method, check their selection state and depending on the state remove it by calling panel.remove(component). For example:
Component checkBox[] = checkBoxPanel.getComponents();
for(Component c:checkBox)
if(((JCheckBox)c).isSelected())
checkBoxPanel.remove(c);
checkBoxPanel.revalidate();
checkBoxPanel.repaint();
The last call revalidate() and repaint() on the checkBoxPanel is important for reflecting changes on the layout and graphics rendering of the components.
You can use ItemListener with the instances of JCheckBox to do things on selection state change. Use an instance of ArrayList<JCheckBox> to add the selected checkBox to the list. However you should use an implemented ItemListener: MyItemListener implements ItemListener and create one instance and add this instances to all the checkboxes to react on state change. You can use event source e.getSource() to get the JCheckBox instance on which the ItemEvent is performed.
Tutorial resource:
How to Write an Item Listener
Related
I have a ArrayList of JPanel. And each items of this list has a JButton.
Now, when JButton is clicked I want to remove its' parent JPanel from the ArrayList. So how can I make the JButton remove its' parent from the ArrayList?
Thanks in advance.
public class TestingArrayList extends JFrame {
JPanel grandPanel; // a JPanel for all the panels
ArrayList<JPanel> panelParent = new ArrayList<>(); // JPanel ArrayList
public TestingArrayList() {
super("Test");
setLayout(new FlowLayout());
grandPanel = new JPanel();
add(grandPanel);
for (int i = 0; i < 10; i++) { // adding 10 JPanel into grandPanel
panelParent.add(new JPanel());
grandPanel.add(panelParent.get(i));
// adding JButton in all panels
JButton btnParent = new JButton("X");
panelParent.get(i).add(btnParent);
// add new task button action
btnParent.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(getParent());
//What to do!!!
}
});
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 100);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new TestingArrayList();
}
}
You have all you need right in your code. You just need a final reference to the JPanel of interest as this will allow you to use it within the anonymous inner ActionListener class:
for (int i = 0; i < 10; i++) {
// make it final so that it is accessible from inner anon class
final JPanel myPanel = new JPanel();
panelParent.add(myPanel);
grandPanel.add(myPanel);
JButton btnParent = new JButton("X");
myPanel.add(btnParent);
btnParent.addActionListener(event -> panelParent.remove(myPanel));
}
If you also want to remove it from the grandPanel, then you'll need more...
btnParent.addActionListener(event -> {
panelParent.remove(myPanel);
grandPanel.remove(myPanel);
grandPanel.revalidate();
grandPanel.repaint();
});
Note, that if you wanted to use Seymore's method of removing the JPanel, you first need to understand that the source object obtained by calling getSource() on the ActionEvent parameter is the object that the listener was added to -- here a JButton not a JPanel, and also the type of object returned is Object, and so no Swing component methods can be called on it without casting. And so you would need to wrap all in parenthesis in order to allow you to call methods of that type. For example:
parentPanel.remove((JPanel) ((JButton) event.getSource()).getParent());
or
parentPanel.remove((JPanel) ((JComponent) event.getSource()).getParent());
I find it easier to separate lines when code gets this convoluted:
// since a JButton extends from JComponent
JComponent source = (JComponent) event.getSource();
JPanel parent = (JPanel) source.getParent();
parentPanel.remove(parent);
btnParent.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(getParent());
panelParent.remove((JPanel)(event.getSource().getParent()));
}
});
I have a program utilizing JTabbedPane. On one pane I have a button that updates an arrayList of objects based on input from the same pane.
What I would like to happen is have the second pane update itself with the object information based on the arrayList in the first pane.
However, I am not sure how to pass the list between the panes. Is there some way to push the array to pane #2 when the update button on the first pane is pressed?
Here is the main file. Instantiating the two tabs
public class Assignment6 extends JApplet
{
private int APPLET_WIDTH = 650, APPLET_HEIGHT = 350;
private JTabbedPane tPane;
private StorePanel storePanel;
private PurchasePanel purchasePanel;
private ArrayList computerList;
public void init()
{
computerList = new ArrayList();
storePanel = new StorePanel(computerList, purchasePanel);
purchasePanel = new PurchasePanel(computerList);
tPane = new JTabbedPane();
tPane.addTab("Store Inventory", storePanel);
tPane.addTab("Customer Purchase", purchasePanel);
getContentPane().add(tPane);
setSize (APPLET_WIDTH, APPLET_HEIGHT); //set Applet size
}
}
The first panel instantiates a button listener that applies all of the logic to the array list "compList"
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//Add Computer to list
Computer comp = new Computer();
comp.setBrandName(brandField.getText());
comp.setPrice(Double.parseDouble(priceField.getText()));
comp.setMemory(Integer.parseInt(memoryField.getText()));
comp.setCPU(typeField.getText(), Integer.parseInt(speedField.getText()));
compList.add(comp);
}
stringField.setText(listString);
alertLabel.setText("Computer Added");
}
}
Here is the other pane. The for loop at the end is what I need to push the arrayList to. After it receives the list, it populates a box with a checkbox for each object in the list
public PurchasePanel(ArrayList compList)
{
west = new JPanel();
east = new JPanel();
totalField = new JTextField();
this.compList = compList;
setLayout(new GridLayout(0,2));
add(west);
add(east);
east.setLayout(new BorderLayout());
east.add(currentTotalLabel, BorderLayout.NORTH);
east.add(totalField, BorderLayout.CENTER);
west.setLayout( new BoxLayout(west, BoxLayout.Y_AXIS));
for(Object c : compList){
System.out.println("Made it");
NumberFormat fmt = NumberFormat.getCurrencyInstance();
String str = ("BrandName:" + (((Computer) c).getBrandName() +"CPU:" + (((Computer) c).getCPU() +"Memory:" + ((Computer) c).getMemory() + "M" +"Price:" + fmt.format(((Computer) c).getPrice()))));
JCheckBox chk = new JCheckBox(str);
west.add(chk);
}
}
}
You can use the same listener used to update the first ArrayList, to update the second pane. Something like:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Update the first ArrayList
// Update the second pane
}
public class ListComboBox extends JFrame {
private String MIS = "MULTIPLE_INTERVAL_SELECTION";
private String SIS = "SINGLE_INTERVAL_SELECTION";
private String SS = "SINGLE_SELECTION";
final int COUNTRIES = 9;
private String[] countries = {"Canada", "China", "Denmark",
"France", "Germany", "India", "Norway", "United Kingdom",
"United States of America"};
private JList<String> jlst = new JList<String>(countries);
private JLabel comboLabel = new JLabel("Choose Selection Mode: ");
private JComboBox jcbo = new JComboBox();
//to hold country labels
private JLabel countryLabel = new JLabel();
public static void main(String[] args) {
ListComboBox frame = new ListComboBox();
frame.setSize(400, 200);
frame.setTitle("Exercise 17.14");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public ListComboBox() {
//Adding selection option to combobox
jcbo.addItem(MIS);
jcbo.addItem(SIS);
jcbo.addItem(SS);
// Register listener combobox
jcbo.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getItem() == MIS) {
jlst.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
if (e.getItem() == SIS) {
jlst.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
if (e.getItem() == SS) {
jlst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
});
//Combobox panel
JPanel combopanel = new JPanel(new FlowLayout());
combopanel.add(comboLabel);
combopanel.add(jcbo);
add(combopanel, BorderLayout.NORTH);
//List panel
JScrollPane listpanel = new JScrollPane(jlst);
add(listpanel, BorderLayout.CENTER);
//Bottom label panel
final JPanel labelpanel = new JPanel();
labelpanel.add(countryLabel);
add(labelpanel, BorderLayout.SOUTH);
//List listener
jlst.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
StringBuilder sb = new StringBuilder(64);
int[] indices = jlst.getSelectedIndices();
int i;
for (i = 0; i < indices.length; i++) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(countries[indices[i]]);
}
countryLabel.setText(sb.toString());
}
});
}
}
Good day, I need your help.
What I need code to do: Add selected country names from the list with scroll bar to the label below the list, remove them as they are unselected in the list.
List selection mode can be switched in JComboBox on top.
Everything works fine, but I cannot figure out the way for country names to properly appear inside the label.
Any tips on how I might accomplish that?
Thanks!
UPDATED!
setName is used for internal identification of the component. Imagin you've been give a list of components, all you know is you need to find the one with some unique identifier, that identifier is supplied via the name property. It has no effect on the output of the component.
You need to use the setText method to change what is displayed on the screen.
The next problem you'll have is setText is a replacement method. That is, it will replace what ever was previously applied with the new value. What might need to do is build a temporary String of the values you want to display and then apply that value to the label, for example...
StringBuilder sb = new StringBuilder(64);
for (i = 0; i < indices.length; i++) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(countries[indices[i]]);
}
countryLabel.setText(sb.toString());
To set text on JLabel use countryLabel.setText instead of countryLabel.setName. Another issue is that in the posted code countryLabel is not added to the frame. I assume it should go into labelpanel, but this part is commented out.
Some other observations:
Do not mix light weight and heavy weight components. See Mixing Heavyweight and Lightweight Components. Instead of ScrollPane use JScrollPane, for example:
JScrollPane listpanel = new JScrollPane(jlst);
Also there is no need to revalidate() the container when you set text on JLabel. The label will be refreshed as a result of setText() method.
For example, I am trying to call the setEnable method on a JButton that I constructed within the parameter parenthesis of an add method:
add(new JButton());
I know I could just do something like:
JButton button = new JButton();
button.setEnable(false);
but is there I way I can call setEnable on a JButton that I didn't assign a reference name to?
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using this for loop.
for (int i = 0; i < numberOfButtonsToAdd; i++)
{
JPanelName.add(new JButton());
}
and I want all the JButtons to be disabled.
You state in comment:
The reason why I am not assigning the JButton a reference name is because I am supposed to add an unknown number of JButtons to a JPanel. How I am doing this, is by using a for loop: for (int i = 0; i < numberOfButtonsToAdd; i++) { JPanelName.add(new JButton()); }
Then just use either an array or ArrayList of JButton.
// in your field declarations
List<JButton> buttonList = new ArrayList<JButton>();
// elsewhere in your program
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
buttonList.add(button);
somePanel.add(button);
}
Now you have a reference to any button in the list via buttonList.get(someIndex)
Note also, that most buttons are given ActionListeners that are activated whenever the button is pressed. Without such listeners, the buttons are pretty much useless. You can also get a reference to the pressed JButton from the ActionListener via the ActionEvent object passed into its actionPerformed method:
public void actionPerformed(ActionEvent e) {
AbstractButton myButton = (AbstractButton) e.getSource();
// now you can use myButton
}
Note that this is key information that you should have shared with us up front in your original question.
Edit
You state now:
and I want all the JButtons to be disabled.
Then just make them disabled from the get-go:
for (int i = 0; i < numberOfButtonsToAdd; i++) {
JButton button = new JButton();
button.setEnabled(false);
buttonList.add(button);
somePanel.add(button);
}
Although I am curious -- why all disabled? Why no ActionListener? No text?
Edit 2
You state:
Would I still be able to access those individual buttons later on, since they are all assigned "button"?
Please understand that the variable name is of little importance, and in fact, in my example above, the variable named button does not exist outside of the for loop within which it was declared. Instead what matters is the reference to the JButton object. As has been much discussed in the other answers and as you are aware, this can be obtained by using a variable, but it doesn't have to be a variable directly to the JButton, it could, as is in this case, be the variable to the ArrayList<JButton>. That's why I suggest that you create this entity.
Edit 3
for example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class ButtonLists extends JPanel {
private static final int ROWS = 6;
private static final int COLS = 6;
private List<JButton> allButtons = new ArrayList<JButton>();
private List<JButton> evenButtons = new ArrayList<JButton>();
public ButtonLists() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int buttonInt = i * COLS + j;
String buttonString = String.valueOf(buttonInt);
JButton button = new JButton(buttonString);
button.setEnabled(false);
gridPanel.add(button);
allButtons.add(button);
if (buttonInt % 2 == 0) {
evenButtons.add(button);
}
}
}
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Activate All") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Even") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(false);
}
for (JButton btn : evenButtons) {
btn.setEnabled(true);
}
}
}));
bottomPanel.add(new JButton(new AbstractAction("Activate Odd") {
#Override
public void actionPerformed(ActionEvent e) {
for (JButton btn : allButtons) {
btn.setEnabled(true);
}
for (JButton btn : evenButtons) {
btn.setEnabled(false);
}
}
}));
setLayout(new BorderLayout());
add(gridPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonLists");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonLists());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
If you added it to a panel you can get the components of that panel and looping through those components if one is a button you could call setEnabled(), but if there were more than one button you would have to determine if it was the correct one.
Edit:
Since you added that you want all the buttons disabled then this method should work nicely. Examples:
All:
for(Component c : panel.getComponents()){
c.setEnabled(false);
}
Just JButtons:
for(Component c : panel.getComponents()){
if(c instanceof JButton){
((JButton)c).setEnabled(false);
}
}
No, you can't. If setEnabled() returned the object it's enabling, you could enable-and-add the object in a single line. But as it is, setEnabled() returns void, so you have no choice but to use a local variable.
However, a JButton is enabled by default, so there's no need to explicitly call setEnabled() on it, it's already enabled!
You can call a method in a new instance like
new JButton().setEnabled(true);
But this won't allow you to access the JButton instance you create here anymore and thus you cannot call add().
This can only be possible if the method call returns the instance object on which it was called. So if for example setEnabled would return the same instance on which it was called (that is, this in setEnabled context) , you could do add(new JButton().setEnabled(true)).
Anyway in your case don't be afraid of using references:
final JButton button = new JButton();
button.setEnabled(true);
add(button);
Note that in this case 2 last methods can be called in any order, the result will be the same.
The only way this can work is if what ever you are adding it to has a get method. other than that you don't have any other options. Best way is what you showed.
JButton button = new JButton();
button.setEnable(true);
I'm very new to Java.
I've created two JLists in which you can add and remove 'shopping cart' items.
Once the user has added all their items they can click a submit button to view their selected items in a new window.
My first list is itemList (populated with items from array), the second list is shoppinglist which gets populated with whatever the user selects with a JButton.
Additional arrays are created to handle the actions of the buttons moving the items to and from the JLists. I've tried a few things, but haven't been successful in showing the items that get selected and shown in shopinglist to appear in a new window once submit is hit.
Any help is much appreciated.
//Create itemList
itemList = new JList(shopping);
contentPane.add(itemList);
itemList.setVisibleRowCount(10);
itemList.setFixedCellHeight(20);
itemList.setFixedCellWidth(140);
itemList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list1 = new JScrollPane(itemList);
//contentPane.add(list1);
//Create shoppingList
shoppingList = new JList(items);
contentPane.add(shoppingList);
shoppingList.setVisibleRowCount(10);
shoppingList.setFixedCellHeight(20);
shoppingList.setFixedCellWidth(140);
shoppingList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list2 = new JScrollPane(shoppingList);
JPanel buttonPanel = new JPanel();
//contentPane.add(list2);
Buttonin = new JButton(">>");
//Buttonin.setBounds(144, 46, 60, 23);
Buttonin.addActionListener(this);
buttonPanel.add(Buttonin);
ButtonOut = new JButton("<<");
//ButtonOut.setBounds(144, 80, 60, 23);
ButtonOut.addActionListener(this);
buttonPanel.add(ButtonOut);
JPanel submitPanel = new JPanel();
submitButton = new JButton("Submit");
submitPanel.add(submitButton);
submitButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent az) {
JFrame frame = new JFrame ("Go Shopping!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyPanel2());
frame.pack();
frame.setVisible(true);
}
});
contentPane.add(list1);
contentPane.add(buttonPanel);
contentPane.add(list2);
contentPane.setOpaque(true);
contentPane.add(submitPanel);
return contentPane;
}
public void actionPerformed(ActionEvent e)
{
int i = 0;
//When in buttonin is pressed index and value of selected item is output to array
if (e.getSource() == Buttonin)
{
int[] fromindex = itemList.getSelectedIndices();
Object[] from = itemList.getSelectedValues();
//add items to the shoppingList
for (i = 0; i < from.length; i++)
{
items.addElement(from[i]);
}
//Must remove items that are selected from the itemList
for (i = (fromindex.length-1); i >= 0; i--)
{
shopping.remove(fromindex[i]);
}
}
//When out button is pressed index and value of selected item is output to new array
else if (e.getSource() == ButtonOut)
{
Object[] to = shoppingList.getSelectedValues();
int [] toindex = shoppingList.getSelectedIndices();
//add items to previous list
for(i = 0; i < to.length; i++)
{
shopping.addElement(to[i]);
}
//Must remove what's deselected
for (i = (toindex.length-1); i >= 0; i--)
{
items.remove(toindex[i]);
}
}
Ok, bear with me (very very new to java) is this how I would set up the constructor to reference to ProfileFrame objects? And if so how do I change my main to reflect the new constructor?
public class GoShopping extends JPanel {
private JList shopList;
public GoShopping(ProfileFrame slist) {
//construct components
shopList = new JList(slist.getListModel());
shopList.setBounds(6, 6, 123, 166);//don't worry I'm changing the layout
add(shopList);
}
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//I need new GoShopping to reflect the new constructor, but not sure how to make it work
frame.getContentPane().add (new GoShopping());
frame.pack();
frame.setVisible (true);
}
}
You're creating a new ProfileFrame object in your MyPanel2 constructor, and since this is not the same instance as the visualized ProfileFrame object, then its JList's model will be null. A bad solution is to use static variables -- just don't do this please. A better solution is to pass a reference to the true visualized ProfileFrame object into your MyPanel2 constructor and call the public methods off of this instance.
And again, don't use null layout and setBounds(...), but instead use the layout managers unless you like making things more difficult than they need to be.