JCheckBox' value resets / doesn't change - java

I have several components, all inheriting JCheckBox without overwriting anything from it, stored in a vector, which is then traversed and each of the components is added to a dialog
CreateLists(); // initialises the checkbox vector
for(int i = 0; i < checkBoxes.size() ; i++){
myPanel.add(checkBoxes.elementAt(i));
}
Some of these checkboxes are already selected.
My problem now is: When I open the dialog and select or unselect any checkbox, the value of the checkboxes in the vector doesn't change. Selected stays selected and unselected stays unselected.
I also tryed to get the new values by using JPanels getCompoents(), but the values of these are wrong, too.
An ItemListener in the checkbox inheritors confirmes that the changes do happen, but whenever I try to get the new values, there just the same as those with which the checkboxes were initialised.
Here is a console output I used to keep track of the changes:
create lists
print values:
checkBox1 = true
checkBox2 = true
checkBox3 = false
checkBox2 clicked new value = false
checkBox3 clicked new value = true
print values:
checkBox1 = true
checkBox2 = true
checkBox3 = false

Here is some more code and information:
CreateList() compares a watchlist with the watchable things, creates the checkboxes accordingly (true = watched etc) and adds them to the new initalised vector.
To read the values i use this:
Component[] components = pnlGesamt.getComponents();
for(int i = 0; i < components.length; i++){
if(components[i] instanceof WLElementCheckBox){
WLElementCheckBox cb = (WLElementCheckBox) components[i];
System.out.println(cb.WlElement().Name() + " = " + cb.isSelected());
}
}
The JCheckBox inheritor:
private WatchListElement wlElement;
public WLElementCheckBox (WatchListElement wl, boolean selected)
{
super();
WlElement(wl);
setSelected(selected);
setText(wlElement.Name());
addItemListener(new MIL());
}
public WatchListElement WlElement ()
{
return wlElement;
}
public void WlElement (WatchListElement wlElement)
{
this.wlElement = wlElement;
}
public class MIL implements ItemListener{
public void itemStateChanged(ItemEvent arg0) {
System.out.println("Ckb " + wlElement.Name() +" geklickt Item neu = " + isSelected());
}
}

There is a small possibility that the changes to your checkboxes are not visible because you're querying them from another thread (such as main) instead of the Event Dispatch Thread (EDT). Swing is not thread-safe. When you check the checkboxes, the values are set on the EDT, but other threads might have the old state saved in memory and don't check to see if it's been updated. So, the first thing you need to do is ensure that when you're checking the states of your checkboxes, you're doing it from the EDT, using a call to SwingUtilities.invokeAndWait() or SwingUtilities.invokeLater().
For more information on why this happens, search for Thread Safety in Java.
(Also, don't be tempted to use synchronization to solve the problem or you might end up with a deadlock in your GUI).
One final pro tip: using new Java for-loop syntax makes code easier to read and write, as well as more efficient in some cases. Your code...
for(int i = 0; i < checkBoxes.size() ; i++){
myPanel.add(checkBoxes.elementAt(i));
}
... can turn into...
for(JCheckBox c : checkBoxes) {
myPanel.add(c);
}
This works on arrays and anything that is Iterable (which includes Collection).

Related

How can you make a case inside a button action performed, based off if another jbutton is chosen in java swing?

I have these two methods:
private void bcsButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
DefaultListModel model = new DefaultListModel<>();
for (Subject s : cCores) {
coreSubjectsList.setModel(model);
model.addElement(bcs.displayCores(s));
}
record1 = new Record(bcs.getCourseName());
ArrayList cores = new ArrayList<>(Arrays.asList(cCores));
record1.enrolCores(cores);
DefaultListModel model2 = new DefaultListModel<>();
for (Major m : BCSMajors) {
majorsList.setModel(model2);
model2.addElement(bcs.displayMajors(m));
}
DefaultListModel model3 = new DefaultListModel<>();
for (Subject s : cEles) {
this.electivesList.setModel(model3);
model3.addElement(bcs.displayElectives(s));
}
}
private void enrolButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String text = this.studNumberField.getText();
int studentNumber = Integer.parseInt(text);
String selection = group.getSelection().getActionCommand();
Student stud1 = new UnderGraduate(this.studentNameTextField.getText(), studentNumber, selection, this.dobField.getText(), "");
if (stud1 instanceof UnderGraduate) {
((UnderGraduate) stud1).writeFileUnderGrad();
record1.setStatus(Record.Status.ACTIVE);
record1.writeRecordFile();
}
}
For the enrol button, I want to make a case that if the bcsButton is chosen, and I click enrol, it will execute what is inside the enrol method. Because later on I want to make another button called mcsButton, and make two cases, that if mcsButton is chosen it will perform "the enrol code for mcs", and if bcsButton is chosen, it will perform "the enrol code for bcs". Is there any particular way I can do this? Thank you.I've tried using something like:
if(evt.getSource() == bcsButton){
//put my code here
}
It doesn't run anything though.
and make two cases, that if mcsButton is chosen it will perform "the enrol code for mcs", and if bcsButton is chosen, it will perform "the enrol code for bcs".
You would generally use a JRadioButton for this. The user can only select one of two buttons that has been added to the ButtonGroup.
Then in your "Enroll" button you check to see which button has been selected and execute the appropriate logic. The ActionListener code would be something like:
if (mcsButton.isSelected())
processMCSEnrol();
else if (bcsButton.isSelected())
processBCSEnrol();
Read the section from the Swing tutorial on How to Use Radio Buttons for more information and working examples.
Edit:
You need a variable lets say, mcsSelected.
In the ActionListener for the "mcsButton" you add:
mcsSelected = true;
In the ActionListener for the "bcsButton" you add:
mcsSelected = false;
In the "Enrol" ActionListener you add:
if (mcsSeleced)
processMCS();
else
processBCS();

