Estoy usando una segunda JTable en la ventana gráfica de un JScrollPane para construir un RowHeader para una tabla principal. DragAndDrop en la tabla principal está deshabilitado. En la tabla de encabezado de fila, DnD está habilitado.
Si el usuario inicia un Arrastrar en el encabezado de fila, quiero extender la línea desplegable del encabezado de fila pintado (la línea negra en la imagen) sobre la tabla principal (como la línea verde en la imagen).
¿Alguien tiene algún consejo para mí?
Aquí está el SSCCE:
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
public class DNDLinePainterExampleMain extends JFrame {
public DNDLinePainterExampleMain() {
JTable mainTable = new JTable(4, 3);
mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JTable rowTable = new RowHeaderTable(mainTable);
rowTable.setAutoscrolls(true);
rowTable.setDragEnabled(true);
rowTable.setTransferHandler(new RowHeaderTransferHandler());
rowTable.setDropMode(DropMode.INSERT_ROWS);
JScrollPane scrollPane = new JScrollPane(mainTable);
scrollPane.setRowHeaderView(rowTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER,
rowTable.getTableHeader());
this.add(scrollPane);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new DNDLinePainterExampleMain();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
/*
* Use a JTable as a renderer for row numbers of a given main table. This
* table must be added to the row header of the scrollpane that contains the
* main table. from:
* http://tips4java.wordpress.com/2008/11/18/row-number-table/
*/
public class RowHeaderTable extends JTable implements ChangeListener,
PropertyChangeListener {
private final JTable table;
public RowHeaderTable(JTable table) {
this.table = table;
table.addPropertyChangeListener(this);
setFocusable(false);
setAutoCreateColumnsFromModel(false);
updateRowHeight();
updateModel();
updateSelectionModel();
TableColumn column = new TableColumn();
column.setHeaderValue("");
addColumn(column);
column.setCellRenderer(new RowNumberRenderer());
getColumnModel().getColumn(0).setPreferredWidth(50);
setPreferredScrollableViewportSize(getPreferredSize());
getTableHeader().setReorderingAllowed(false);
}
@Override
public void addNotify() {
super.addNotify();
Component c = getParent();
// Keep scrolling of the row table in sync with the main table.
if (c instanceof JViewport) {
JViewport viewport = (JViewport) c;
viewport.addChangeListener(this);
}
}
/*
* Delegate method to main table
*/
@Override
public int getRowCount() {
return table.getRowCount();
}
@Override
public int getRowHeight(int row) {
return table.getRowHeight(row);
}
/*
* This table does not use any data from the main TableModel, so just return
* a value based on the row parameter.
*/
@Override
public Object getValueAt(int row, int column) {
return Integer.toString(row + 1);
}
/*
* Don't edit data in the main TableModel by mistake
*/
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
// implements ChangeListener
@Override
public void stateChanged(ChangeEvent e) {
// Keep the scrolling of the row table in sync with main table
JViewport viewport = (JViewport) e.getSource();
JScrollPane scrollPane = (JScrollPane) viewport.getParent();
scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
}
// implements PropertyChangeListener
@Override
public void propertyChange(PropertyChangeEvent e) {
// Keep the row table in sync with the main table
if ("rowHeight".equals(e.getPropertyName()))
updateRowHeight();
if ("selectionModel".equals(e.getPropertyName()))
updateSelectionModel();
if ("model".equals(e.getPropertyName()))
updateModel();
}
private void updateRowHeight() {
setRowHeight(table.getRowHeight());
}
private void updateModel() {
setModel(table.getModel());
}
private void updateSelectionModel() {
setSelectionModel(table.getSelectionModel());
}
/*
* Borrow the renderer from JDK1.4.2 table header
*/
private class RowNumberRenderer extends DefaultTableCellRenderer {
public RowNumberRenderer() {
setHorizontalAlignment(JLabel.CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
if (isSelected) {
setFont(getFont().deriveFont(Font.BOLD));
}
setText((value == null) ? "" : value.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}//class RowNumberRenderer
}//class RowHeaderTable
public class RowHeaderTransferHandler extends TransferHandler {
@Override
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
@Override
protected Transferable createTransferable(JComponent c) {
return new StringSelection(c.getName());
}
@Override
public boolean canImport(TransferSupport supp) {
return true;
}
}//class RowHeaderTransferHandler
}//class DNDLinePainterExampleMain
Te sugiero que hagas esto (usando la funcionalidad de arrastrar y soltar de Swing):
RowHeaderTable rowTable = new RowHeaderTable(mainTable);
rowTable.setAutoscrolls(true);
rowTable.setDragEnabled(true);
rowTable.setTransferHandler(new RowHeaderTransferHandler(mainTable));
rowTable.setDropMode(DropMode.INSERT_ROWS);
try {
DropTarget dropTarget = rowTable.getDropTarget();
dropTarget.addDropTargetListener(rowTable);
}
catch(TooManyListenersException e) {
e.printStackTrace();
}
Ahora tienes que implementar DropTargetListener
:
public class RowHeaderTable extends JTable implements ChangeListener, PropertyChangeListener, DropTargetListener {
Estos son 2 métodos que deberían interesarle:
@Override
public void dragEnter(DropTargetDragEvent dtde) { shouldPaint = true }
@Override
public void dragExit(DropTargetEvent dte) { shouldPaint = false }
Ahora debes manipular tu mainTable
(para pintar esta "línea verde") usando tu TranserHandler:
@Override
public boolean canImport(TransferSupport supp) {
DropLocation location = supp.getDropLocation();
if(location instanceof javax.swing.JTable.DropLocation && shouldPaint) {
javax.swing.JTable.DropLocation tableLocation = (javax.swing.JTable.DropLocation) location;
int rowToInsert = tableLocation.getRow();
//paint somehow the "green line"
//remember that canImport is invoked when you move your mouse
}
return true;
}
Básicamente, debe implementar su propio renderizador de filas o algo similar (como en la respuesta de @naugler). De alguna manera también debería proporcionar boolean shouldPaint
a su TransferHandler. Pero esto no es gran cosa de implementar.
Espero que esto ayude.
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras