Preciso mesclar algumas linhas e colunas numa JTable ou outro componente (caso exista), montando um layout semelhante ao elaborado facilmente no excel, depois preciso calcular cada célula individualmente.
Meu objetivo é apresentar o resultado de cálculos estatísticos, gerados a partir da base de dados.
Algum dos amigos poderia me dar algumas dicas?
Você pode fazer isso na hora de puxar do banco, ao invés de colocar só uma coluna, você coloca duas, três ou mais. E na hora de fazer a soma você faz individualmente.
Exemplo de mesclar,
Ao invés disso:
tabela.add("Nome"), tabela.add("Sobrenome")...
Vc faz:
tabela.add("Nome"+ " " + "Sobrenome")...
Isso dá um trabalho do cão.
Existe um exmplo na seguinte página: http://www.java2s.com/Code/Java/Swing-Components/MultiSpanCellTableExample.htm, entretanto ele tem um bug de StackOverflowError
.
Abaixo tenho o mesmo código do link acima, mas sem causar StackOverflowError
Classe executável:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.UIManager;
public class Exemplo {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
MultiSpanCellTableExample example = new MultiSpanCellTableExample();
example.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
example.setVisible(true);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Os fontes do exemplo em si:
// Example from http://www.java2s.com/Code/Java/Swing-Components/MultiSpanCellTableExample.htm
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/**
* @version 1.0 11/26/98
*/
public class MultiSpanCellTableExample extends JFrame {
MultiSpanCellTableExample() {
super("Multi-Span Cell Example");
AttributiveCellTableModel ml = new AttributiveCellTableModel(10, 6);
/*
* AttributiveCellTableModel ml = new AttributiveCellTableModel(10,6) { public Object getValueAt(int row, int col) { return "" + row + ","+ col; } };
*/
final CellSpan cellAtt = (CellSpan) ml.getCellAttribute();
final MultiSpanCellTable table = new MultiSpanCellTable(ml);
JScrollPane scroll = new JScrollPane(table);
JButton b_one = new JButton("Combine");
b_one.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
cellAtt.combine(rows, columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
JButton b_split = new JButton("Split");
b_split.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int column = table.getSelectedColumn();
int row = table.getSelectedRow();
cellAtt.split(row, column);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
JPanel p_buttons = new JPanel();
p_buttons.setLayout(new GridLayout(2, 1));
p_buttons.add(b_one);
p_buttons.add(b_split);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(p_buttons);
getContentPane().add(box);
setSize(400, 200);
}
}
/**
* @version 1.0 11/22/98
*/
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector) null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
@Override
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null) {
throw new IllegalArgumentException("setDataVector() - Null parameter");
}
dataVector = new Vector(0);
columnIdentifiers = columnNames;
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(),
columnIdentifiers.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
@Override
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null) {
throw new IllegalArgumentException("addColumn() - null parameter");
}
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration eeration = dataVector.elements();
while (eeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size())) {
value = columnData.elementAt(index);
} else {
value = null;
}
((Vector) eeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
@Override
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount() - 1, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
@Override
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns) ||
(newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
* public void changeCellAttribute(int row, int column, Object command) { cellAtt.changeAttribute(row, column, command); }
*
* public void changeCellAttribute(int[] rows, int[] columns, Object command) { cellAtt.changeAttribute(rows, columns, command); }
*/
}
/**
* @version 1.0 11/22/98
*/
class DefaultCellAttribute
// implements CellAttribute ,CellSpan {
implements CellAttribute, CellSpan, ColoredCell, CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1, 1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for (int i = 0; i < span.length; i++) {
for (int j = 0; j < span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
@Override
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = { 1, 1 };
return ret_code;
}
return span[row][column];
}
@Override
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column)) {
return;
}
this.span[row][column] = span;
}
@Override
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column)) {
return false;
}
if ((span[row][column][CellSpan.COLUMN] < 1)
|| (span[row][column][CellSpan.ROW] < 1)) {
return false;
}
return true;
}
@Override
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) {
return;
}
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
// System.out.println("can't combine");
return;
}
}
}
for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
// System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
@Override
public void split(int row, int column) {
if (isOutOfBounds(row, column)) {
return;
}
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
span[row + i][column + j][CellSpan.COLUMN] = 1;
span[row + i][column + j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
@Override
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column)) {
return null;
}
return foreground[row][column];
}
@Override
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column)) {
return;
}
foreground[row][column] = color;
}
@Override
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) {
return;
}
setValues(foreground, color, rows, columns);
}
@Override
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column)) {
return null;
}
return background[row][column];
}
@Override
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column)) {
return;
}
background[row][column] = color;
}
@Override
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) {
return;
}
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
@Override
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column)) {
return null;
}
return font[row][column];
}
@Override
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column)) {
return;
}
this.font[row][column] = font;
}
@Override
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) {
return;
}
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
@Override
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numRows; i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
@Override
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numColumns; i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
@Override
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan, 0, span, 0, row - 1);
}
System.arraycopy(oldSpan, 0, span, row, numRows - row);
for (int i = 0; i < numColumns; i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
@Override
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
@Override
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
* public void changeAttribute(int row, int column, Object command) { }
*
* public void changeAttribute(int[] rows, int[] columns, Object command) { }
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0) || (rowSize <= row)
|| (column < 0) || (columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
if ((rows[i] < 0) || (rowSize <= rows[i])) {
return true;
}
}
for (int i = 0; i < columns.length; i++) {
if ((columns[i] < 0) || (columnSize <= columns[i])) {
return true;
}
}
return false;
}
protected void setValues(Object[][] target, Object value,
int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/26/98
*/
class MultiSpanCellTable extends JTable {
public MultiSpanCellTable(TableModel model) {
super(model);
setUI(new MultiSpanCellTableUI());
getTableHeader().setReorderingAllowed(false);
setCellSelectionEnabled(true);
setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
@Override
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle sRect = super.getCellRect(row, column, includeSpacing);
if ((row < 0) || (column < 0) ||
(getRowCount() <= row) || (getColumnCount() <= column)) {
return sRect;
}
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel()).getCellAttribute();
if (!cellAtt.isVisible(row, column)) {
int temp_row = row;
int temp_column = column;
row += cellAtt.getSpan(temp_row, temp_column)[CellSpan.ROW];
column += cellAtt.getSpan(temp_row, temp_column)[CellSpan.COLUMN];
}
int[] n = cellAtt.getSpan(row, column);
int index = 0;
int columnMargin = getColumnModel().getColumnMargin();
Rectangle cellFrame = new Rectangle();
int aCellHeight = rowHeight + rowMargin;
cellFrame.y = row * aCellHeight;
cellFrame.height = n[CellSpan.ROW] * aCellHeight;
Enumeration eeration = getColumnModel().getColumns();
while (eeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn) eeration.nextElement();
cellFrame.width = aColumn.getWidth() + columnMargin;
if (index == column) {
break;
}
cellFrame.x += cellFrame.width;
index++;
}
for (int i = 0; i < n[CellSpan.COLUMN] - 1; i++) {
TableColumn aColumn = (TableColumn) eeration.nextElement();
cellFrame.width += aColumn.getWidth() + columnMargin;
}
if (!includeSpacing) {
Dimension spacing = getIntercellSpacing();
cellFrame.setBounds(cellFrame.x + spacing.width / 2,
cellFrame.y + spacing.height / 2,
cellFrame.width - spacing.width,
cellFrame.height - spacing.height);
}
return cellFrame;
}
private int[] rowColumnAtPoint(Point point) {
int[] retValue = { -1, -1 };
int row = point.y / (rowHeight + rowMargin);
if ((row < 0) || (getRowCount() <= row)) {
return retValue;
}
int column = getColumnModel().getColumnIndexAtX(point.x);
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel()).getCellAttribute();
if (cellAtt.isVisible(row, column)) {
retValue[CellSpan.COLUMN] = column;
retValue[CellSpan.ROW] = row;
return retValue;
}
retValue[CellSpan.COLUMN] = column + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
retValue[CellSpan.ROW] = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
return retValue;
}
@Override
public int rowAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.ROW];
}
@Override
public int columnAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.COLUMN];
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
repaint();
}
@Override
public void valueChanged(ListSelectionEvent e) {
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
repaint();
}
Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
int numCoumns = getColumnCount();
int index = firstIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
index = lastIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
}
}
/**
* @version 1.0 11/26/98
*/
class MultiSpanCellTableUI extends BasicTableUI {
@Override
public void paint(Graphics g, JComponent c) {
Rectangle oldClipBounds = g.getClipBounds();
Rectangle clipBounds = new Rectangle(oldClipBounds);
int tableWidth = table.getColumnModel().getTotalColumnWidth();
clipBounds.width = Math.min(clipBounds.width, tableWidth);
g.setClip(clipBounds);
int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
int lastIndex = table.getRowCount() - 1;
Rectangle rowRect = new Rectangle(0, 0,
tableWidth, table.getRowHeight() + table.getRowMargin());
rowRect.y = firstIndex * rowRect.height;
for (int index = firstIndex; index <= lastIndex; index++) {
if (rowRect.intersects(clipBounds)) {
// System.out.println(); // debug
// System.out.print("" + index +": "); // row
paintRow(g, index);
}
rowRect.y += rowRect.height;
}
g.setClip(oldClipBounds);
}
private void paintRow(Graphics g, int row) {
Rectangle rect = g.getClipBounds();
boolean drawn = false;
AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table.getModel();
CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute();
int numColumns = table.getColumnCount();
for (int column = 0; column < numColumns; column++) {
Rectangle cellRect = table.getCellRect(row, column, true);
int cellRow, cellColumn;
if (cellAtt.isVisible(row, column)) {
cellRow = row;
cellColumn = column;
// System.out.print(" "+column+" "); // debug
} else {
cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
cellColumn = column + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
// System.out.print(" ("+column+")"); // debug
}
if (cellRect.intersects(rect)) {
drawn = true;
paintCell(g, cellRect, cellRow, cellColumn);
} else {
if (drawn) {
break;
}
}
}
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
int spacingHeight = table.getRowMargin();
int spacingWidth = table.getColumnModel().getColumnMargin();
Color c = g.getColor();
g.setColor(table.getGridColor());
g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1, cellRect.height - 1);
g.setColor(c);
cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y + spacingHeight / 2,
cellRect.width - spacingWidth, cellRect.height - spacingHeight);
if (table.isEditing() && table.getEditingRow() == row &&
table.getEditingColumn() == column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
} else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null) {
rendererPane.add(component);
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
}
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
AHHHHHHHHH, são linhas e colunas, desculpa!! Não me atentei direito nisso
Entendo isso Staroski, no entanto pergunto, mas como numa linguagem tão avançada, temos que escrever tantas linhas de código…
Não é possível, tem que haver uma solução!