Senin, 13 Juli 2026

JAVA MVC 3

java swing gui jtable sample model view controller book title and author database in one package and save as csv file

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)

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.

Java
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.

Java
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.

Java
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)

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

  1. Save all files in a folder structure matching the package, like ./bookapp/Main.java, ./bookapp/BookModel.java, etc.

  2. Open your terminal at the root directory (the folder containing bookapp).

  3. Compile all files:

Tidak ada komentar: