# Advanced JTable with Row Buttons and Images
Here's a comprehensive guide to creating a JTable with buttons in each row and image display capabilities.
## Complete Example with Row Buttons and Images
```java
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
public class AdvancedJTableExample extends JFrame {
private PersonTableModel tableModel;
private JTable table;
public AdvancedJTableExample() {
setTitle("Advanced JTable Example");
setSize(800, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// Create sample data
List<Person> persons = new ArrayList<>();
persons.add(new Person("John Doe", 30, "john@example.com", "images/user1.png"));
persons.add(new Person("Jane Smith", 25, "jane@example.com", "images/user2.png"));
persons.add(new Person("Bob Johnson", 40, "bob@example.com", "images/user3.png"));
// Create custom table model
tableModel = new PersonTableModel(persons);
table = new JTable(tableModel);
// Set custom renderer and editor for buttons
table.getColumn("Action").setCellRenderer(new ButtonRenderer());
table.getColumn("Action").setCellEditor(new ButtonEditor(new JCheckBox()));
// Set custom renderer for images
table.getColumn("Photo").setCellRenderer(new ImageRenderer());
// Make rows taller to accommodate images
table.setRowHeight(60);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
// Add button to add new person
JButton addButton = new JButton("Add New Person");
addButton.addActionListener(e -> {
persons.add(new Person("New Person", 0, "new@example.com", "images/default.png"));
tableModel.fireTableDataChanged();
});
add(addButton, BorderLayout.SOUTH);
}
// Custom TableModel
class PersonTableModel extends AbstractTableModel {
private List<Person> persons;
private String[] columns = {"Photo", "Name", "Age", "Email", "Action"};
public PersonTableModel(List<Person> persons) {
this.persons = persons;
}
@Override
public int getRowCount() {
return persons.size();
}
@Override
public int getColumnCount() {
return columns.length;
}
@Override
public String getColumnName(int column) {
return columns[column];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Person person = persons.get(rowIndex);
switch (columnIndex) {
case 0: return person.getPhotoPath();
case 1: return person.getName();
case 2: return person.getAge();
case 3: return person.getEmail();
case 4: return "Delete";
default: return null;
}
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) return ImageIcon.class;
if (columnIndex == 4) return JButton.class;
return Object.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 4; // Only the button column is editable
}
}
// Person data class
class Person {
private String name;
private int age;
private String email;
private String photoPath;
public Person(String name, int age, String email, String photoPath) {
this.name = name;
this.age = age;
this.email = email;
this.photoPath = photoPath;
}
// Getters and setters
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
public String getPhotoPath() { return photoPath; }
}
// Button renderer
class ButtonRenderer extends DefaultTableCellRenderer {
private JButton button;
public ButtonRenderer() {
button = new JButton();
button.setOpaque(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
button.setText((value == null) ? "" : value.toString());
return button;
}
}
// Button editor
class ButtonEditor extends DefaultCellEditor {
private JButton button;
private String label;
private boolean isPushed;
private int clickedRow;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
clickedRow = row;
return button;
}
@Override
public Object getCellEditorValue() {
if (isPushed) {
// Perform action when button is clicked
int choice = JOptionPane.showConfirmDialog(
AdvancedJTableExample.this,
"Delete " + tableModel.persons.get(clickedRow).getName() + "?",
"Confirm Delete",
JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION) {
tableModel.persons.remove(clickedRow);
tableModel.fireTableDataChanged();
}
}
isPushed = false;
return label;
}
@Override
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
}
// Image renderer
class ImageRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
String imagePath = (String) value;
ImageIcon icon = new ImageIcon(imagePath);
// Scale the image if needed
if (icon.getImage() != null) {
Image scaledImage = icon.getImage().getScaledInstance(
50, 50, Image.SCALE_SMOOTH);
icon = new ImageIcon(scaledImage);
}
setIcon(icon);
setText("");
setHorizontalAlignment(JLabel.CENTER);
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return this;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new AdvancedJTableExample().setVisible(true);
});
}
}
```
## Key Features Explained
### 1. Images in Table Cells
- **ImageRenderer class**: Custom renderer that displays images in cells
- **Image scaling**: Images are scaled to fit the row height
- **Handling missing images**: The renderer will show nothing if image path is invalid
### 2. Buttons in Table Cells
- **ButtonRenderer class**: Displays buttons in cells
- **ButtonEditor class**: Handles button clicks with action confirmation
- **Row-specific actions**: The editor knows which row's button was clicked
### 3. Custom TableModel
- **PersonTableModel**: Extends AbstractTableModel for custom data handling
- **Column types**: Specifies different column types (ImageIcon, JButton)
- **Dynamic updates**: Fires events when data changes
### 4. Person Data Class
- Simple POJO to hold person data including image path
## How to Use This Example
1. **Image Preparation**:
- Create an "images" folder in your project directory
- Add some sample images (user1.png, user2.png, etc.)
- Or use a default image when none is available
2. **Adding New Rows**:
- The "Add New Person" button adds a new row with default values
- You can modify this to show a dialog for entering new person details
3. **Deleting Rows**:
- Clicking a "Delete" button shows a confirmation dialog
- Only removes the row if confirmed
## Advanced Customizations
### 1. Multiple Action Buttons
```java
// In PersonTableModel
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Person person = persons.get(rowIndex);
switch (columnIndex) {
case 0: return person.getPhotoPath();
case 1: return person.getName();
case 2: return person.getAge();
case 3: return person.getEmail();
case 4: return new String[]{"Edit", "Delete"}; // Array of buttons
default: return null;
}
}
// Then modify ButtonRenderer/Editor to handle multiple buttons
```
### 2. Dynamic Image Loading
```java
// In ImageRenderer
ImageIcon icon;
if (imagePath.startsWith("http")) {
// Load from URL
try {
URL url = new URL(imagePath);
icon = new ImageIcon(url);
} catch (Exception e) {
icon = new ImageIcon("images/default.png");
}
} else {
// Load from file
icon = new ImageIcon(imagePath);
}
```
### 3. Inline Editing
```java
// In PersonTableModel
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 4 || columnIndex == 1 || columnIndex == 2;
// Allow editing name and age columns too
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Person person = persons.get(rowIndex);
switch (columnIndex) {
case 1: person.setName((String)aValue); break;
case 2: person.setAge(Integer.parseInt(aValue.toString())); break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
```
This example provides a solid foundation for creating advanced JTables with images and row buttons. You can extend it further based on your specific requirements.
No comments:
Post a Comment