Remove HTML from JTable CellEditor - java

I have a JTable and some editable cells which are dynamically formatted with very specific HTML based on some business rules.
However, when you edit these cells all the HTML is in the CellEditor. I just want the plain text in the CellEditor.
I am trying to do this to the entire table. Here is the code I used. I threw together an extended DefaultCellEditor but its still showing the HTML. I don't even see the debugger entering the getCellEditorValue() method. What do I do?
public class MyTable extends JTable
{
public MyTable()
{
MyTable.setCellEditor(new DefaultCellEditor(new JTextField())
{
#Override
public Object getCellEditorValue() {
// get content of textField
String str = (String) super.getCellEditorValue();
if (str == null) {
return null;
}
if (str.length() == 0) {
return null;
}
//remove HTML and return plain text
return Jsoup.parse(str).text();
}
});
}
}

I'm not sure where things are going awry; a complete example may shed some light. The normal editing sequence is outlined here, suggesting that you should probably create your own renderer and editor:
class MyRenderer extends DefaultTableCellRenderer {…}
class MyEditor extends DefaultCellEditor {…}
and apply them as follows:
table.setDefaultRenderer(String.class, new MyRenderer());
table.setDefaultEditor(String.class, new MyEditor());
Be certain that your TableModel returns the correct type token from getColumnClass().

Related

JComboBox to display multiple lines of text

I'm currently writing a small tool for sending sql queries to a database and recieving the according data.
Now to my problem:
I want to allow the user to enter a new search query or select from a "latest" list, where the last few queries are saved.
For that, I planned on using an editable JComboBox, but I'm having trouble diplaying multiple lines of text in the box itself.
The reason I want to do that, is because sql queries can get quite long and since I want make the box editable and at the same time keep the frame clean.
I've found ways to display multiple lines in the dropdown menu, but nothing for the box itself.
Thank you in advance and please forgive me if I overlooked something simple ;)
Greetings
Zeus
Extended editing functionality is supplied by the ComboBoxEditor, this allows you to define the actual component which is used as the combobox's editor
Based on your requirements, you're going to need (at the very least) a JTextArea, to provide (optionally) word wrapping and multiple lines
A rough and ready example might look something like this...
public class TextAreaComboBoxEditor implements ComboBoxEditor {
private JTextArea ta = new JTextArea(4, 20);
private JScrollPane sp = new JScrollPane(ta);
public TextAreaComboBoxEditor() {
ta.setWrapStyleWord(true);
ta.setLineWrap(true);
}
#Override
public Component getEditorComponent() {
return sp;
}
#Override
public void setItem(Object anObject) {
if (anObject instanceof String) {
ta.setText((String) anObject);
} else {
ta.setText(null);
}
}
#Override
public Object getItem() {
return ta.getText();
}
#Override
public void selectAll() {
ta.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
}
#Override
public void removeActionListener(ActionListener l) {
}
}
This doesn't support ActionListener, as JTextArea uses the Enter key for it's own purposes. If you wanted to, you could use the key bindings API to add your own Action that can trigger the ActionListeners, for that, you'd need to supply a List or other means for managing them so you can call them back

GWT: Adding GWTP Tooltip to a CellTable cell

I want to use GWT-Bootstrap Tooltip for cells of a column in the CellTable. Each Tooltip will show description of a cell which is a field in the "MyCustomObject" class used for generating the table.
One of the quick solutions I found in one of the answers on this question is the following.
CellTable<MyCustomObject> table = new CellTable<MyCustomObject>();
table.addCellPreviewHandler(new Handler<MyCustomObject>() {
#Override
public void onCellPreview(CellPreviewEvent<MyCustomObject> event) {
if (event.getNativeEvent().getType().equals("mouseover")){
table.getRowElement(event.getIndex()).getCells()
.getItem(event.getColumn()).setTitle(event.getValue().getDescription());
}
}
}
);
It makes a little sense but I don't see anything when I hover the cursor over the table cells and nothing is attached to the DOM. Can anyone explain how this even works? I want to attach the Tooltip to table cell similar to the following.
Tooltip tt = new Tooltip("Here goes the description");
tt.setAnimation(true);
tt.setWidget(tableColumn);
tt.reconfigure();
The problem is that a CellTable cell is not a widget so it can't be attached in that way.
So is there any workaround for this?
I've faced this issue once and I created my own cell that displays a tooltip, here's how I did it: Note: My cell was displaying an image with a tooltip so I quickly changed the code to display String text... So I did not test it with text.
private class TooltipCell extends AbstractCell<String> {
private String tooltipText = "";
#Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendHtmlConstant("<div title=\"" + tooltipText + "\">");
sb.append(SafeHtmlUtils.fromString(value));
}
}
public void setTooltip(String tootltipTextToSet){
tooltipText = tootltipTextToSet;
}
}
And in your table use method setTooltip("tooltip text") in method getValue just before returning the cell text.
Hope this helps

