Multiple selection and JPopupMenu on right click - java

I am having problems with a popup menu on a JTable and the fact that this JTable allows for Multiple Interval Selection.
I'm going to explain in detail my situation, making it as clear as possible, hopefully.
I have a basic data class, lets call it Item, with a string id (name) and two boolean fields, online and active (with relative getters).
The idea behind the JTable is that, for each item in the dataset, it will show its name in the first colum and its status in the second column, where by 'status' I mean that, it will show "ACTIVE/NOT ACTIVE" if the Item is Online, otherwise it will show "OFFLINE".
I have implemented a TableModel that does the job and it works.
I also want, when the user right clicks on a row, a popup to appear (if the selected Item is ONLINE) allowing to Activate/Deactivate the item, depending on its status.
This worked perfectly as long as the Selection Model was SINGLE SELECTION, but when I changed it to MULTIPLE INTERVALS SELECTION, I could not make it work properly anymore.
The behaviour that I want is that, on right-click, a popup appears where the click is performed, the row is added to the selection and highlighted and all the previously selected rows stay selected! This I cannot manage to do!
Here is the code I have in the MouseListener:
tblModel.addMouseListener(new MouseAdapter() {
void showPopup(MouseEvent e){
int r = tblModel.rowAtPoint(e.getPoint());
if (r >= 0 && r < tblModel.getRowCount()) {
//tblModel.setRowSelectionInterval(r, r);
} else {
tblModel.clearSelection();
}
int[] viewRowIndexes = tblModel.getSelectedRows();
int rowViewIndex = tblModel.getSelectedRow();
if (rowViewIndex < 0)
return;
int rowModelIndex = tblModel.convertRowIndexToModel(rowViewIndex);
if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
Action changeActiveAction;
Action changeInactiveAction;
List<String> actives = new ArrayList<String>();
List<String> inactives = new ArrayList<String>();
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) tblModel.getSelectionModel();
for (int viewRowIndex : viewRowIndexes) {
int modelRowIndex = tblModel.convertRowIndexToModel(viewRowIndex);
if (selectionModel.isSelectedIndex(viewRowIndex)) {
boolean online = ((MyTableModel) tblModel.getModel()).isItemOnline(modelRowIndex);
if (!online)
continue;
boolean active = ((MyTableModel) tblModel.getModel()).isItemActive(modelRowIndex);
String idItem = (String) ((MyTableModel) tblModel.getModel()).getValueAt(modelRowIndex,0);
if (active) {
actives.add(idItem);
} else {
inactives.add(idItem);
}
}
}
if (actives.size() > 0 || inactives.size() > 0) {
popup = new JPopupMenu();
if (actives.size() > 0) {
changeActiveAction = new ChangeAction("Deactivate ACTIVE Items","This will deactivate all the selected ACTIVE items",actives, false);
popup.add(new JMenuItem(changeActiveAction));
}
if (inactives.size() > 0) {
changeInactiveAction = new ChangeAction("Activate INACTIVE Items","This will activate all the selected INACTIVE items",inactives, true);
popup.add(new JMenuItem(changeInactiveAction));
}
popup.show(e.getComponent(), e.getX(),e.getY());
}
}
}
#Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
};
The behaviour is functionally correct, but the selection of rows is not working.
Having commented the line
//tblModel.setRowSelectionInterval(r, r);
when I right-click on a row, a popup appears, but it ignores the row on which I clicked.
On the other hand, if uncommented, that line will select only the clicked row, losing all the rest of the selection....
I am sorry for the long post, but I didn't know how to explain my problem without giving all the details of my situation....
Hopefully this is a trivial thing and you can tell me how I can fix/change it.
Thank you in advance.

One part of the answer is:
if (tblModel.isSelectedIndex(r)) {
tblModel.removeSelectionInterval(r, r);
} else {
tblModel.addSelectionInterval(r, r);
}

Related

How to get value from dynamic JCheckBox?

I created dynamic JCheckBox, and I don't know how to get their value when I check it.
When I click the checkbox I want to get value and put them to SQL query.
like : query = select checkbox1, checkbox2 from table
This is my dynamic checkbox code:
roll[K] = new JCheckBox();
roll[K].setText(metaData.getColumnLabel(columnIndex));
roll[K].setBounds(X,Y,150,30);
Y = Y+30;
Rectangle r = jPanel3.getBounds();
int h=r.height;
if (Y>=h-50){
Y=0;
X=X+200;
}
jPanel3.add(roll[K]);
You can set checkbox item listener like this
roll[K].setActionCommand(Integer.toString(k));
roll[K].addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
//this is not necessary and depends upon you, how do u want
// use this
int id = Integer.parseInt(Integer.getSource().getActionCommand())
//can apply switch case on ID to take appropriate action based on ID
if (e.getStateChange() == 1)
System.out.println("Checked");
else
System.out.println("un-Checked");
}
});

Selecting Items in JComboBox

I have two combo boxes with a list of distance units to convert from/to. Now, when I want to choose eg. "Centimeter" from the ComboBox From (distance)..., I really don't need to have "Centimeter" in ComboBox To (distance)..., because it doesn't make sense to convert from centimeter to centimeter.
So when "Centimeter" is selected in From (distance)... I want it to be removed in To (distance)... ComboBox. But, when I change my selection (say "Meter"), I want "Centimeter" to be back and "Meter" disappear etc.
I managed to remove the selected item in To (distance)... box, but don't know how to return it back when I change my selection. Besides, when I change selection, the code below just removes the corresponding item in To (distance)... ComboBox.
Please guide me to the correct solution. Here is the corresponding code. I can give you the whole code if you need. Thank you!
private String[] convertFromDistance = {"From (distance)...", "Centimeter", "Inch", "Kilometer", "Knot", "Meter", "Mile", "Millimeter", "Yard"};
private String[] convertToDistance = {"To (distance)...", "Centimeter", "Inch", "Kilometer","Knot", "Meter", "Mile", "Millimeter", "Yard"};
private JComboBox fromListDistance, toListDistance;
fromListDistance.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String list = (String)fromListDistance.getSelectedItem();
for (int i=0; i<convertToDistance.length; i++) {
if (convertToDistance[i].equals(list)) {
toListDistance.removeItem(convertToDistance[i]);
//here should go the code for adding back the item if selection is changed
}
}
}
});
toListDistance = new JComboBox<String>(convertToDistance);
first thing you i should do in your problem is to know what is the selected choice from fromListDistance combo box ..
after that i have to refill the toListDistance combo box except for the choice that the user have selected ..
it's easy to do this with if statement
fromListDistance.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//saving the selected choice
String choise=fromListDistance.getSelectedItem().toString();
//here we remove all items from the combo box
toListDistance.removeAllItems();
for (int i = 0; i < convertToDistance.length; i++) {
String distance=convertToDistance[i];
//compare the selected choice with the convertToDistance[i]
if (choise.equals(distance)) {
continue;
}
toListDistance.addItem(distance);
}
}
});

How to detect a selection on JavaFX TableView when clicking a highlighted item?

I need a way to get the user selection every time a user selects an item on a TableView, even if the item is already selected.
The tableView.getSelectionModel().selectedItemProperty().addListener works when the user selects a different item from the one highlighted, but if the user selects the highlighted item again, it doesn't seem to work.
How would this be fixed?
you can do this:
tableView.setOnMouseClicked((MouseEvent event) -> {
if(event.getButton().equals(MouseButton.PRIMARY)){
System.out.println(tableView.getSelectionModel().getSelectedItem());
}
});
the code above doesn't work if you select the highlighted item again using editable table cell
If you're only interested in the clicks on the rows, use a custom rowFactory:
TableView<Item> table = ...
EventHandler<MouseEvent> clickListener = evt -> {
TableRow<Item> row = (TableRow<Item>) evt.getTarget();
if (!row.isEmpty()) {
// do something for non-empty rows
System.out.println("you clicked " + row.getItem());
}
};
table.setRowFactory(tv -> {
TableRow<Item> row = new TableRow<>();
// add click listener to row
row.setOnMouseClicked(clickListener);
return row;
});
The simplest way what i know:
yourTableView.setOnMousePressed(e ->{
if (e.getClickCount() == 2 && e.isPrimaryButtonDown() ){
int index = yourTableView.getSelectionModel().getSelectedIndex();
System.out.println("" + index);
}
});
put it in to constructor or initialize method in your corntroller class... :)

<JTable>.getSelectedRow() is returning -1