How to code if a checkbox is unchecked in java

Currently, I'm developing a Restaurant management system in java. when I check a checkbox it will add money to the total amount, all I want to know that if I uncheck that checked checkbox again then it will subtract that added amount again. following is my checkbox code
private void jcbWPizzaMouseClicked(java.awt.event.MouseEvent evt) {
double cMeal = Double.parseDouble(jlblCostOfMeal.getText());
double WavePizza = Double.parseDouble(jtxtWP.getText());
double iWavePizza = 350;
if (jcbWPizza.isSelected()) {
i[1] = (WavePizza * iWavePizza) + cMeal;
String pMeal = String.format("%.2f", i[1]);
jlblCostOfMeal.setText(pMeal);
}
}
if you are using JCheckBox there is a method boolean isSelected() so to verify whether the JCheckBox is selected you can try :
if (checkbox.isSelected()) {
// selected, do something...
} else {
// un-selected, do something else...
}
You want to change the value of total amount based on the object jcbWPizza's selected stated. you can add ItemListener to the checkbox
jcbWPizza.addItemListener(new ItemListener() {
#Override public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
//checkbox has been selected //do selected action...
} else {
//checkbox has been deselected //do deselected action...
};
}
})
Your question raises a number of issues that you might not have thought about.
Firstly, by relying on a MouseEvent, you will not capture those times when the checkbox changes state due to some other reason (for example, by code, or if the user uses the keyboard to change selection). Adding an ItemListener would be a more generation approach.
In the future, there might be a number of other things that affect the price. Having the code that updates the price hidden in this checkbox listener seems like the wrong approach. What would be better is to add a listener that just calls a general "update the displayed price" method. Within that method, you could then check the state of each of the widgets that will affect the final price and calculate accordingly. It then doesn't matter if the checkbox is or was hidden or not, as each time it is asked to update, it will calculate the total from scratch.
Finally, bear in mind that Swing is not thread-safe. Whilst a single Thread will call your listeners, there is no guarantee that only a single Thread will be calling your "recalculate the price" method. Ensure that if more than one Thread should call your code at the same time, you don't end up getting your state out of sync. Avoiding a "the checkbox has been toggled, so add or subtract" logic is a good idea once again, as it adds additional state that needs to be kept in sync.

Java - synchronizing two scrollbars via a checkbox

this code below creates a checkbox which I want to turn synchronized scrolling on my two panels on/off. Initially when the program runs the scrollbars are independent. When the checkbox is checked and the "if" statement is reached, scroller2's scrollbar is set to the model of scroller1's scrollbar and they are connected, i.e. they move together.
However the problem is when the checkbox is unchecked, meaning I want the scrollbars to be independent again. Nothing I put in the else statement seems to work.
JCheckBox check = new JCheckBox("Global");
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
boolean selected = abstractButton.getModel().isSelected();
System.out.println(selected);
if (selected){
scroller2.getHorizontalScrollBar().setModel(scroller.getHorizontalScrollBar().getModel());
} else {
scroller = new JScrollPane(plotPanel);
scroller2 = new JScrollPane(plotPanel2);
}
}
};
check.addActionListener(actionListener);
This:
scroller = new JScrollPane(plotPanel);
scroller2 = new JScrollPane(plotPanel2);
creates two new JScrollPanes but you do nothing with them. Understand that changing the object a variable refers to, here the scroller and scroller2 vairables will have no effect on the object that is displayed, and this issue gets to the core distinction of the difference between a reference variable and a reference or object. If you wanted to change the displayed JScrollPane you'd have to remove the old one, and add the new one to the GUI.
But you don't want to do this. Simply give one of the horizontal JScrollBars a new model, specifically a new DefaultBoundedRangeModel. I would use the constructor that takes 4 ints, and would scrape the value, extent, min, max parameters from the current model.
e.g., something like:
else {
JScrollBar horizBar = scroller2.getHorizontalScrollBar();
DefaultBoundedRangeModel currentModel = (DefaultBoundedRangeModel) horizBar.getModel();
int extent = currentModel.getExtent();
int min = currentModel.getMin();
int max = currentModel.getMax();
int value = currentModel.getValue();
DefaultBoundedRangeModel newModel = new DefaultBoundedRangeModel(value, extent, min, max);
horizBar.setModel(newModel);
}
Note code not tested

