Gemini said
Here is a complete, lightweight Java Swing CRUD application implementing the Model-View-Controller (MVC) design pattern.
This implementation handles a database of books (Title and Author) and persists the data directly to a CSV file (books.csv). For simplicity and to meet your requirement, all classes are designed to sit within the same package.
Project Structure
Since everything is in one package (e.g., com.bookapp), you will create four files:
Book.java(The Data Model)BookRepository.java(The CSV Database Handler)BookView.java(The Swing GUI View)BookController.java(The Controller / Main Entry)
1. The Model (Book.java)
This represents a single book entity.
package com.bookapp;
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
}
2. The File Handler (BookRepository.java)
This class manages reading from and writing to the CSV file.
package com.bookapp;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class BookRepository {
private final String csvFile = "books.csv";
// Load books from CSV
public List<Book> loadBooks() {
List<Book> books = new ArrayList<>();
File file = new File(csvFile);
if (!file.exists()) return books; // Return empty list if file doesn't exist yet
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
String[] data = line.split(",");
if (data.length >= 2) {
// Escape commas if necessary, but keeping it simple here
books.add(new Book(data[0].trim(), data[1].trim()));
}
}
} catch (IOException e) {
e.printStackTrace();
}
return books;
}
// Save books to CSV
public void saveBooks(List<Book> books) {
try (PrintWriter pw = new PrintWriter(new FileWriter(csvFile))) {
for (Book book : books) {
pw.println(book.getTitle() + "," + book.getAuthor());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. The View (BookView.java)
This handles the GUI layout. It exposes UI components and data to the controller via methods so that it doesn't handle business logic itself.
package com.bookapp;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionListener;
public class BookView extends JFrame {
private JTextField txtTitle = new JTextField(15);
private JTextField txtAuthor = new JTextField(15);
private JButton btnCreate = new JButton("Add");
private JButton btnUpdate = new JButton("Update");
private JButton btnDelete = new JButton("Delete");
private JButton btnClear = new JButton("Clear");
private JTable table = new JTable();
private DefaultTableModel tableModel = new DefaultTableModel(new Object[]{"Title", "Author"}, 0);
public BookView() {
setTitle("Book CRUD Manager (MVC)");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
table.setModel(tableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Input Panel
JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
inputPanel.add(new JLabel("Title:"));
inputPanel.add(txtTitle);
inputPanel.add(new JLabel("Author:"));
inputPanel.add(txtAuthor);
// Buttons Panel
JPanel buttonPanel = new JPanel();
buttonPanel.add(btnCreate);
buttonPanel.add(btnUpdate);
buttonPanel.add(btnDelete);
buttonPanel.add(btnClear);
// Top Area combining Inputs and Buttons
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
topPanel.add(inputPanel, BorderLayout.CENTER);
topPanel.add(buttonPanel, BorderLayout.SOUTH);
// Main Layout
setLayout(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(new JScrollPane(table), BorderLayout.CENTER);
}
// Getters and Helper Methods for Controller
public String getBookTitle() { return txtTitle.getText().trim(); }
public String getBookAuthor() { return txtAuthor.getText().trim(); }
public void setInputs(String title, String author) {
txtTitle.setText(title);
txtAuthor.setText(author);
}
public int getSelectedRow() { return table.getSelectedRow(); }
public DefaultTableModel getTableModel() { return tableModel; }
public JTable getTable() { return table; }
public void clearInputs() {
txtTitle.setText("");
txtAuthor.setText("");
table.clearSelection();
}
// Listeners registrations
public void addCreateListener(ActionListener l) { btnCreate.addActionListener(l); }
public void addUpdateListener(ActionListener l) { btnUpdate.addActionListener(l); }
public void addDeleteListener(ActionListener l) { btnDelete.addActionListener(l); }
public void addClearListener(ActionListener l) { btnClear.addActionListener(l); }
}
4. The Controller & Main Application (BookController.java)
The brains of the operation. It syncs the BookRepository (Model/Data) with the BookView (UI) and handles all user interactions.
package com.bookapp;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import java.util.List;
public class BookController {
private BookView view;
private BookRepository repository;
private List<Book> bookList; // Runtime memory cache of our data
public BookController(BookView view, BookRepository repository) {
this.view = view;
this.repository = repository;
this.bookList = repository.loadBooks();
// Populate View table initially
updateTable();
// Wire up listeners
this.view.addCreateListener(e -> handleCreate());
this.view.addUpdateListener(e -> handleUpdate());
this.view.addDeleteListener(e -> handleDelete());
this.view.addClearListener(e -> view.clearInputs());
// Table row selection syncs back to input fields
this.view.getTable().getSelectionModel().addListSelectionListener(e -> {
int selectedRow = view.getSelectedRow();
if (selectedRow != -1) {
String title = view.getTableModel().getValueAt(selectedRow, 0).toString();
String author = view.getTableModel().getValueAt(selectedRow, 1).toString();
view.setInputs(title, author);
}
});
}
private void updateTable() {
DefaultTableModel model = view.getTableModel();
model.setRowCount(0); // Clear table view
for (Book book : bookList) {
model.addRow(new Object[]{book.getTitle(), book.getAuthor()});
}
}
private void handleCreate() {
String title = view.getBookTitle();
String author = view.getBookAuthor();
if (title.isEmpty() || author.isEmpty()) {
JOptionPane.showMessageDialog(view, "Fields cannot be empty!");
return;
}
bookList.add(new Book(title, author));
repository.saveBooks(bookList);
updateTable();
view.clearInputs();
}
private void handleUpdate() {
int selectedRow = view.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(view, "Select a book to update.");
return;
}
String title = view.getBookTitle();
String author = view.getBookAuthor();
if (title.isEmpty() || author.isEmpty()) {
JOptionPane.showMessageDialog(view, "Fields cannot be empty!");
return;
}
// Update runtime list and save to CSV
Book book = bookList.get(selectedRow);
book.setTitle(title);
book.setAuthor(author);
repository.saveBooks(bookList);
updateTable();
view.clearInputs();
}
private void handleDelete() {
int selectedRow = view.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(view, "Select a book to delete.");
return;
}
bookList.remove(selectedRow);
repository.saveBooks(bookList);
updateTable();
view.clearInputs();
}
// MAIN ENTRY POINT
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
BookView view = new BookView();
BookRepository repository = new BookRepository();
new BookController(view, repository);
view.setVisible(true);
});
}
}
How to Run it:
Put all 4 files into a directory folder named
com/bookapp(matching the package structure).
Tidak ada komentar:
Posting Komentar