Gemini said
Here is a complete, self-contained Java Swing application demonstrating the Model-View-Controller (MVC) pattern. It manages a simple Book database (Title and Author), displays it in a JTable, and includes a button to save the data to a CSV file.
All classes are structured to sit within a single package (bookapp).
The Architecture Breakdown
Model (
Book&BookModel): Holds the data and handles the logic (like saving to CSV).View (
BookView): Handles the UI layout (JFrame,JTable, inputs, and buttons).Controller (
BookController): The bridge. It listens for UI actions and updates the Model and View accordingly.
The Code
Create a directory named bookapp and place these five classes inside it.
1. The Data Object (Book.java)
package 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 String getAuthor() { return author; }
}
2. The Model (BookModel.java)
This manages the list of books and handles writing the data to a CSV file.
package bookapp;
import javax.swing.table.AbstractTableModel;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class BookModel extends AbstractTableModel {
private final List<Book> books;
private final String[] columnNames = {"Title", "Author"};
public BookModel() {
this.books = new ArrayList<>();
// Seed some sample data
books.add(new Book("The Hobbit", "J.R.R. Tolkien"));
books.add(new Book("184", "George Orwell"));
}
public void addBook(Book book) {
books.add(book);
// Notify the JTable that a new row has been inserted
fireTableRowsInserted(books.size() - 1, books.size() - 1);
}
public void saveToCSV(String filePath) throws IOException {
try (FileWriter writer = new FileWriter(filePath)) {
// Write Header
writer.write("Title,Author\n");
// Write Data
for (Book book : books) {
// Basic escaping for commas in titles/authors
String title = book.getTitle().contains(",") ? "\"" + book.getTitle() + "\"" : book.getTitle();
String author = book.getAuthor().contains(",") ? "\"" + book.getAuthor() + "\"" : book.getAuthor();
writer.write(title + "," + author + "\n");
}
}
}
// --- JTable Architecture Overrides ---
@Override
public int getRowCount() { return books.size(); }
@Override
public int getColumnCount() { return columnNames.length; }
@Override
public String getColumnName(int column) { return columnNames[column]; }
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Book book = books.get(rowIndex);
switch (columnIndex) {
case 0: return book.getTitle();
case 1: return book.getAuthor();
default: return null;
}
}
}
3. The View (BookView.java)
This builds the visual interface. Notice that it doesn't contain logic; it provides methods so the Controller can grab data or hook up button listeners.
package bookapp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class BookView extends JFrame {
private JTable table;
private JTextField txtTitle;
private JTextField txtAuthor;
private JButton btnAdd;
private JButton btnSave;
public BookView(BookModel model) {
setTitle("Book Database (MVC)");
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// Components
table = new JTable(model);
txtTitle = new JTextField(15);
txtAuthor = new JTextField(15);
btnAdd = new JButton("Add Book");
btnSave = new JButton("Save to CSV");
// Layout: Input Panel
JPanel inputPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0; gbc.gridy = 0; inputPanel.add(new JLabel("Title:"), gbc);
gbc.gridx = 1; inputPanel.add(txtTitle, gbc);
gbc.gridx = 0; gbc.gridy = 1; inputPanel.add(new JLabel("Author:"), gbc);
gbc.gridx = 1; inputPanel.add(txtAuthor, gbc);
JPanel buttonPanel = new JPanel();
buttonPanel.add(btnAdd);
buttonPanel.add(btnSave);
gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 2;
inputPanel.add(buttonPanel, gbc);
// Main Layout Assembly
setLayout(new BorderLayout());
add(new JScrollPane(table), BorderLayout.CENTER);
add(inputPanel, BorderLayout.SOUTH);
}
// Getters for data entry
public String getBookTitle() { return txtTitle.getText().trim(); }
public String getBookAuthor() { return txtAuthor.getText().trim(); }
public void clearInputs() {
txtTitle.setText("");
txtAuthor.setText("");
}
// Action listeners hooked up by the Controller
public void addAddBookListener(ActionListener listener) { btnAdd.addActionListener(listener); }
public void addSaveCSVListener(ActionListener listener) { btnSave.addActionListener(listener); }
}
4. The Controller (BookController.java)
This coordinates how the View reacts to user inputs and how it updates the Model.
package bookapp;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
public class BookController {
private BookModel model;
private BookView view;
public BookController(BookModel model, BookView view) {
this.model = model;
this.view = view;
// Attach listeners to the view
this.view.addAddBookListener(new AddBookListener());
this.view.addSaveCSVListener(new SaveCSVListener());
}
// Listener for adding books
class AddBookListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String title = view.getBookTitle();
String author = view.getBookAuthor();
if (title.isEmpty() || author.isEmpty()) {
JOptionPane.showMessageDialog(view, "Please fill in both fields.", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
model.addBook(new Book(title, author));
view.clearInputs();
}
}
// Listener for saving to CSV
class SaveCSVListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Save Database as CSV");
int userSelection = fileChooser.showSaveDialog(view);
if (userSelection == JFileChooser.APPROVE_OPTION) {
String filePath = fileChooser.getSelectedFile().getAbsolutePath();
// Ensure it ends with .csv
if (!filePath.toLowerCase().endsWith(".csv")) {
filePath += ".csv";
}
try {
model.saveToCSV(filePath);
JOptionPane.showMessageDialog(view, "Database saved successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(view, "Error saving file: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
}
5. The Application Entry Point (Main.java)
package bookapp;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] args) {
// Run UI code on the Event Dispatch Thread (EDT)
SwingUtilities.invokeLater(() -> {
BookModel model = new BookModel();
BookView view = new BookView(model);
// The controller wires them together
new BookController(model, view);
view.setVisible(true);
});
}
}
How to Compile and Run
Save all files in a folder structure matching the package, like
./bookapp/Main.java,./bookapp/BookModel.java, etc.Open your terminal at the root directory (the folder containing
bookapp).Compile all files:
Tidak ada komentar:
Posting Komentar