Currently every header contains the name of the column and ocassionally a combo box below it. Whenever the combo box is clicked the jtable automatically sort. Is there a simple way to disable sorting for just the combo box clicks while preserving the rest of the header to sort on click.
I have been suggested JXTable but am fearful that it will cause more problems than it would fix.
Any help is appreciated.
Try something like:
public class SortFilterTableHeaderUI extends BasicTableHeaderUI {
private Component filteredComponent;
#Override
protected MouseInputListener createMouseInputListener() {
return new MouseInputHandler() {
#Override
public void mouseClicked(MouseEvent e) {
if (!filteredComponent.contains(e.getPoint()))
super.mouseClicked(e);
}
};
}
}
Other option is override JTAbleHeader.columnAtPoint(Point point) and return -1 if the combo contains the point.
Related
Is there a way to set the value in a ComboBoxCellEditor other then when the focus is lost on the cell? I'm using it in each cell of a column in a TreeViewer and the only time that the setValue method is called is when focus is lost on the cell. So when a user makes a selection and doesn't click off of the cell the value is never set to the new selection. I've tried adding listeners on the ComboBoxCellEditor and on the control of the ComboBoxCellEditor but nothing seems to pick up the selection event.
I figured out that I needed to cast the control to a CCombo in order to add the correct type of listener to the ComboBoxCellEditor. Here's what I did:
CCombo combo = (CCombo) cellEditor.getControl();
combo.addSelectionListener(new SelectionListener()
{
#Override
public void widgetSelected(SelectionEvent paramSelectionEvent)
{
//selection code here...
}
#Override
public void
widgetDefaultSelected(SelectionEvent paramSelectionEvent)
{
//do nothing here...
}
});
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()))
I am very new to SWT. Started working on it today actually. I have a table of type CheckboxTableViewer. What i want to be able to do is whenever the user selects the row (i.e clicks anywhere on the row) I want the check box to be checked (ticked). Currently I have a listener on the CheckboxTableViewer as follows:
diagnosesTableViewer.addCheckStateListener(new ICheckStateListener() {
#Override
public void checkStateChanged(CheckStateChangedEvent event) {
Nomenclature changedStateNomenclature = (Nomenclature) event
.getElement();
if (event.getChecked()) {
selectedNomenclatures.add(changedStateNomenclature);
} else {
selectedNomenclatures.remove(changedStateNomenclature);
}
}
});
I am able to select the row by checking on the checkbox. But i want to select the check box even when the user selects the row by clicking anywhere on that row on any column (not just the checkbox).
I guess that logic would go somewhere in the addSelectionChangedListener for the addSelectionChangedListener. But I am not sure how to go about it. Can anyone help me with this?
Use this code: Add selection listener to the table. ctv is the instance of of your CheckboxTableViewer.
Also I assumed CheckboxTableViewer allow only single selection not multi.
ctv.getTable().addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
int df = ctv.getTable().getSelectionIndex();
ctv.setChecked(ctv.getElementAt(df), !ctv.getChecked(ctv.getElementAt(df)));
}
});
I have a JTable with editable cells. When I click in a cell, it enters edit mode; the same happens when I'm moving through cell using the directional arrows.
Now I want to select the cell instead of start editing, and edit the cell only when the Enter key is pressed.
If any other information is needed, please just ask for it.
Edit: Action for Enter key
class EnterAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
JTable tbl = (JTable) e.getSource();
tbl.editCellAt(tbl.getSelectedRow(), tbl.getSelectedColumn());
if (tbl.getEditorComponent() != null) {
tbl.getEditorComponent().requestFocus();
}
}
}
Now this is for left arrow action the rest of 3 are not hard to deduce from this one:
class LeftAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
JTable tbl = (JTable)e.getSource();
tbl.requestFocus();
tbl.changeSelection(tbl.getSelectedRow(), tbl.getSelectedColumn() > 0 ? tbl.getSelectedColumn()-1:tbl.getSelectedColumn(), false, false);
if(tbl.getCellEditor()!=null)
tbl.getCellEditor().stopCellEditing();
}
}
And this is how you bind this actions:
final String solve = "Solve";
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(enter, solve);
table.getActionMap().put(solve, new EnterAction());
final String sel = "Sel";
KeyStroke arrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(arrow, sel);
table.getActionMap().put(sel, new LeftAction());
Oh,i almost forgot,to select the cell instead of edit on Mouse Click:
public static MouseListener mAdapterTable = new MouseListener()
{
#Override
public void mousePressed(MouseEvent e)
{
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing())
{
tbl.getCellEditor().stopCellEditing();
}
}
#Override
public void mouseClicked(MouseEvent e) {
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing() )
tbl.getCellEditor().stopCellEditing();
}
#Override
public void mouseReleased(MouseEvent e) {
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing() )
tbl.getCellEditor().stopCellEditing();
}
};
The EventListner must be added to table like so:
table.addMouseListener(mAdapterTable);
Use Key Bindings for this. Most Look & Feel implementations already bind F2 to the table's startEditing action, but you add a different binding:
tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "startEditing");
This will effectively replace the previous binding of Enter to the table's selectNextRowCell action.
Here is what i would do:
First enable the single cell selection for the JTable
Create a KeyAdapter or KeyListener for the JTable or for the JPanel,
what contains your table.
In the KeyAdapter's keyPressed() method enter the edit mode of the
selected cell, something like this:
http://www.exampledepot.com/egs/javax.swing.table/StopEdit.html
You can check in the keyPressed() method, if the user pressed the right button for editing. I'm not sure, if the normal (double click) editing is disabled in your table, then what happens, if you try to edit it programmatically, but if it doesn't work, then you can enable the editing on the selected cell, when the user presses the edit button, then when he/she finished, disable it again.
I´m trying to implement an undo (and redo) function for an editable JTable with the default components. The JTable has an extra class to specify its properties called SpecifiedJTable.
To do so I wanted to grab the moment when a cell is doubleclicked (i.e. the moment when a cell is chosen/marked to be edited) to push the information in the cell and its coordinates onto the stack.
This should be done by a MouseListener ...at least that was my idea.
I tried this (standing in the constructor of my SpecifiedJTable class)
class JTableSpecified extends JTable {
private static final long serialVersionUID = 1L;
private int c; // the currently selected column
private int r; // the currently selected row
public JTableSpecified(String[][] obj, String[] columnNames) {
super(obj, columnNames); // constructs the real table
// makes that you can only select one row at a time
this.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
// makes that columns are not squeezed
this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// forbids to rearrange the columns
getTableHeader().setReorderingAllowed(false);
// adds action listener
this.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
r = getSelectedRow();
c = getSelectedColumn();
// get the String at row r and column c
String s = (String) getValueAt(r, c);
if (jobDisplayed) jobSwitch(c, s);
else resSwitch(c, s);
}
});
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
System.out.println("test");
}
}
});
}
}
but somehow the clickCounter doesn´t want to reach anything that´s higher than 1.
I am glad about any answer and help. Thanks.
The problem you are experiencing is related to use of mouseClicked() rather than using mousePressed(). In this case it appears to be very hard to increase the click counter, yet still it is possible. It took me lots of clicking and also mouse movement to increase the click counter over 1. You could try it by yourself, in your code. To get the counter over 1 you need to go crazy on the mouse by pressing & releasing fast while moving the mouse from cell to cell at the same time (or maybe I was just luckily clicking between the cells?).
As you can see in this fully working sample, made from your code, two mouse presses, using the mousePressed() method are being detected just fine.
public class JTableSpecified extends JTable {
private static final long serialVersionUID = 1L;
public JTableSpecified(String[][] obj, String[] columnNames) {
super(obj, columnNames); // constructs the real table
// makes that you can only select one row at a time
this.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
// makes that columns are not squeezed
this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// forbids to rearrange the columns
getTableHeader().setReorderingAllowed(false);
// adds action listener
this.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
}
});
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 2) {
System.out.println("test");
}
System.out.println("e.getClickCount() = " + e.getClickCount());
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel panel = new JPanel();
panel.add(new JTableSpecified(new String[][]{{"oi", "oi2"}, {"oi3", "oi4"}}, new String[]{"Col1", "Col2"}));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(panel);
f.pack();
f.setVisible(true);
}
});
}
}
Conclusion: Maybe you in fact want to use the mousePressed() method?
This answer extends Boro´s answer.
To catch every case that enables the user to edit the table I will also need to add a KeyListener for F2 (which has the same effect as double clicking onto a cell) and disable the automatic cell editing by pressing any key.
I just added it to the constructor right behind the mouseListener (see above)
// forbids the editing by striking a key
this.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
// keyListener to react on pressing F2 (key code 113)
this.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 113) System.out.println("test");
}
});
The BasicTableUI is responding to the double-click by going into an edit mode on the cell that was double-clicked. It does lots of complicated stuff, part of which involves creating a JTextField (or other component) to allow the data to be edited, and then preventing the mouse click event from propagating any further.
If your table, or that table cell, is not editable, you can easily capture mouse events with click count 2, 3, 4, .... But since you want your table to be editable, you need a different approach.
One idea would be to override JTable.editCellAt()
A better idea is to forget about messing with the JTable and instead listen for data changes on the table model itself.
the error in the code is that the mouseClicked method is called as soon as the first click takes place. when a double click takes place the mouseClicked method is called again. you can place a static variable (or a class variable) for the earlier click event storing the time (using the e.getWhen() method).
Check for the time difference and if it's small enough, execute your actions (I'd suggest calling a doubleClick method).
you may have to implement mouse listener in your class JTableSpecified since a static variable might not be placed in your existing code.