Hallo zusammen,
ich hänge zur Zeit an einer privaten Applikation um meine Finanzen zu verwalten. Das ganze soll als Übung für mich dienen.
Ich bin aber generell mit einigen Dingen im Design irgendwie unzufrieden bzw. finde diese relativ kompliziert. Aus diesem Grunde frage ich hier erneut nach einigen Tipps & Tricks, was ich am bisher bestehenden noch ändern kann.
Am schlimmsten/komischten finde ich es eigentlich, dass man bestimmte GUI Elemente, sowie den Controller/Persistenzmanager durch die gesamte Applikation durchreichen muss.
Vorneweg sei gesagt, dass die Codeauszüge relativ groß sind.
Main, startet die Applikation mit Erzeugung von GUI und meiner Persistenzlösung. Denke hier kann man nicht viel anders machen.
Das Account Model. Implementiert Observable um die GUI benachrichtigen zu können. Denke das sollte auch noch alles in Ordnung sein.
Interface für die Persistenz/Controller Schicht.
Implementierung der Persistenz/Controller Schicht. Ist das so ok oder entspricht das nicht wirklich einem "guten" Controller?
Die Hauptgui. Ganz normale initialisierung mit einer JMenuBar und einer JTabbedPane zur Anzeige der Accounts. Ist das so noch ok oder sind hier bereits größere Fehler dabei?
Das Menü zum hinzufügen und löschen von Accounts. Hier stört mich, dass ich sowohl die JTabbedPane als auch den AccountManager brauche. Geht das hier auch anders? Ist es normal, dass die GUI Elemente sich untereinander kennen müssen um die GUI Funktionalität zu bewerkstelligen?
Und zum Abschluss ein einzelner Tab zur Anzeige eines Accounts. Mit dieser Implementierung bin ich eigentlich zufrieden.
Mit freundlichen Grüßen
Michael
ich hänge zur Zeit an einer privaten Applikation um meine Finanzen zu verwalten. Das ganze soll als Übung für mich dienen.
Ich bin aber generell mit einigen Dingen im Design irgendwie unzufrieden bzw. finde diese relativ kompliziert. Aus diesem Grunde frage ich hier erneut nach einigen Tipps & Tricks, was ich am bisher bestehenden noch ändern kann.
Am schlimmsten/komischten finde ich es eigentlich, dass man bestimmte GUI Elemente, sowie den Controller/Persistenzmanager durch die gesamte Applikation durchreichen muss.
Vorneweg sei gesagt, dass die Codeauszüge relativ groß sind.
Main, startet die Applikation mit Erzeugung von GUI und meiner Persistenzlösung. Denke hier kann man nicht viel anders machen.
Code:
package de.vitz.jfinancemanager2;
import javax.swing.SwingUtilities;
import de.vitz.jfinancemanager2.controller.HashAccountManager;
import de.vitz.jfinancemanager2.view.GUI;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GUI(new HashAccountManager());
}
});
}
}
Das Account Model. Implementiert Observable um die GUI benachrichtigen zu können. Denke das sollte auch noch alles in Ordnung sein.
Code:
package de.vitz.jfinancemanager2.model;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
public class Account extends Observable {
private String name;
private double amount;
public Account(String name) {
super();
this.name = name;
amount = 0;
}
public String getName() {
return name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
setChanged();
notifiyObservers();
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj.getClass().equals(Account.class)) {
if (((Account) obj).getName().equals(name)) {
return true;
}
}
return false;
}
}
Interface für die Persistenz/Controller Schicht.
Code:
package de.vitz.jfinancemanager2.controller;
import de.vitz.jfinancemanager2.model.Account;
public interface IAccountManager {
public Account createAccount(String name);
public boolean removeAccount(String name);
}
Implementierung der Persistenz/Controller Schicht. Ist das so ok oder entspricht das nicht wirklich einem "guten" Controller?
Code:
package de.vitz.jfinancemanager2.controller;
import java.util.LinkedList;
import java.util.List;
import de.vitz.jfinancemanager2.model.Account;
public class HashAccountManager implements IAccountManager {
private List<Account> accounts;
public HashAccountManager() {
accounts = new LinkedList<Account>();
}
@Override
public Account createAccount(String name) {
Account account = new Account(name);
if (accounts.contains(account)) {
throw new RuntimeException("Account exists.");
}
accounts.add(account);
return account;
}
@Override
public boolean removeAccount(String name) {
Account account = new Account(name);
if (accounts.contains(account)) {
accounts.remove(account);
return true;
} else {
return false;
}
}
}
Die Hauptgui. Ganz normale initialisierung mit einer JMenuBar und einer JTabbedPane zur Anzeige der Accounts. Ist das so noch ok oder sind hier bereits größere Fehler dabei?
Code:
package de.vitz.jfinancemanager2.view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JTabbedPane;
import de.vitz.jfinancemanager2.controller.IAccountManager;
import de.vitz.jfinancemanager2.view.menu.AccountMenu;
public class GUI extends JFrame {
private static final long serialVersionUID = 1L;
private IAccountManager accountManager;
private JTabbedPane accountPane;
public GUI(IAccountManager accountManager) {
// initialize
super("jFinanceManager2");
this.accountManager = accountManager;
accountPane = new JTabbedPane();
// basic properties
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setMinimumSize(new Dimension(400, 200));
// add components
setJMenuBar(menuBar());
add(accountPane, BorderLayout.CENTER);
// show frame
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private JMenuBar menuBar() {
JMenuBar menuBar = new JMenuBar();
menuBar.add(new AccountMenu(accountPane, accountManager));
return menuBar;
}
}
Das Menü zum hinzufügen und löschen von Accounts. Hier stört mich, dass ich sowohl die JTabbedPane als auch den AccountManager brauche. Geht das hier auch anders? Ist es normal, dass die GUI Elemente sich untereinander kennen müssen um die GUI Funktionalität zu bewerkstelligen?
Code:
package de.vitz.jfinancemanager2.view.menu;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import de.vitz.jfinancemanager2.controller.IAccountManager;
import de.vitz.jfinancemanager2.view.account.AccountTab;
public class AccountMenu extends JMenu {
private static final long serialVersionUID = 1L;
private IAccountManager accountManager;
private JTabbedPane accountTabs;
public AccountMenu(JTabbedPane accountTabs, IAccountManager accountManager) {
super("Accounts");
this.accountManager = accountManager;
this.accountTabs = accountTabs;
add(addAccountItem());
add(removeAccountItem());
}
public JMenuItem addAccountItem() {
final String title = "Add account.";
JMenuItem item = new JMenuItem(title);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String accountName = JOptionPane.showInputDialog(null,
"Add an account!", title, JOptionPane.DEFAULT_OPTION);
if (accountName != null && !accountName.equals("")) {
accountTabs.add(new AccountTab(accountManager
.createAccount(accountName)));
}
}
});
return item;
}
public JMenuItem removeAccountItem() {
final String title = "Remove account.";
JMenuItem item = new JMenuItem(title);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Component component = accountTabs.getSelectedComponent();
if (component != null
&& accountManager.removeAccount(component.getName())) {
accountTabs.remove(component);
}
}
});
return item;
}
}
Und zum Abschluss ein einzelner Tab zur Anzeige eines Accounts. Mit dieser Implementierung bin ich eigentlich zufrieden.
Code:
package de.vitz.jfinancemanager2.view.account;
import java.awt.BorderLayout;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JLabel;
import javax.swing.JPanel;
import de.vitz.jfinancemanager2.model.Account;
public class AccountTab extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private Account account;
private JLabel amountLabel;
public AccountTab(Account account) {
super(new BorderLayout());
this.account = account;
this.account.addObserver(this);
setName(account.getName());
add(header(), BorderLayout.NORTH);
}
private JPanel header() {
JLabel heading = new JLabel(account.getName());
amountLabel = new JLabel(account.getAmount() + "");
JButton button = new JButton("Amountchange");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
account.setAmount(account.getAmount() + 10);
}
});
JPanel panel = new JPanel(new BorderLayout());
panel.add(heading, BorderLayout.NORTH);
panel.add(amountLabel, BorderLayout.CENTER);
panel.add(button, BorderLayout.SOUTH);
return panel;
}
@Override
public void update(Observable o, Object arg) {
amountLabel.setText(account.getAmount() + "");
}
}
Mit freundlichen Grüßen
Michael