I have written a "double-click" event on my JTable. My JTable, viz. myTaskTable is populated with a number of rows having multiple columns. I want the row index to be retrieved when I double click on one of the rows of the JTable. I am not sure why is it always returning me an index of -1 resulting in an exception. Am I am overlooking something? What could be going wrong?
This is how I am retrieving the index of the selected row from the JTable - myTaskTable
int selRow = myTaskTable.getSelectedRow();
Thank you!
Edit
Here is the code:
...
myTaskTable.addMouseListener(this);
...
public void mouseClicked(MouseEvent e)
{
if(e.getModifiers() == MouseEvent.BUTTON1_MASK)
{
if(e.getClickCount() == 2)
{
e.consume();
int selRow = myTaskTable.getSelectedRow();
System.out.println("GridReport double clicked on row="+selRow);
}
}
}
Get the row index using the event, not the table selection:
final int selectedRowIndex = table.rowAtPoint(mouseEvent.getPoint());
// If the rows are sorted or filtered
final int modelRowIndex = table.convertRowIndexToModel(selectedRowIndex);
getSelectedRow() would not work with multiple selected rows (multiple selections allowed), as it will always return "the index of the first selected row".
have you tried to put e.consume(); as the last statement?
public void mouseClicked(MouseEvent e){
if(e.getModifiers() == MouseEvent.BUTTON1_MASK){
if(e.getClickCount() == 2){
int selRow = myTaskTable.getSelectedRow();
System.out.println("GridReport double clicked on row="+selRow);
e.consume();
}
}
}
normaly e.consume(); is called when you are done with your reactive code. This clears dependencies of the Event, so it might also clear the selected Row.

JTable boolean values not updating when using JOptionPane

I'm trying to write a bit of code that can allow the user to fill in text fields by clicking on boolean cells in a JTable.
I can get the program to enter the data from the table into a text-field but my current method of doing this involves a JOptionPane which for some strange reason stops the table from changing the check-box values (i.e. the check-box doesn't change from black to ticked). Not only this but the selection doesn't update so the value in the last column remains false, even though the selection should switch it to true.
I think it might be something to do with the JOptionPane somehow overriding the selection event, but I don't know enough about the JOptionPane object to say how. My code is:
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel) e.getSource();
if (lsm.isSelectionEmpty()) {
//no rows are selected do nothing
} else {
//First find the row clicked
int selectedRow = lsm.getLeadSelectionIndex();
/*
* put a popup here to ask the user which peak to associate
* the energy with.
*/
System.out.println(selectedRow);
//Get user to associate with a peak
availablePeaks = getAvailablePeaks();
String returnVal = (String) JOptionPane.showInputDialog(
null,
"Select the peak:",
"Peak Matching",
JOptionPane.QUESTION_MESSAGE,
null,
availablePeaks, null);
System.out.println(returnVal);
//Determine the selection
int index = 0;
for (int i = 0; i < availablePeaks.length; i++) {
if (availablePeaks[i] == returnVal) {
index = i;
} else {
}
}
//Set the peak value in the peak specifier to the energy in the row
double energy = (Double) table.getValueAt(selectedRow, 0);
System.out.println(energy);
frame.getPeakSetter().getPeakSpecifiers()[index].setEnergy(energy);
frame.getPeakSetter().getPeakSpecifiers()[index].getTextField().setText("" + energy);
}
}
});
Does anyone know why a JOptionPane in the ListSelectionListener would stop the table from updating the check-boxes?
Thanks!
I assume that your model returns true for isCellEditable() and that getColumnClass() returns Boolean.class for the JCheckBox column. This enables the default rednerer/editor, listed here.
It looks like the gesture of selecting the row is bringing up the dialog. It's not clear how this prevents the DefaultCellEditor from concluding; it works for me. As you are not checking getValueIsAdjusting(), I'm surprised you don't see two ListSelectionEvent instances.
In any case, bringing up a dialog each time the selection changes seems cumbersome. Several alternatives are possible:
Keep the ListSelectionListener, make the cell non-editable by returning false from isCellEditable(), and set its value in the model only if the dialog concludes successfully.
Drop the ListSelectionListener in favor of a JButton editor, shown here.
Drop the ListSelectionListener in favor of a custom CellEditor, as outlined below.
table.setDefaultEditor(Boolean.class, new DefaultCellEditor(new JCheckBox()) {
#Override
public boolean stopCellEditing() {
String value = JOptionPane.showInputDialog(...);
...
return super.stopCellEditing();
}
});

Categories

Resources