SWT TreeViewer with combobox and checkbox

I'm looking for a way to display a tree in the first column of a table/grid with three other columns, one with a combobox and the others with checkboxes. I've been trying to make this work with a TreeViewer but it doesn't quite fit what I'm looking for. The tree goes together fine. The Combobox column where I used the EditorSupport for the column and return a ComboboxCellEditor in the getCellEditor method but you can only see that there is a combobox in the column when you select a cell in that column. Then when you click out of the cell the selected value goes back to the default blank. The same goes for the checkbox columns where it is is only visible when the cell is selected. I'm looking for something that will display my tree with the combobox column and checkbox columns always visible. I've looked at TableViewer but couldn't find a way to force in a tree in the first column. I've looked at Nebula Grid but that doesn't look like it supports comboboxes. Any tips on how to get one of these to work like what I am looking for or if there is some other tree/table/grid I should be looking at. Thanks.
Edit: Here's the code for the EditingSupport class.
private class ComboBoxEditingSupport extends EditingSupport
{
private ComboBoxCellEditor cellEditor;
public ComboBoxEditingSupport(ColumnViewer viewer)
{
super(viewer);
cellEditor =
new ComboBoxCellEditor(((TreeViewer) viewer).getTree(),
new String[] {
"Some String",
"Some other String" }, SWT.READ_ONLY);
}
#Override
protected CellEditor getCellEditor(Object element)
{
if (element instanceof MyObject
{
return cellEditor;
}
return null;
}
#Override
protected boolean canEdit(Object element)
{
if (element instanceof MyObject
{
return true;
}
return false;
}
#Override
protected Object getValue(Object element)
{
return 0;
}
#Override
protected void setValue(Object element, Object value)
{
TreeItem[] ti = treeViewer.getTree().getSelection();
CCombo combo = ((CCombo) cellEditor.getControl());
String str = combo.getItem(combo.getSelectionIndex());
ti[0].setText(1, str);
}
}
Your setValue method must update the value in your model data (the data returned by your content provider). The element parameter to setValue is the particular model data object (MyObject) that you should update.
After updating the value call:
getViewer().update(element, null);
to get the tree to update the display from the model.
Trying to update the TreeItem directly will not work.

Input validation using TableCellEditor in jTables

I have a JTable with 3 columns. One on the columns must have an integer value and I must validate the input before the cell loses its focus.
I've used cell editor and overrided the stopCellEditing() function. I've wrote the validation in stopCellEditing and it does keep the focus on the cell but but my problem is this:
the column cannot accept more than one value (if I move to editing another cell the content disappears!!)
I cannot hit enter if I'm editing one of the cells in this column!
this is my editor class:
public class MyEditor extends DefaultCellEditor implements TableCellEditor {
public MyEditor() {
super(new JTextField());
}
#Override
public boolean stopCellEditing() {
Object obj = delegate.getCellEditorValue();
if (obj is not an integer) {
return false;
}
return true;
}
and this is how I'm using in in my Frame:
studentsTable.getColumnModel().getColumn(2).setCellEditor(new
MyEditor());
Plz help me :)
One on the columns must have an integer value
No need to write a custom editor for this.
All you need to do is override the getColumnClass() method of JTable or your TableModel and the table will use the supplied Integer editor.
Regarding the code you posted:
It won't compile since your if condition is not valid. We want real code so we can spot possible logic errors. The code should also be posted in the form of an SSCCE.
There is no need to reference the delegate variable. Just invoke the getCellEditor() method directly.
Don't know if it makes a difference bu when I override stopCellEditing(), instead of returning true I use:
return super.stopCellEditing();

JTable - drag and drop

OK, this problem is out of my league. I'm trying to implement a GUI widget in swing that allows files to be dropped onto a JTable, and allows the rows of the JTable to be dragged for re-sorting. Think VLC's playlists or the one in iTunes.
I got dropping files from the OS (Explorer, Finder, etc.) working just fine, but I'm having an impossible time with re-arranging the rows of the table, once the files are in. The problem is that when I add a custom TransferHandler to the table, dragging from the table is instantly killed. Here is some example code:
import javax.swing.*;
public class TableTest
{
public static void main (String [] argv)
{
// setup table data
String [] columns = new String [] {"Foo", "Bar", "Baz", "Quux"};
String [][] data = new String [][] {{"A", "B", "C", "D"},
{"1", "2", "3", "4"},
{"i", "ii", "iii", "iv"}};
// create table
JTable table = new JTable(data, columns);
// set up drag and drop
table.setDragEnabled(true);
table.setDropMode(DropMode.INSERT_ROWS);
table.setFillsViewportHeight(true);
TransferHandler dnd = new TransferHandler() {
// here be code to handle drops, and one would
// presume drag exporting, too
};
table.setTransferHandler(dnd);
JScrollPane scroll = new JScrollPane(table);
// create and show window
JFrame window = new JFrame();
window.getContentPane().add(scroll);
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
Run this code as-is and you'll see that you cannot initiate a drag on the table.If you comment out the call to setTransferHandler() on the table, dragging works (i.e., when I start dragging a table row, I get the X'd out circle cursor saying I can't drop there). But as soon as a TransferHandler is set for the table, I can't drag any rows. The problem has to be in the TransferHandler, but I've thoroughly troubleshot and debugged it, and have determined that dragging is never started once there is a TransferHandler on the table. What am I doing wrong?
I had the same problem, it's got nothing to do with your custom implementation of the TransferHandler. When you replace the TransferHandler you also need to get a hold of the default DragSource and tell it to recognize drag gesture. You may also need to implement your own Transferable because you'll need to pass it to the DragGestureEvent.startDrag() method.
table.setTransferHandler(new MyTransferHandler());
table.setDragEnabled(true);
DragSource source = DragSource.getDefaultDragSource();
source.createDefaultDragGestureRecognizer(table, DnDConstants.ACTION_COPY, new DragGestureListener() {
#Override
public void dragGestureRecognized(DragGestureEvent dge) {
//grab the selected files from the table model
ArrayList<File> files = new ArrayList<File>();
for (int row : table.getSelectedRows()) {
files.add((File) dm.getValueAt(row, 1));
}
//FileTransferable is a custom Transferable implementation
Transferable transferable = new FileTransferable(files);
//and this is the magic right here
dge.startDrag(null,transferable);
}
});
It doesn't look like you are using the TransferHandler properly. Try to read through the tutorial here.
See the TransferHandler doc here. The empty constructor doesn't look like it's meant for usage outside a subclass of TransferHandler.
And you don't implement any of the functionality provided in the standard TransferHandler provided on Swing components. See exerpt from the DnD tutorial here (my bold):
Note: If you install a custom TransferHandler onto a Swing component, the default support is replaced. For example, if you replace JTextField's TransferHandler with one that handles colors only, you will disable its ability to support import and export of text.
If you must replace a default TransferHandler — for example, one that handles text — you will need to re-implement the text import and export ability. This does not need to be as extensive as what Swing provides — it could be as simple as supporting the StringFlavor data flavor, depending on your application's needs.
I think the problem is that the empty TransferHandler actually prevents DnD events from occurring. There is a sample here which may be relevant.
http://www.java2s.com/Code/Java/Swing-JFC/ExtendedDnDDragandDropDemo.htm
I did not want to get into the nuts and bolts of what was going on so I just delegated the methods I wasn't interested to the old TransferHandler.
tree.setDragEnabled(true);
tree.setDropMode(DropMode.XXXX);
tree.setTransferHandler(new MyTransferHandler(tree.getTransferHandler());
Start with a standard setup but pass the old TransferHandler into your custom TransferHandler.
private class MyTransferHandler extends TransferHandler {
private TransferHandler delegate;
public MyTransferHandler(TransferHandler delegate) {
this.delegate = delegate;
}
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
return delegate.canImport(comp, transferFlavors);
}
public boolean canImport(TransferSupport support) {
return true;
}
protected Transferable createTransferable(JComponent c) {
try {
Method method = delegate.getClass().getDeclaredMethod("createTransferable", JComponent.class);
method.setAccessible(true);
return (Transferable) method.invoke(delegate, c);
} catch (Exception e) {
return super.createTransferable(c);
}
}
public void exportAsDrag(JComponent comp, InputEvent event, int action) {
delegate.exportAsDrag(comp, event, action);
}
protected void exportDone(JComponent source, Transferable data, int action) {
try {
Method method = delegate.getClass().getDeclaredMethod("exportDone", JComponent.class, Transferable.class,
int.class);
method.setAccessible(true);
method.invoke(delegate, source, data, action);
} catch (Exception e) {
super.exportDone(source, data, action);
}
}
public int getSourceActions(JComponent c) {
return delegate.getSourceActions(c);
}
public Icon getVisualRepresentation(Transferable t) {
return delegate.getVisualRepresentation(t);
}
public boolean importData(JComponent comp, Transferable t) {
return delegate.importData(comp, t);
}
public boolean importData(TransferHandler.TransferSupport support) {
return delegate.importData(support);
}
}
One gotcha is that createTransferable(JComponent) and exportDone(JComponent, Transferable, int) methods are protected so you need to do reflection in order to delegate to those methods. When I didn't do this reflection delegation the strategy did not work. Once I did this delegation drag and drop worked as expected without changing the DragSource or having to write a new Transferable.

Categories