Чтобы ячейка могла отображаться за ее пределами, необходимо реализовать класс TableUI.
В основном вам нужно самим покрасить клетки. Код немного длинный, но определенно работает для меня.
Чтобы решить эту проблему, создайте новый класс MyTableUI, расширьте javax.swing.plaf.basic.BasicTableUI, перезапишите его метод paint ().
Полный код ниже, вы можете скопировать его в Ide и запустить его.
package me.chenyi.table;
import javax.swing.*;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.*;
import java.awt.*;
public class MyBasicTableUI extends BasicTableUI
{
@Override
public void paint(Graphics g, JComponent c)
{
super.paint(g, c);
Rectangle clip = g.getClipBounds();
Rectangle bounds = table.getBounds();
// account for the fact that the graphics has already been translated
// into the table's bounds
bounds.x = bounds.y = 0;
//just do not want to copy too much code from BasicTableUI, so comment out following code.
//code from BasicTableUI comment out begin
// if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
// // this check prevents us from painting the entire table
// // when the clip doesn't intersect our bounds at all
// !bounds.intersects(clip)) {
//
// paintDropLines(g);
// return;
// }
//code from BasicTableUI comment out end
boolean ltr = table.getComponentOrientation().isLeftToRight();
Point upperLeft = clip.getLocation();
if(!ltr)
{
upperLeft.x++;
}
Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
clip.y + clip.height);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
// This should never happen (as long as our bounds intersect the clip,
// which is why we bail above if that is the case).
if(rMin == -1)
{
rMin = 0;
}
// If the table does not have enough rows to fill the view we'll get -1.
// (We could also get -1 if our bounds don't intersect the clip,
// which is why we bail above if that is the case).
// Replace this with the index of the last row.
if(rMax == -1)
{
rMax = table.getRowCount() - 1;
}
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
if(cMin == -1)
{
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if(cMax == -1)
{
cMax = table.getColumnCount() - 1;
}
paintCells(g, rMin, rMax, cMin, cMax);
}
private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax)
{
JTableHeader header = table.getTableHeader();
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
TableColumnModel cm = table.getColumnModel();
int columnMargin = cm.getColumnMargin();
Rectangle cellRect;
TableColumn aColumn;
int columnWidth;
if(table.getComponentOrientation().isLeftToRight())
{
for(int row = rMin; row <= rMax; row++)
{
//code from BasicTableUI comment out begin
// cellRect = table.getCellRect(row, cMin, false);
// for(int column = cMin; column <= cMax; column++)
// {
// aColumn = cm.getColumn(column);
// columnWidth = aColumn.getWidth();
// cellRect.width = columnWidth - columnMargin;
// if(aColumn != draggedColumn)
// {
// paintCell(g, cellRect, row, column);
// }
// cellRect.x += columnWidth;
// }
//code from BasicTableUI end
//code written by sean begin
cellRect = table.getCellRect(row, cMax, false);
int maxWidth = 0;
for(int column = cMax; column >= cMin; column--)
{
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
maxWidth += cellRect.width;
if(aColumn != draggedColumn)
{
paintCell(g, cellRect, row, column, maxWidth);
}
cellRect.x -= columnWidth;
if (table.getValueAt(row, column) != null)
{
maxWidth = 0;
}
}
//code written by sean end
}
}
else
{
for(int row = rMin; row <= rMax; row++)
{
cellRect = table.getCellRect(row, cMin, false);
aColumn = cm.getColumn(cMin);
if(aColumn != draggedColumn)
{
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
paintCell(g, cellRect, row, cMin);
}
for(int column = cMin + 1; column <= cMax; column++)
{
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
cellRect.x -= columnWidth;
if(aColumn != draggedColumn)
{
paintCell(g, cellRect, row, column);
}
}
}
}
//just do not want to copy too much code from BasicTableUI, so comment out following code.
//code from BasicTableUI comment out begin
// Paint the dragged column if we are dragging.
// if(draggedColumn != null)
// {
// paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
// }
//code from BasicTableUI comment out end
// Remove any renderers that may be left in the rendererPane.
rendererPane.removeAll();
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column)
{
paintCell(g, cellRect, row, column, -1);
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column,
/** sean's modification begin**/
int maxWidth
/** sean's modification end**/)
{
if(table.isEditing() && table.getEditingRow() == row &&
table.getEditingColumn() == column)
{
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else
{
//code from BasicTableUI begin
// TableCellRenderer renderer = table.getCellRenderer(row, column);
// Component component = table.prepareRenderer(renderer, row, column);
// rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
// cellRect.width, cellRect.height, true);
//code from BasicTableUI end
//code written by sean begin
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
int width = cellRect.width;
int height = cellRect.height;
Dimension preferredSize = component.getPreferredSize();
if(preferredSize != null && preferredSize.getWidth() != 0 && preferredSize.getHeight() != 0)
{
if(maxWidth > 0)
width = Math.min(preferredSize.width, maxWidth);
else
width = preferredSize.width;
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
width, height, true);
//code written by sean end
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
DefaultTableModel tableModel = new DefaultTableModel(2, 4);
tableModel.setValueAt("1234567890abcdefg1234567890abcdefg90abcdefg1234567890abcdefg90abcdefg1234567890abcdefg90abcdefg1234567890abcdefg", 0, 0);
// tableModel.setValueAt("xyz", 0, 1);//try to uncomment to see the difference
final JTable table = new JTable(tableModel);
final Font font = new Font("Arial", Font.PLAIN, 12);
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus,
int row, int column)
{
Component tableCellRendererComponent =
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(tableCellRendererComponent instanceof JLabel)
{
JLabel label = (JLabel)tableCellRendererComponent;
if(hasFocus && value != null)
{
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
int width = metrics.stringWidth((String)value) + 20;
label.setPreferredSize(new Dimension(width, metrics.getHeight()));
// label.setBorder(BorderFactory.createLineBorder(Color.red));
}
else
{
label.setPreferredSize(null);
}
// label.setText("_______________");
}
return tableCellRendererComponent;
}
});
table.setUI(new MyBasicTableUI());
frame.getContentPane().add(table, BorderLayout.CENTER);
frame.setSize(600, 800);
frame.setVisible(true);
}
}
и скриншот ниже. Еще нужно настроить код, сделать рисование лучше, но в любом случае это верный способ реализовать то, что вы хотите.