Are you ready to take control of your finances and learn Java in the process? Today, Iβm going to walk you through creating a Personal Budget Manager desktop application using Java Swing and File I/O β and yes, it’s beginner-friendly, but powerful enough to impress your friends or ace that portfolio project. π
Letβs dive into how you can build this app from scratch, with every line of code explained.
π§ What Youβll Learn:
- Java OOP design
- GUI with Java Swing
- File I/O for persistent data
- Budget calculations
- Error handling and clean code practices
π Project Structure:
com.budgetmanager
β
βββ BudgetManager.java // GUI & main entry point
βββ Transaction.java // Represents each entry
βββ BudgetService.java // Business logic
βββ FileManager.java // File read/write
βββ data/
βββ budget_data.csv // Saved transaction data
β Features:
- Add income and expenses
- Categorize transactions
- View total income, expenses, and remaining balance
- Save/load data from a CSV file
π Step-by-Step Code (With Explanations)
1οΈβ£ Transaction.java
: Model Class
import java.time.LocalDate;
public class Transaction {
private String type; // Income or Expense
private String category;
private double amount;
private LocalDate date;
public Transaction(String type, String category, double amount, LocalDate date) {
this.type = type;
this.category = category;
this.amount = amount;
this.date = date;
}
public String getType() { return type; }
public String getCategory() { return category; }
public double getAmount() { return amount; }
public LocalDate getDate() { return date; }
@Override
public String toString() {
return type + "," + category + "," + amount + "," + date;
}
}
π‘ Explanation: This class represents one budget entry, storing its type (income/expense), category, amount, and date.
2οΈβ£ BudgetService.java
: Budget Logic
import java.util.ArrayList;
import java.util.List;
public class BudgetService {
private List<Transaction> transactions = new ArrayList<>();
public void addTransaction(Transaction t) {
transactions.add(t);
}
public double getTotalIncome() {
return transactions.stream()
.filter(t -> t.getType().equalsIgnoreCase("Income"))
.mapToDouble(Transaction::getAmount).sum();
}
public double getTotalExpense() {
return transactions.stream()
.filter(t -> t.getType().equalsIgnoreCase("Expense"))
.mapToDouble(Transaction::getAmount).sum();
}
public double getRemainingBudget() {
return getTotalIncome() - getTotalExpense();
}
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
}
π‘ Explanation: Core service to manage and calculate the totals for income, expenses, and balance.
3οΈβ£ FileManager.java
: Data Persistence
import java.io.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class FileManager {
private static final String FILE_PATH = "data/budget_data.csv";
public static void save(List<Transaction> transactions) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_PATH));
for (Transaction t : transactions) {
writer.write(t.toString());
writer.newLine();
}
writer.close();
}
public static List<Transaction> load() throws IOException {
List<Transaction> transactions = new ArrayList<>();
File file = new File(FILE_PATH);
if (!file.exists()) return transactions;
BufferedReader reader = new BufferedReader(new FileReader(FILE_PATH));
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
Transaction t = new Transaction(
parts[0],
parts[1],
Double.parseDouble(parts[2]),
LocalDate.parse(parts[3])
);
transactions.add(t);
}
reader.close();
return transactions;
}
}
π‘ Explanation: Reads and writes all transactions to a CSV file. Automatically creates an empty list if the file doesnβt exist.
4οΈβ£ BudgetManager.java
: Main GUI App
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.*;
import java.time.LocalDate;
import java.util.List;
public class BudgetManager extends JFrame {
private BudgetService budgetService = new BudgetService();
private DefaultTableModel tableModel;
public BudgetManager() {
setTitle("Java Budget Manager");
setSize(700, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
initComponents();
loadExistingData();
}
private void initComponents() {
JPanel inputPanel = new JPanel(new GridLayout(2, 5, 10, 10));
String[] types = { "Income", "Expense" };
JComboBox<String> typeBox = new JComboBox<>(types);
JTextField categoryField = new JTextField();
JTextField amountField = new JTextField();
JTextField dateField = new JTextField(LocalDate.now().toString());
JButton addButton = new JButton("Add Transaction");
inputPanel.add(new JLabel("Type"));
inputPanel.add(new JLabel("Category"));
inputPanel.add(new JLabel("Amount"));
inputPanel.add(new JLabel("Date (YYYY-MM-DD)"));
inputPanel.add(new JLabel("")); // Spacer
inputPanel.add(typeBox);
inputPanel.add(categoryField);
inputPanel.add(amountField);
inputPanel.add(dateField);
inputPanel.add(addButton);
add(inputPanel, BorderLayout.NORTH);
String[] columns = { "Type", "Category", "Amount", "Date" };
tableModel = new DefaultTableModel(columns, 0);
JTable table = new JTable(tableModel);
add(new JScrollPane(table), BorderLayout.CENTER);
JLabel summaryLabel = new JLabel();
updateSummary(summaryLabel);
add(summaryLabel, BorderLayout.SOUTH);
addButton.addActionListener(e -> {
try {
String type = typeBox.getSelectedItem().toString();
String category = categoryField.getText();
double amount = Double.parseDouble(amountField.getText());
LocalDate date = LocalDate.parse(dateField.getText());
Transaction t = new Transaction(type, category, amount, date);
budgetService.addTransaction(t);
tableModel.addRow(new Object[]{ type, category, amount, date });
updateSummary(summaryLabel);
FileManager.save(budgetService.getTransactions());
categoryField.setText("");
amountField.setText("");
dateField.setText(LocalDate.now().toString());
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Invalid input. Please check your values.");
}
});
}
private void loadExistingData() {
try {
List<Transaction> transactions = FileManager.load();
budgetService.setTransactions(transactions);
for (Transaction t : transactions) {
tableModel.addRow(new Object[]{ t.getType(), t.getCategory(), t.getAmount(), t.getDate() });
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateSummary(JLabel summaryLabel) {
double income = budgetService.getTotalIncome();
double expense = budgetService.getTotalExpense();
double remaining = budgetService.getRemainingBudget();
summaryLabel.setText("π° Total Income: βΉ" + income +
" | πΈ Total Expenses: βΉ" + expense +
" | πΌ Remaining: βΉ" + remaining);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new BudgetManager().setVisible(true));
}
}
π‘ Explanation:
- Builds the main app window
- Takes user input for new transactions
- Displays all transactions in a table
- Shows a real-time summary of income, expense, and balance
π Bonus Idea:
Want to go next level? Add:
- A pie chart to visualize expenses by category (with JFreeChart)
- Export as PDF/Excel
- Monthly budget reports
- Cloud sync using Firebase or MySQL
π― Final Thoughts
This app may be simple, but it covers everything: OOP, GUI, file handling, and real-world problem-solving. If you’re learning Java or building a portfolio, this project is perfect.
π Like the project?
Subscribe to my blog for more Java + Spring Boot tutorials!
Share it with your friends!
Leave a comment below if youβd like me to add graphing support π