java 1

 avatar
unknown
java
14 days ago
13 kB
5
Indexable
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExpenseTracker {

    private JFrame frame;
    private JTabbedPane tabbedPane;
    private JTable spendingTable, transactionTable;
    private DefaultTableModel spendingModel, transactionModel;
    private JLabel totalExpenseLabel, balanceLabel, savingsLabel;
    private HashMap<String, String> spendingData;
    private List<Object[]> transactionHistory;
    private String income = "0.0";
    private String currentUser = null;

    private static final String DATA_FILE_PREFIX = "expense_data_"; // Prefix to save per user data file

    public ExpenseTracker() {
        spendingData = new HashMap<>();
        transactionHistory = new ArrayList<>();
        showLoginDialog();
    }

    private void showLoginDialog() {
        JPanel loginPanel = new JPanel();
        loginPanel.setLayout(new BoxLayout(loginPanel, BoxLayout.Y_AXIS));

        JTextField usernameField = new JTextField(15);
        JPasswordField passwordField = new JPasswordField(15);
        JButton loginButton = new JButton("Login");
        JButton registerButton = new JButton("Register");

        loginPanel.add(new JLabel("Username:"));
        loginPanel.add(usernameField);
        loginPanel.add(new JLabel("Password:"));
        loginPanel.add(passwordField);
        loginPanel.add(loginButton);
        loginPanel.add(registerButton);

        loginButton.addActionListener(e -> {
            String username = usernameField.getText().trim();
            String password = new String(passwordField.getPassword()).trim();
            if (username.isEmpty() || password.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "Please enter both username and password.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            if (login(username, password)) {
                currentUser = username;
                loadData();
                initialize();
                JOptionPane.showMessageDialog(frame, "Login successful!");
                frame.setVisible(true);
            } else {
                JOptionPane.showMessageDialog(frame, "Invalid credentials", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        registerButton.addActionListener(e -> {
            String username = usernameField.getText().trim();
            String password = new String(passwordField.getPassword()).trim();
            if (username.isEmpty() || password.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "Please enter both username and password.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            if (register(username, password)) {
                JOptionPane.showMessageDialog(frame, "Registration successful!");
            } else {
                JOptionPane.showMessageDialog(frame, "Username already taken", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        frame = new JFrame("Login");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.add(loginPanel);
        frame.setLocationRelativeTo(null); // Center the frame on the screen
        frame.setVisible(true);
    }

    private boolean login(String username, String password) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_data.dat"))) {
            HashMap<String, String> userData = (HashMap<String, String>) ois.readObject();
            return userData.containsKey(username) && userData.get(username).equals(password);
        } catch (IOException | ClassNotFoundException e) {
            return false; // Error in loading data, assuming user doesn't exist
        }
    }

    private boolean register(String username, String password) {
        HashMap<String, String> userData;
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_data.dat"))) {
            userData = (HashMap<String, String>) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            userData = new HashMap<>();
        }

        if (userData.containsKey(username)) {
            return false;
        }

        userData.put(username, password);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user_data.dat"))) {
            oos.writeObject(userData);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    private void initialize() {
        frame = new JFrame("Expense Tracker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);

        tabbedPane = new JTabbedPane();

        // Spending Tab
        JPanel spendingPanel = new JPanel(new BorderLayout());
        spendingModel = new DefaultTableModel(new String[]{"Category", "Amount"}, 0);
        spendingTable = new JTable(spendingModel);
        updateSpendingTable();
        spendingPanel.add(new JScrollPane(spendingTable), BorderLayout.CENTER);

        JPanel summaryPanel = new JPanel(new GridLayout(4, 1)); // Adjusted layout
        totalExpenseLabel = new JLabel();
        balanceLabel = new JLabel();
        savingsLabel = new JLabel();
        JButton logoutButton = new JButton("Logout");
        logoutButton.addActionListener(e -> logout()); // Logout functionality
        updateSummaryLabels();
        summaryPanel.add(totalExpenseLabel);
        summaryPanel.add(balanceLabel);
        summaryPanel.add(savingsLabel);
        summaryPanel.add(logoutButton); // Add logout button
        spendingPanel.add(summaryPanel, BorderLayout.NORTH);

        JPanel spendingButtons = new JPanel();
        JButton addIncomeButton = new JButton("+ Income");
        addIncomeButton.addActionListener(e -> addIncome());
        JButton addExpenseButton = new JButton("+ Expense");
        addExpenseButton.addActionListener(e -> addExpense());
        spendingButtons.add(addIncomeButton);
        spendingButtons.add(addExpenseButton);
        spendingPanel.add(spendingButtons, BorderLayout.SOUTH);

        tabbedPane.add("Spending", spendingPanel);

        // Transaction Tab
        JPanel transactionPanel = new JPanel(new BorderLayout());
        transactionModel = new DefaultTableModel(new String[]{"Category", "Date", "Amount"}, 0);
        transactionTable = new JTable(transactionModel);
        loadTransactionHistory();
        transactionPanel.add(new JScrollPane(transactionTable), BorderLayout.CENTER);

        JButton deleteTransactionButton = new JButton("Delete");
        deleteTransactionButton.addActionListener(e -> deleteTransaction());
        transactionPanel.add(deleteTransactionButton, BorderLayout.SOUTH);

        tabbedPane.add("Transaction", transactionPanel);

        // Graph Tab
        JPanel graphPanel = new JPanel(new BorderLayout());
        JButton refreshGraphButton = new JButton("Refresh Graph");
        refreshGraphButton.addActionListener(e -> updateGraph(graphPanel));
        graphPanel.add(refreshGraphButton, BorderLayout.NORTH);
        updateGraph(graphPanel); // Ensure graph updates initially
        tabbedPane.add("Graph", graphPanel);

        frame.add(tabbedPane);
        frame.setVisible(true);
    }

    private void logout() {
        int confirm = JOptionPane.showConfirmDialog(frame, "Are you sure you want to log out?", "Logout", JOptionPane.YES_NO_OPTION);
        if (confirm == JOptionPane.YES_OPTION) {
            frame.dispose();
            currentUser = null;
            showLoginDialog();
        }
    }

    private void addIncome() {
        String incomeStr = JOptionPane.showInputDialog(frame, "Enter income amount:");
        try {
            double amount = Double.parseDouble(incomeStr);
            income = String.valueOf(Double.parseDouble(income) + amount);
            updateSummaryLabels();
            saveData();
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(frame, "Invalid amount.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void addExpense() {
        String category = JOptionPane.showInputDialog(frame, "Enter category:");
        String amountStr = JOptionPane.showInputDialog(frame, "Enter amount:");
        try {
            double amount = Double.parseDouble(amountStr);
            spendingData.put(category, String.valueOf(Double.parseDouble(spendingData.getOrDefault(category, "0.0")) + amount));
            Object[] transaction = {category, java.time.LocalDate.now().toString(), amountStr};
            transactionHistory.add(transaction);
            transactionModel.addRow(transaction);
            updateSpendingTable();
            updateSummaryLabels();
            saveData();
            updateGraph((JPanel) tabbedPane.getComponentAt(2)); // Automatically refresh graph after adding expense
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(frame, "Invalid amount.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void deleteTransaction() {
        int selectedRow = transactionTable.getSelectedRow();
        if (selectedRow >= 0) {
            String category = (String) transactionModel.getValueAt(selectedRow, 0);
            String amountStr = (String) transactionModel.getValueAt(selectedRow, 2);
            spendingData.put(category, String.valueOf(Double.parseDouble(spendingData.getOrDefault(category, "0.0")) - Double.parseDouble(amountStr)));
            transactionHistory.remove(selectedRow);
            transactionModel.removeRow(selectedRow);
            updateSpendingTable();
            updateSummaryLabels();
            saveData();
            updateGraph((JPanel) tabbedPane.getComponentAt(2)); // Automatically refresh graph after deletion
        } else {
            JOptionPane.showMessageDialog(frame, "Select a transaction to delete.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void updateSpendingTable() {
        spendingModel.setRowCount(0);
        for (Map.Entry<String, String> entry : spendingData.entrySet()) {
            spendingModel.addRow(new Object[]{entry.getKey(), entry.getValue()});
        }
    }

    private void updateSummaryLabels() {
        DecimalFormat df = new DecimalFormat("0.00");
        double totalExpense = spendingData.values().stream().mapToDouble(value -> Double.parseDouble(value)).sum();
        double balance = Double.parseDouble(income) - totalExpense;
        double savings = balance > 0 ? balance : 0;

        totalExpenseLabel.setText("Total Expense: $" + df.format(totalExpense));
        balanceLabel.setText("Balance: $" + df.format(balance));
        savingsLabel.setText("Total Savings: $" + df.format(savings));
    }

    private void updateGraph(JPanel graphPanel) {
        DefaultPieDataset dataset = new DefaultPieDataset();
        for (Map.Entry<String, String> entry : spendingData.entrySet()) {
            dataset.setValue(entry.getKey(), Double.parseDouble(entry.getValue()));
        }

        JFreeChart chart = ChartFactory.createPieChart("Spending Chart", dataset, true, true, false);
        ChartPanel chartPanel = new ChartPanel(chart);

        graphPanel.removeAll();
        graphPanel.add(chartPanel, BorderLayout.CENTER);
        graphPanel.revalidate();
        graphPanel.repaint();
    }

    private void saveData() {
        String dataFileName = DATA_FILE_PREFIX + currentUser + ".dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(dataFileName))) {
            oos.writeObject(spendingData);
            oos.writeObject(income);
            oos.writeObject(transactionHistory);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadData() {
        String dataFileName = DATA_FILE_PREFIX + currentUser + ".dat";
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(dataFileName))) {
            spendingData = (HashMap<String, String>) ois.readObject();
            income = (String) ois.readObject();
            transactionHistory = (List<Object[]>) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            spendingData = new HashMap<>();
            income = "0.0";
            transactionHistory = new ArrayList<>();
        }
    }

    private void loadTransactionHistory() {
        transactionModel.setRowCount(0);
        for (Object[] transaction : transactionHistory) {
            transactionModel.addRow(transaction);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ExpenseTracker::new);
    }
}
Leave a Comment