cancel JComboBox actionEvent - java

I'm writing a gui program and have an AbstractAction for a Jbutton that opens a file. In a JComboBox I have a list of the files that have been opened. The AbstractAction for the JComboBox will change back to any of the files that have been opened. When I update the list for a JComboBox though the action fires.
So when I actually open a file the JComboBox action fires, and when I use the JComboBox the action fires once, then a second time when updating.
Is there a way i can stop the event when just updating the JComboBox list?
Thanks in advance

The answer is in the design, particularly in separation of concers: don't think view-with-two-actions, instead think many-views-change-state-of-single-data.
In pseudo-code something like:
// data class
public class MyOpenFilesBean {
private File currentFile;
public void setCurrentFile(File current) {
File old = getCurrentFile();
this.currentFile = current;
firePropertyChange("currentFile", old, getCurrentFile());
}
public File getCurrentFile() {
return currentFile;
}
}
// view wiring (view --> data)
Action open = new AbstractAction(...) {
public void actionPerformed(...) {
File choosenFile = // grab it from whereever in the view
myOpenFileBean.setCurrentFile(choosenFile);
}
};
myButton.setAction(open);
myComboBox.setAction(open);
// view wiring (data --> view)
PropertyChangeListener l = new PropertyChangeListener() {
public void propertyChanged(...) {
if ("currentFile".equals(evt.getPropertyName()) {
// a method implemented to update f.i. the combo selection
updateView((File) evt.getNewValue());
}
}
};
myOpenFileBean.addPropertyChangeListener(l);

Related

Edit the value of a JComboBox entry without triggering a selection change [duplicate]

I need your suggestions and guidence on following task.
I have a frame which has two JComboBoxes supposed they are named combo1 and combo2, a JTable and other components.
At initial stage when frame is visible with above component. The combo1 combobox is filled with some values but no value is selected at initial stage, the combo2 combobox is disabled and the table is empty.
I have added an actionListener on combo1 as well as combo2. There are two types of values in combo1 suppose those values are type1 and type2.
Condition 1:
When we selects value type1 from Combo1 the actionListener method is called of combo1 which invokes a method which combo2 remains disabled and adds some rows to table related to selected value type1 from combo1.
Condition 2:
when we selects value type2 from combo1 the actionListener method is called of combo1 which invokes a method who makes combo2 filled with some values related to type2 and gets enabled but no value is selected from combo2 and table also should remain empty until we selects any value from combo2.
table at every addition of value to combo2 the action listener method of combo2 is gets fired. In actionListener method of combo2 which gets combo2 selected value but here there is no selected value of combo2 which leads to a NullPointerException.
So what should I do that the action listner method of combo2 will not be get executed after addition of an values to combo2.
You could remove the action listener before you add the new elements, and add it back once you're done . Swing is single threaded so there is no need to worry about other threads needing to fire the listener.
Your listener could probably also check if something is selected and take appropriate action if not. Better than getting a NPE.
What i do instead of adding and removing action listeners i have a boolean variable in my action listeners that is true if it has to allow the action through or false if it has to block it.
I then set it to false when i do some changes that will fire off the action listener
JComboBox test = new JComboBox();
test.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(testActionListenerActive)
{
//runn your stuff here
}
}
});
//then when i want to update something where i want to ignore all action evetns:
testActionListenerActive = false;
//do stuff here like add
SwingUtilities.invokeLater(() -> testActionListenerActive = false);
//and now it is back enabled again
//The reason behind the invoke later is so that if any event was popped onto the awt queue
//it will not be processed and only events that where inserted after the enable
//event will get processed.
try this:
indicatorComboBox = new JComboBox() {
/**
* Do not fire if set by program.
*/
protected void fireActionEvent() {
// if the mouse made the selection -> the comboBox has focus
if(this.hasFocus())
super.fireActionEvent();
}
};
although its late, a better alternative would be to disabled the combobox to be modified prior to being modified. by doing so, you prevent firing events of the modified combobox, when for example, you use methods likes removeAllItems() or addItem()
String orderByOptions[] = {"smallest","highest","longest"};
JComboBox<String> jcomboBox_orderByOption1 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption2 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption3 = new JComboBox<String(orderByOptions);
jcomboBox_orderByOption1.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem = jcomboBox_orderByOption1.getSelectedItem();
jcomboBox_orderByOption2.setEnabled(false);
jcomboBox_orderByOption2.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem))
{
jcomboBox_orderByOption2.addItem(item);
}
}
jcomboBox_orderByOption2.setEnabled(true);
}
}
});
jcomboBox_orderByOption2.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem1 = jcomboBox_orderByOption1.getSelectedItem();
Object selectedItem2 = jcomboBox_orderByOption2.getSelectedItem();
jcomboBox_orderByOption3.setEnabled(false);
jcomboBox_orderByOption3.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem1) && !item.equals(selectedItem2))
{
jcomboBox_orderByOption3.addItem(item);
}
}
jcomboBox_orderByOption3.setEnabled(true);
}
}
});
The cleaner way is to use lambda expressions like this:
do(comboBox, () -> comboBox.setSelectedItem("Item Name"));
For the above to work, you need the following method defined somewhere:
public static void do(final JComboBox<String> component, final Runnable f) {
final ActionListener[] actionListeners = component.getActionListeners();
for (final ActionListener listener : actionListeners)
component.removeActionListener(listener);
try {
f.run();
} finally {
for (final ActionListener listener : actionListeners)
component.addActionListener(listener);
}
}
This works:
/** Implements a Combo Box with special setters to set selected item or
* index without firing action listener. */
public class MyComboBox extends JComboBox {
/** Constructs a ComboBox for the given array of items. */
public MyComboBox(String[] items) {
super(items);
}
/** Flag indicating that item was set by program. */
private boolean isSetByProgram;
/** Do not fire if set by program. */
protected void fireActionEvent() {
if (isSetByProgram)
return;
super.fireActionEvent();
}
/** Sets selected Object item without firing Action Event. */
public void setSelection(Object item) {
isSetByProgram = true;
setSelectedItem(item);
isSetByProgram = false;
}
/** Sets selected index without firing Action Event. */
public void setSelection(int index) {
isSetByProgram = true;
setSelectedIndex(index);
isSetByProgram = false;
}
}
Note: You can't just override setSelectedItem(...) or setSelectedIndex(...) because these are also used internally when items are actually selected by user keyboard or mouse actions, when you do not want to inhibit firing the listeners.
To determine whether or not to perform various methods in actionListener interface methods (actionPerformed() blocks of code) use setActionCommand() on source components (combo1 or combo2).
For your example, before adding elements to combo2, call setActionCommand("doNothing") and guard your comboBoxActionPerformed() method.
Here's a compilable example that uses this principle to have one combo set another combo's selected index while also displaying a String in a JTextField. By using setActionCommand() and guarding the comboActionPerformed() block of code, the JTextField will cycle through each word in the wordBank. If the comboActionPerformed() method was not guarded or if the actionCommand String was not changed, 2 actionEvents will trigger and the textField will skip words.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
/** #author PianoKiddo */
public class CoolCombos extends JPanel {
JComboBox<String> candyCombo;
JComboBox<String> flavorCombo;
JTextField field;
String[] wordBank;
int i = 0;
CoolCombos() {
super();
initComponents();
addComponentsToPanel();
}
private void initComponents() {
initCombos();
initTextField();
}
private void initCombos() {
ActionListener comboListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
comboActionPerformed(e);
}
};
String[] candyList = {"Sourpatch", "Skittles"};
String[] flavorList = {"Watermelon", "Original"};
candyCombo = new JComboBox<>(candyList);
candyCombo.addActionListener(comboListener);
flavorCombo = new JComboBox<>(flavorList);
flavorCombo.addActionListener(comboListener);
}
private void initTextField() {
wordBank = new String[]{"Which", "Do", "You", "Like", "Better?"};
field = new JTextField("xxxxx");
field.setEditable(false);
field.setText(wordBank[i]);
}
private void addComponentsToPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(candyCombo);
this.add(flavorCombo);
this.add(field);
}
public void comboActionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (!command.equals("doNothing")) {
JComboBox combo = (JComboBox) e.getSource();
if (combo.equals(candyCombo)) {
setOtherComboIndex(candyCombo, flavorCombo); }
else {
setOtherComboIndex(flavorCombo, candyCombo); }
displayText(); //replace here for toDo() code
}
}
private void setOtherComboIndex(JComboBox combo, JComboBox otherCombo) {
String command = otherCombo.getActionCommand();
otherCombo.setActionCommand("doNothing"); //comment this line to skip words.
otherCombo.setSelectedIndex(combo.getSelectedIndex());
otherCombo.setActionCommand(command);
}
private void displayText() {
i++;
String word;
if (i > 4) { i = 0; }
word = wordBank[i];
field.setText(word);
this.repaint();
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CoolCombos");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new CoolCombos();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setMinimumSize(frame.getSize());
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I kind of went the stupid simple route with this issue for my program since I am new to programming.
I changed the action listeners to have a counter if statement:
if(stopActionlistenersFromFiringOnLoad != 0){//action performed ;}
Then at the end of the java program creation, I added 1 to the counter:
topActionlistenersFromFiringOnLoad += 1;
To avoid that addItem method fire events is better to use an DefaultComboBoxModel in the JComboBox to add data. Also, if you invoke a model.addElement(), an event is fired, so, you can add all the elements to the model and later use JComboBox.setModel(model). In this way, if you add elements to the model, events are not fired because you have not link the JComboBox with the model. Then, I show you an example.
private void rellenarArrendatarioComboBox(ArrayList<Arrendatario> arrendatarios) {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(new Arrendatario(" -- Seleccione un arrendatario --"));
for (Arrendatario arrendatario : arrendatarios) {
model.addElement(arrendatario);
}
ArrendatarioComboBox.setModel(model);
}
First, we create the model, add all elements to the model (events are not fired because you have not link the JComboBox with the model), we link the model with the JComboBox using ArrendatarioComboBox.setModel(model). After linking, events are fired.

SetSelectedItem JCombobox without performing action [duplicate]

I need your suggestions and guidence on following task.
I have a frame which has two JComboBoxes supposed they are named combo1 and combo2, a JTable and other components.
At initial stage when frame is visible with above component. The combo1 combobox is filled with some values but no value is selected at initial stage, the combo2 combobox is disabled and the table is empty.
I have added an actionListener on combo1 as well as combo2. There are two types of values in combo1 suppose those values are type1 and type2.
Condition 1:
When we selects value type1 from Combo1 the actionListener method is called of combo1 which invokes a method which combo2 remains disabled and adds some rows to table related to selected value type1 from combo1.
Condition 2:
when we selects value type2 from combo1 the actionListener method is called of combo1 which invokes a method who makes combo2 filled with some values related to type2 and gets enabled but no value is selected from combo2 and table also should remain empty until we selects any value from combo2.
table at every addition of value to combo2 the action listener method of combo2 is gets fired. In actionListener method of combo2 which gets combo2 selected value but here there is no selected value of combo2 which leads to a NullPointerException.
So what should I do that the action listner method of combo2 will not be get executed after addition of an values to combo2.
You could remove the action listener before you add the new elements, and add it back once you're done . Swing is single threaded so there is no need to worry about other threads needing to fire the listener.
Your listener could probably also check if something is selected and take appropriate action if not. Better than getting a NPE.
What i do instead of adding and removing action listeners i have a boolean variable in my action listeners that is true if it has to allow the action through or false if it has to block it.
I then set it to false when i do some changes that will fire off the action listener
JComboBox test = new JComboBox();
test.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(testActionListenerActive)
{
//runn your stuff here
}
}
});
//then when i want to update something where i want to ignore all action evetns:
testActionListenerActive = false;
//do stuff here like add
SwingUtilities.invokeLater(() -> testActionListenerActive = false);
//and now it is back enabled again
//The reason behind the invoke later is so that if any event was popped onto the awt queue
//it will not be processed and only events that where inserted after the enable
//event will get processed.
try this:
indicatorComboBox = new JComboBox() {
/**
* Do not fire if set by program.
*/
protected void fireActionEvent() {
// if the mouse made the selection -> the comboBox has focus
if(this.hasFocus())
super.fireActionEvent();
}
};
although its late, a better alternative would be to disabled the combobox to be modified prior to being modified. by doing so, you prevent firing events of the modified combobox, when for example, you use methods likes removeAllItems() or addItem()
String orderByOptions[] = {"smallest","highest","longest"};
JComboBox<String> jcomboBox_orderByOption1 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption2 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption3 = new JComboBox<String(orderByOptions);
jcomboBox_orderByOption1.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem = jcomboBox_orderByOption1.getSelectedItem();
jcomboBox_orderByOption2.setEnabled(false);
jcomboBox_orderByOption2.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem))
{
jcomboBox_orderByOption2.addItem(item);
}
}
jcomboBox_orderByOption2.setEnabled(true);
}
}
});
jcomboBox_orderByOption2.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem1 = jcomboBox_orderByOption1.getSelectedItem();
Object selectedItem2 = jcomboBox_orderByOption2.getSelectedItem();
jcomboBox_orderByOption3.setEnabled(false);
jcomboBox_orderByOption3.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem1) && !item.equals(selectedItem2))
{
jcomboBox_orderByOption3.addItem(item);
}
}
jcomboBox_orderByOption3.setEnabled(true);
}
}
});
The cleaner way is to use lambda expressions like this:
do(comboBox, () -> comboBox.setSelectedItem("Item Name"));
For the above to work, you need the following method defined somewhere:
public static void do(final JComboBox<String> component, final Runnable f) {
final ActionListener[] actionListeners = component.getActionListeners();
for (final ActionListener listener : actionListeners)
component.removeActionListener(listener);
try {
f.run();
} finally {
for (final ActionListener listener : actionListeners)
component.addActionListener(listener);
}
}
This works:
/** Implements a Combo Box with special setters to set selected item or
* index without firing action listener. */
public class MyComboBox extends JComboBox {
/** Constructs a ComboBox for the given array of items. */
public MyComboBox(String[] items) {
super(items);
}
/** Flag indicating that item was set by program. */
private boolean isSetByProgram;
/** Do not fire if set by program. */
protected void fireActionEvent() {
if (isSetByProgram)
return;
super.fireActionEvent();
}
/** Sets selected Object item without firing Action Event. */
public void setSelection(Object item) {
isSetByProgram = true;
setSelectedItem(item);
isSetByProgram = false;
}
/** Sets selected index without firing Action Event. */
public void setSelection(int index) {
isSetByProgram = true;
setSelectedIndex(index);
isSetByProgram = false;
}
}
Note: You can't just override setSelectedItem(...) or setSelectedIndex(...) because these are also used internally when items are actually selected by user keyboard or mouse actions, when you do not want to inhibit firing the listeners.
To determine whether or not to perform various methods in actionListener interface methods (actionPerformed() blocks of code) use setActionCommand() on source components (combo1 or combo2).
For your example, before adding elements to combo2, call setActionCommand("doNothing") and guard your comboBoxActionPerformed() method.
Here's a compilable example that uses this principle to have one combo set another combo's selected index while also displaying a String in a JTextField. By using setActionCommand() and guarding the comboActionPerformed() block of code, the JTextField will cycle through each word in the wordBank. If the comboActionPerformed() method was not guarded or if the actionCommand String was not changed, 2 actionEvents will trigger and the textField will skip words.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
/** #author PianoKiddo */
public class CoolCombos extends JPanel {
JComboBox<String> candyCombo;
JComboBox<String> flavorCombo;
JTextField field;
String[] wordBank;
int i = 0;
CoolCombos() {
super();
initComponents();
addComponentsToPanel();
}
private void initComponents() {
initCombos();
initTextField();
}
private void initCombos() {
ActionListener comboListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
comboActionPerformed(e);
}
};
String[] candyList = {"Sourpatch", "Skittles"};
String[] flavorList = {"Watermelon", "Original"};
candyCombo = new JComboBox<>(candyList);
candyCombo.addActionListener(comboListener);
flavorCombo = new JComboBox<>(flavorList);
flavorCombo.addActionListener(comboListener);
}
private void initTextField() {
wordBank = new String[]{"Which", "Do", "You", "Like", "Better?"};
field = new JTextField("xxxxx");
field.setEditable(false);
field.setText(wordBank[i]);
}
private void addComponentsToPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(candyCombo);
this.add(flavorCombo);
this.add(field);
}
public void comboActionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (!command.equals("doNothing")) {
JComboBox combo = (JComboBox) e.getSource();
if (combo.equals(candyCombo)) {
setOtherComboIndex(candyCombo, flavorCombo); }
else {
setOtherComboIndex(flavorCombo, candyCombo); }
displayText(); //replace here for toDo() code
}
}
private void setOtherComboIndex(JComboBox combo, JComboBox otherCombo) {
String command = otherCombo.getActionCommand();
otherCombo.setActionCommand("doNothing"); //comment this line to skip words.
otherCombo.setSelectedIndex(combo.getSelectedIndex());
otherCombo.setActionCommand(command);
}
private void displayText() {
i++;
String word;
if (i > 4) { i = 0; }
word = wordBank[i];
field.setText(word);
this.repaint();
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CoolCombos");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new CoolCombos();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setMinimumSize(frame.getSize());
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I kind of went the stupid simple route with this issue for my program since I am new to programming.
I changed the action listeners to have a counter if statement:
if(stopActionlistenersFromFiringOnLoad != 0){//action performed ;}
Then at the end of the java program creation, I added 1 to the counter:
topActionlistenersFromFiringOnLoad += 1;
To avoid that addItem method fire events is better to use an DefaultComboBoxModel in the JComboBox to add data. Also, if you invoke a model.addElement(), an event is fired, so, you can add all the elements to the model and later use JComboBox.setModel(model). In this way, if you add elements to the model, events are not fired because you have not link the JComboBox with the model. Then, I show you an example.
private void rellenarArrendatarioComboBox(ArrayList<Arrendatario> arrendatarios) {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(new Arrendatario(" -- Seleccione un arrendatario --"));
for (Arrendatario arrendatario : arrendatarios) {
model.addElement(arrendatario);
}
ArrendatarioComboBox.setModel(model);
}
First, we create the model, add all elements to the model (events are not fired because you have not link the JComboBox with the model), we link the model with the JComboBox using ArrendatarioComboBox.setModel(model). After linking, events are fired.

Event handling in Java (JTree + JButton)

private void createEvents()
{
menuFileExit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
System.exit(0);
}
});
////// Events on tree selection
jtStoryViewer.addTreeSelectionListener(new TreeSelectionListener()
{
public void valueChanged(TreeSelectionEvent arg0)
{
DefaultMutableTreeNode selection = (DefaultMutableTreeNode) jtStoryViewer.getLastSelectedPathComponent();
Object nodeObject = selection.getUserObject();
////// Checks if selected node is a String (only story title is a string)
if(selection.getUserObject().getClass().getName() == "java.lang.String" )
{
tfTitle.setText(nodeObject.toString());
////// Action listener for Change Button
btnChange.addActionListener(new ActionListener()
{
////// Title text swap
public void actionPerformed(ActionEvent arg0)
{
selection.setUserObject(tfTitle.getText());
((DefaultTreeModel)jtStoryViewer.getModel()).nodeChanged(selection);
}
});
}
///// checks if the object is a chapter object
if(selection.getUserObject().getClass().getName() == "ISW.common.Chapter")
{
Chapter chapter = (Chapter) selection.getUserObject();
tfTitle.setText(chapter.toString());
////// Action listener for Change Button
btnChange.addActionListener(new ActionListener()
{
////// Title text swap
public void actionPerformed(ActionEvent arg0)
{
chapter.setTitle(tfTitle.getText());
((DefaultTreeModel)jtStoryViewer.getModel()).nodeChanged(selection);
}
});
}
}
});
}
I am using JTree to display and modify some objects. I added a TreeSelectionListener to get the object data on selection. For now I want to be able to change the title of an object, it works fine on first selection on the tree , I change the value in the text box and the "Change" button works just fine, but when I move on to next objects, the change button also modifies the value of all previously selected objects.
I guess it is caused due to my improper usage of the ActionListeners but I can't tell for sure and at this point I'm stuck.
Will be grateful for any hints.
Don't keep adding an ActionListener to the btnChange JButton within the TreeSelectionListener#valueChanged method.
This will cause the button to call EVERY ActionListener you have previously
Instead, give the btnChange a single ActionListener, when clicked, can act on the currently selected node (by checking the JTree it self). You could have the TreeSelectionListener#valueChanged method enable or disable the btnChange based on the validity of the selection
Also, if(selection.getUserObject().getClass().getName() == "ISW.common.Chapter") isn't how String comparison is done in Java, instead you should use something more like if("ISW.common.Chapter".equals(selection.getUserObject().getClass().getName()))

How to remove object (including components) from arraylist?

I'm working on a task planning app. I have a 'new task' button to add a task. When clicked, this button makes a new instance of the TaskRowToDo class and adds this to the toDoList arraylist. This class contains a row with a text field and some buttons.
This is the 'new task' button code:
private void drawNewBtn(){
JButton btnNew = new JButton("Nieuwe taak");
btnNew.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("New task added");
toDoList.add(new TaskRowToDo(toDoIndex+7, false, "new task", 2));
toDoList.get(toDoIndex).draw();
toDoIndex++;
frmPlanner.revalidate();
}
});
frmPlanner.getContentPane().add(btnNew, "cell 3 12");
}
At the end of the TaskRowToDo there is a 'remove' button. This button should remove the row from the toDoList and remove this row from the screen.
Below is the 'remove' button code:
btnRemoveToDo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("To Do removed");
toDoIndex--;
toDoList.remove(toDoIndex);
frmPlanner.revalidate();
}
});
The button removes the instance of TaskRowToDo from the toDoList, but it still shows up on screen and the components even work. So it's not really removed. I've tried using revalidate() and repaint() but to no avail. As a test I tried frmPlanner.removeAll() and even this doesn't clear the screen (however the components won't work anymore).
How do I remove this one row, including its components and clear this space on the screen?
toDoList is JList?
give same more code, on this time I suggest to setModel on JList.
I always prepare method setModel when I create JList and it works:
private void setModelForJList() {
toDoList.setModel(new ListModel<TaskRowToDo>() {
#Override
public int getSize() {
return toDoListEntityList.size();
}
#Override
public TaskRowToDogetElementAt(int index) {
return toDoListEntityList.get(index);
}
#Override
public void removeListDataListener(ListDataListener l) {
}
#Override
public void addListDataListener(ListDataListener l) {
}
});
toDoList.repaint();
}
when you delete object from JList, call this method, toDoListEntityList is list of object which you put in Jlist.
About JList some advices. Good practice is declare generic type of JList (in your case is JList<TaskRowToDo> toDoList= new JList<TaskRowToDo>

How to listen to selection changes on TableViewer?

I'm working on an Eclipse RCP application and I'm trying to update an expression value which is provided by MySourceProvider according to selection changes on a TableViewer in MyEditorPart.
MyEditorPart instance defines a TableViewer like this:
public class MyEditorPart extends EditorPart {
#Override
public void createPartControl(Composite parent) {
TableViewer tableviewer = new TableViewer(parent, SWT.CHECK);
tableviewer.setContentProvider(ArrayContentProvider.getInstance());
getSite().setSelectionProvider(tableViewer);
...
MySourceProvider have some expression values like this:
public class MySourceProvider extends AbstractSourceProvider {
public static final String EXPR = "org.xyz.isEntrySelected";
// other expressions
#Override
public String[] getProvidedSourceNames() {
return new String[] { EXPR,
// other expressions
};
}
#Override
public Map getCurrentState() {
HashMap<String, Object> map = new HashMap<String, Object>(1);
map.put(EXPR, expr_value); // expr_value calculated by the listener
// other expressions
return map;
}
I want to change expr_value according to selection changes on TableViewer.
I registered the listener like this:
window.getSelectionService().addPostSelectionListener(MyEditorPartId, selectionListener);
private final ISelectionListener selectionListener = new SelectionListener() {
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
handleEvent();
}
};
The listener registers successfully but gets notified only once if I clicked somewhere on MyEditorPart (not just TableViewer but the whole editor). To get notified again, I have to click on some other view (or editor) part to lose focus and then click again on MyEditorPart.
1. Why does the listener gets notified only once when MyEditorPart re-gains focus?
2. How to listen only to selection changes to TableViewer rows?
What am I missing here? What is the proper way to listen to selection changes?
Thanks in advance.
What you need is not a SelectionListener, but a SelectionChangedListener.
With this you can write the following code:
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = viewer.getStructuredSelection();
Object firstElement = selection.getFirstElement();
// do something with it
}
});
It does appear that this form of addPostSelectionListener only fires when the part becomes active. Use the:
addPostSelectionListener(ISelectionListener listener)
form of the listener which is called for every selection change.
You can then test the IWorkbenchPart id in the listener:
#Override
public void selectionChanged(final IWorkbenchPart part, final ISelection selection)
{
if (MyEditorPartId.equals(part.getSite().getId()))
{
// your code
}
}

Categories