Hi,
I have one table with a Member List and then several other tables to witch I want to move the Members using Drag and Drop.
I used
THIS CODE and it woks fine.
Then i tried to restrict the other tables to only 12 rows and it works fine in Single Selection Mode, but as soon as i allow multiple selections it is possible to Move more than 12 Member into one table. I tried several things but none was fine.
I just wondered if i have to add a new Transfer Handler to each table or if i have to add the same TransferHandler to each table? At the moment each table has its own Handler.
I need to know how many rows are selected and how many rows are in the table i want to drop them. I havent found a way to tell the accepting TransferHandler how many Rows are selected.
I also wanted to ask if someone can explain me the ViewportTransferHandler. I understand how the String and TableTransferHandler works but i'm not quite sure about the ViewportHandler especially about the getView() Method.
Another thing is that I highlight a single row in those tables on doubleclick or keypress, but as soon as i highlighted a row I get a NullPointerException when i want to move a row from that table, but it still works:
java.lang.NullPointerException
at javax.swing.plaf.basic.BasicTableUI$TableDropTargetListener.restoreComponentState(Unknown Source)
at javax.swing.plaf.basic.BasicDropTargetListener.dragExit(Unknown Source)
at javax.swing.TransferHandler$SwingDropTarget.dragExit(Unknown Source)
at sun.awt.dnd.SunDropTargetContextPeer.processExitMessage(Unknown Source)
at sun.awt.dnd.SunDropTargetContextPeer.access$700(Unknown Source)
at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchExitEvent(Unknown Source)
at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(Unknown Source)
at sun.awt.dnd.SunDropTargetEvent.dispatch(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.trackMouseEnterExit(Unknown Source)
at java.awt.LightweightDispatcher.processDropTargetEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Abd here the code of my CreateTable class:
public class CreateTable extends JPanel {
//private String tableID = null;
public CreateTable(String tableId) {
createTable(tableId);
}
private void createTable(String tableId) {
DefaultTableModel model = new DefaultTableModel() {
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}};
model.addColumn(tableId);
table = new JTable(model);
table.getTableHeader().setReorderingAllowed(false);
//table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(200,211));
table.setDragEnabled(true);
table.setTransferHandler(new TableTransferHandler());
scrollPane.getViewport().setTransferHandler(new ViewportTransferHandler());
//JPanel panel = new JPanel();
this.add(scrollPane);
this.setBorder(BorderFactory.createTitledBorder(tableId));
renderer = new MyRenderer();
table.setDefaultRenderer(Object.class, renderer);
table.setDefaultRenderer(Boolean.class, renderer);
//protectRows(1,2);
scrollPane.setViewportView(table);
//On Keypress highlight row
table.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if (e.getKeyChar() == 'l'){
protectRows(table.getSelectedRow());
}
}
} );
//On DoubleClick highlight row
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if (e.getClickCount() == 2){
protectRows(table.getSelectedRow());
}
}
} );
}
private void protectRows(int rowFrom){
//if(rowsProtected.size() == 0)
if(rowsProtected.isEmpty())
rowsProtected.add(""+rowFrom);
else if(rowsProtected.contains(""+rowFrom))
rowsProtected.clear();
else {
rowsProtected.clear();
rowsProtected.add(""+rowFrom);
}
table.updateUI();
}
private JTable table;
private DefaultTableCellRenderer renderer;
private HashSet rowsProtected = new HashSet();
private DefaultTableModel tablemodel;
class MyRenderer extends DefaultTableCellRenderer {
public MyRenderer(){
super();
}
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Color background, foreground;
if(rowsProtected.contains(""+row)){
background = Color.yellow;
foreground = Color.blue;
if(isSelected){
background = Color.orange;
}
}else{
background = Color.white;
foreground = Color.black;
if(isSelected){
background = Color.lightGray;
}
}
setBackground(background);
setForeground(foreground);
super.setValue(value);
return this;
}
}
}
abstract class StringTransferHandler extends TransferHandler {
public int rows;
public int rows1;
protected abstract String exportString(JComponent c);
protected abstract void importString(JComponent c, String str);
protected abstract void cleanup(JComponent c, boolean remove);
protected Transferable createTransferable(JComponent c) {
return new StringSelection(exportString(c));
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public boolean importData(JComponent c, Transferable t) {
if (canImport(c, t.getTransferDataFlavors())) {
try {
String str = (String)t.getTransferData(DataFlavor.stringFlavor);
importString(c, str);
return true;
} catch (UnsupportedFlavorException ufe) {
} catch (IOException ioe) {
}
}
return false;
}
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, action == MOVE);
}
public boolean canImport(JComponent c, DataFlavor[] flavors) {
//More than 12 people in table?
JTable t = (JTable) c;
if(t.getRowCount() >= 12) return false;
for (int ndx = 0; ndx < flavors.length; ndx++) {
if (DataFlavor.stringFlavor.equals(flavors[ndx])) {
return true;
}
}
return false;
}
}
class TableTransferHandler extends StringTransferHandler {
public JTable target;
public int[] rows = null;
public int addIndex = -1; //Location where items were added
public int addCount = 0; //Number of items added.
protected String exportString(JComponent c) {
JTable table = (JTable)c;
rows = table.getSelectedRows();
super.rows1 = rows.length;
int colCount = table.getColumnCount();
StringBuffer buff = new StringBuffer();
for (int ndx = 0; ndx < rows.length; ndx++) {
for (int j = 0; j < colCount; j++) {
Object val = table.getValueAt(rows[ndx], j);
buff.append(val == null ? "" : val.toString());
if (j != colCount - 1) {
buff.append(",");
}
}
if (ndx != rows.length - 1) {
buff.append("\n");
}
}
return buff.toString();
}
protected void importString(JComponent c, String str) {
target = (JTable)c;
DefaultTableModel model = (DefaultTableModel)target.getModel();
int index = target.getSelectedRow();
//Prevent the user from dropping data back on itself.
//For example, if the user is moving rows #4,#5,#6 and #7 and
//attempts to insert the rows after row #5, this would
//be problematic when removing the original rows.
//So this is not allowed.
if (rows != null && index >= rows[0] - 1 &&
index <= rows[rows.length - 1]) {
rows = null;
return;
}
int max = model.getRowCount();
if (index < 0) {
index = max;
} else {
index++;
if (index > max) {
index = max;
}
}
addIndex = index;
String[] values = str.split("\n");
addCount = values.length;
int colCount = target.getColumnCount();
for (int ndx = 0; ndx < values.length ; ndx++) {
model.insertRow(index++, values[ndx].split(","));
}
//If we are moving items around in the same table, we
//need to adjust the rows accordingly, since those
//after the insertion point have moved.
if (rows!= null && addCount > 0) {
for (int ndx = 0; ndx < rows.length; ndx++) {
if (rows[ndx] > addIndex) {
rows[ndx] += addCount;
}
}
}
}
protected void cleanup(JComponent c, boolean remove) {
JTable source = (JTable)c;
if (remove && rows != null) {
DefaultTableModel model =
(DefaultTableModel)source.getModel();
for (int ndx = rows.length - 1; ndx >= 0; ndx--) {
model.removeRow(rows[ndx]);
}
}
rows = null;
addCount = 0;
addIndex = -1;
}
}
class ViewportTransferHandler extends TransferHandler {
private JComponent getView(JComponent comp) {
JViewport viewport = (JViewport) comp;
return (JComponent) viewport.getView();
}
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
JComponent view = getView(comp);
return view.getTransferHandler().canImport(view, transferFlavors);
}
public void exportAsDrag(JComponent comp, InputEvent e, int action) {
JComponent view = getView(comp);
view.getTransferHandler().exportAsDrag(view, e, action);
}
public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
JComponent view = getView(comp);
view.getTransferHandler().exportToClipboard(view, clip, action);
}
public int getSourceActions(JComponent c) {
JComponent view = getView(c);
return view.getTransferHandler().getSourceActions(view);
}
public boolean importData(JComponent comp, Transferable t) {
JComponent view = getView(comp);
return view.getTransferHandler().importData(view, t);
}
}
Thanks for your help
spoertsch