JPanel not visible

I've been having a problem with my program that has been driving me crazy and I cannot understand why this is happening. I have a GUI that when the "Add" button is pressed, a new system listing appears (Which is a class called SystemPanel that extends JPanel and cotains system details, which is created and then put into the Frame's main panel.)
To put it shortly, when I try to add a new SystemPanel, it does not appear for whatever reason. I have code using JSch that connects to the system and verifies whether its processes are online or not, but the line of code that does this is after the creation of the SystemPanel. It is only after the code for testing the processes of the system are executed that the SystemPanel becomes visible, and I can't understand why this is the case. Here is the code for adding a new SystemPanel:
public void actionPerformed(ActionEvent e) {
//If the "Add" button is pressed
if (e.getActionCommand() == "Add") {
PopupWindow popup = new PopupWindow(this);
popup.setVisible(true);
String[] results = popup.getResults();
if (results[0] != null && results[1] != null && results[2] != null && results[3] != null && results[4] != null) {
SystemPanel newSystem = new SystemPanel(this, results[0], results[1], results[2], results[3], results[4]);
systemsPanel.add(newSystem);
revalidate();
systemsList.add(newSystem);
System.out.println("Did the stuff");
boolean[] status = SystemChecker.checkOnline(results[0], results[1], results[2], results[3]);
}
}
}
The PopupWindow is a custom JDialog that allows the user to enter the required information which is returned in a String array and is used to create a new SystemPanel. The checkOnline function grabs the user's inputs and uses them to connect to the system and determine whether the processes are working or not, and returns the results into a boolean array, true for working, false for not.
What's even weirder is that I have another part of my program that reads from an .ini file to obtain existing systems and then creates SystemPanels based on the data that it reads. Through this method, the SystemPanels are added the way I want and work perfectly for some reason, even though the code for adding the panels is hardly any different. Code:
for (int i = 0; i < systems.size(); i++) {
SystemPanel newSystem = new SystemPanel(this, systems.get(i)[0], systems.get(i)[1], systems.get(i)[2], systems.get(i)[3], systems.get(i)[4]);
systemsPanel.add(newSystem);
revalidate();
systemsList.add(newSystem);
}
for (int i = 0; i < lineNum; i++) {
boolean[] status = SystemChecker.checkOnline(systems.get(i)[0], systems.get(i)[1], systems.get(i)[2], systems.get(i)[3]);
systemsList.get(i).updateIcons(status);
}
This code grabs the details from the file and then makes the SystemPanels based on those details. Here, all of the SystemPanels are added and show up before the connection is tested, which is what I want to happen when I add one normally.
Why is it that the SystemPanel doesn't appear until the connection is tested, even though the code for displaying the SystemPanel is executed before the connection test? Any help would be greatly appreciated, thanks.
Try it of the current event queue handling, on which actionPerformed is done.
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(() -> { ... your code here ... });
}
Also you cannot add the same component to two parents, every component object has a single parent (container).
(Java 8 notation)

Setting Unselected Items in a JList table to setEnable(false)

I'm having difficulty changing unselected options in a JList table to set them to setEnable(false). The method that is receiving the values is an ActionListener button method that, once pressed, receives the selected values from the JList. Here is the method and the buildEnemySelectionPanel() method is creating the JList with the appropriate JPanel for later placement:
private String[] enemies = {"Goblin", "Skeleton"};
private void buildEnemySelectionPanel()
{
enemyPanel = new JPanel();
enemyListPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
enemyListPanel.setPreferredSize(new Dimension(180, 85));
enemyListPanel.setBackground(Color.WHITE);
enemyPanel.setLayout(new BoxLayout(enemyPanel, BoxLayout.Y_AXIS));
enemyList = new JList(enemies);
enemyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
enemyList.addListSelectionListener(new EnemyListListener());
enemyListPanel.add(enemyList);
enemyPanel.add(enemyListPanel);
}
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("Select Enemy"))
{
indexEnemy = enemyList.getSelectedIndex();
indexEnemyWeapon = weaponList.getSelectedIndex();
/*
here is where I'm having problems
*/
}
}
So far I've tried to take all of the items from the JList and, matching them with the references from the original String[] list items that I sent to the JList, parsed the indexes and if they didn't match set to false. Unfortunately as you are all probably well aware, compilation errors came up as result due to the fact that the JList is not actually a list. Here is a sample of my for loop that I tried to use in my method above:
for(int x = 1; x < enemyList.length(); x++)
{
if (!(enemies[x] == indexEnemy))
{
enemyList[x].setEnable(false);
}
}
I've read the http://docs.oracle.com/javase/8/docs/api/ , (tried to link 'setEnable') among some examples but don't seem to be making the connection.
Ideally, what I wish to happen is that when the ActionEvent of my button is triggered, all non-selected options in my JList will be disabled. I understand that the end-user will still be able to change his/her mind and make a different selection. But I'd like to still receive some help on how I can set the non-selected items in my JList to false if they are not the indexEnemy from my method above.

Categories