Hallo
Hoffe, das ist das richtige Forum für mein Problem.
Nachfolgend der Programmcode einer kleinen Server-Client-Applikation (Verwaltung von Pendenzen). Die App funktioniert im Wesentlichen ganz gut, allerdings gibt es ein paar Bugs, welche ich, auch nach mehrmaligem Durchsehen des Codes in Eclipse, noch nicht ausmerzen konnte. Hoffe, dass "mehr Augen" auch mehr sehen.
Zur App:
1. Sever starten (Server-Main-Methode)
2. Client starten (Client-Main-Methode, dies beliebig oft)
Mit einem Klick auf den Button "Pendenz hinzufügen" wird am Tabellenende eine neue leere Zeile (nur ID wird automatisch vergeben) hinzugefügt. In die Zellen "Datum" und "Beschreibung" (beide vom Datentyp String) können irgendein Datum und eine beliebige Beschreibung eingegeben werden. Die (neuen) Zeilen, in welchen die Zellen "Datum" und / oder "Beschreibung" mit irgendwelchem Inhalt beschrieben wurden, müssen, BEVOR man eine weitere Zeile hinzufügt, zuerst mittels Klick auf den Button "Pendenz speichern" gespeichert werden, sonst verschwinden die neuen Eingaben wieder. Dabei muss die entsprechende (neu befüllte) Zeile markiert sein. Man kann immer nur eine neue Zeile (mit Inhalt gefüllt) auf einmal speichern, nicht mehrere (Lösungsvorschläge, wie man dies verbessern kann, sind willkommen).
Eine mit der Maus markierte Zeile kann mit einem Klick auf den Button "Pendenz löschen" entfernt werden.
Der Button "Aktualisieren" wird eigentlich nur dann benötigt, wenn mehrere Clients gestartet wurden und die Eingaben in einer Client-Tabelle auf einer anderen sichtbar sein sollen.
Zu den Bugs:
In der 4 Spalte (Status) kann in einer Checkbox ein Haken gesetzt werden (symbolisiert, ob eine Pendenz erledigt ist oder nicht, hat sonst keine Funktion). Dies funktioniert aber nur dann, wenn ein Client neu gestartet wurde. Sobald einer der 4 Buttons geklickt wird, verschwindet die Checkboxen und es wird nur noch "true" oder "false" angezeigt (je nachdem, ob die Checkbox gehäkelt wurde oder eben nicht). Wird ein neuer Client gestartet, sind die Checkboxen wieder da. Warum? Wo muss ich was ändern, damit dies nicht mehr passiert?
Wenn ein Client neu gestartet wird, dann hat die JTable die "korrekten" vordefinierten Spaltenbreiten. Sobald ein Button geklickt wird, werden aber wieder alle Spalten mit "default"-Breiten dargestellt. Warum? Wo muss ich was ändern, damit dies nicht mehr passiert?
Für Hilfen wäre ich sehr dankbar. Ich bin absolut KEIN Profi, nicht mal ein Fortgeschrittener, würde mich immer noch als blutigen Anfänger bezeichnen. Habe den Code nur mit der Hilfe von div. Tutorials, Büchern, etc. zusammengebastelt.
Gruss
Hier nun der Programmcode:
Hoffe, das ist das richtige Forum für mein Problem.
Nachfolgend der Programmcode einer kleinen Server-Client-Applikation (Verwaltung von Pendenzen). Die App funktioniert im Wesentlichen ganz gut, allerdings gibt es ein paar Bugs, welche ich, auch nach mehrmaligem Durchsehen des Codes in Eclipse, noch nicht ausmerzen konnte. Hoffe, dass "mehr Augen" auch mehr sehen.
Zur App:
1. Sever starten (Server-Main-Methode)
2. Client starten (Client-Main-Methode, dies beliebig oft)
Mit einem Klick auf den Button "Pendenz hinzufügen" wird am Tabellenende eine neue leere Zeile (nur ID wird automatisch vergeben) hinzugefügt. In die Zellen "Datum" und "Beschreibung" (beide vom Datentyp String) können irgendein Datum und eine beliebige Beschreibung eingegeben werden. Die (neuen) Zeilen, in welchen die Zellen "Datum" und / oder "Beschreibung" mit irgendwelchem Inhalt beschrieben wurden, müssen, BEVOR man eine weitere Zeile hinzufügt, zuerst mittels Klick auf den Button "Pendenz speichern" gespeichert werden, sonst verschwinden die neuen Eingaben wieder. Dabei muss die entsprechende (neu befüllte) Zeile markiert sein. Man kann immer nur eine neue Zeile (mit Inhalt gefüllt) auf einmal speichern, nicht mehrere (Lösungsvorschläge, wie man dies verbessern kann, sind willkommen).
Eine mit der Maus markierte Zeile kann mit einem Klick auf den Button "Pendenz löschen" entfernt werden.
Der Button "Aktualisieren" wird eigentlich nur dann benötigt, wenn mehrere Clients gestartet wurden und die Eingaben in einer Client-Tabelle auf einer anderen sichtbar sein sollen.
Zu den Bugs:
In der 4 Spalte (Status) kann in einer Checkbox ein Haken gesetzt werden (symbolisiert, ob eine Pendenz erledigt ist oder nicht, hat sonst keine Funktion). Dies funktioniert aber nur dann, wenn ein Client neu gestartet wurde. Sobald einer der 4 Buttons geklickt wird, verschwindet die Checkboxen und es wird nur noch "true" oder "false" angezeigt (je nachdem, ob die Checkbox gehäkelt wurde oder eben nicht). Wird ein neuer Client gestartet, sind die Checkboxen wieder da. Warum? Wo muss ich was ändern, damit dies nicht mehr passiert?
Wenn ein Client neu gestartet wird, dann hat die JTable die "korrekten" vordefinierten Spaltenbreiten. Sobald ein Button geklickt wird, werden aber wieder alle Spalten mit "default"-Breiten dargestellt. Warum? Wo muss ich was ändern, damit dies nicht mehr passiert?
Für Hilfen wäre ich sehr dankbar. Ich bin absolut KEIN Profi, nicht mal ein Fortgeschrittener, würde mich immer noch als blutigen Anfänger bezeichnen. Habe den Code nur mit der Hilfe von div. Tutorials, Büchern, etc. zusammengebastelt.
Gruss
Hier nun der Programmcode:
Java:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.text.*;
// Server-Klasse
class Server
{
public static void main(String[] args)
{
System.out.println("Starte Server...");
try
{
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
}
catch(RemoteException ex)
{
System.out.println(ex.getMessage());
}
try
{
CounterImpl myCounter = new CounterImpl();
Naming.rebind("Counter", myCounter);
}
catch(Exception e)
{
System.err.println("Exception: " + e.getMessage());
}
System.out.println("Server gestartet.");
}
}
// Client-Klasse
class Client
{
public static void main(String[] args)
{
String serverName = "127.0.0.1";
System.out.println("Starte Client....");
try
{
Counter myCounter = (Counter) Naming.lookup("rmi://" + serverName + "/Counter");
GUI gui = new GUI(serverName, myCounter);
gui.setVisible(true);
}
catch(Exception e)
{
System.err.println("Exception (Client): " + e.getMessage());
}
System.out.println("Client gestartet.");
}
}
class Issue implements Serializable
{
private int i;
private String date;
private String description;
private boolean status;
public Issue(int i)
{
this.setID(i);
}
public Issue(int i, String date, String description, boolean status)
{
this.setID(i);
this.setDate(date);
this.setDescription(description);
this.setStatus(status);
}
public int getID()
{
return i;
}
public void setID(int i)
{
this.i = i;
}
public String getDate()
{
return date;
}
public void setDate(String date)
{
this.date = date;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Boolean getStatus()
{
return status;
}
public void setStatus(Boolean status)
{
this.status = status;
}
}
// Pendenzen-Tabelle
class IssuesTableModel extends AbstractTableModel implements Serializable
{
private ArrayList<Issue> issues = new ArrayList<Issue>();
private int i;
@Override
public int getColumnCount()
{
return 4;
}
@Override
public int getRowCount()
{
return issues.size();
}
@Override
public String getColumnName(int colNumber)
{
switch (colNumber)
{
case 0: return "ID";
case 1: return "Datum";
case 2: return "Beschreibung";
case 3: return "Status";
default:
assert false : "Wrong colNumber " + colNumber;
return null;
}
}
@Override
public Object getValueAt(int rowNumber, int colNumber)
{
Issue issue = issues.get(rowNumber);
switch (colNumber)
{
case 0: return issue.getID();
case 1: return issue.getDate();
case 2: return issue.getDescription();
case 3: return issue.getStatus();
default:
assert false : "Wrong colNumber " + colNumber;
return null;
}
}
@Override
public void setValueAt(Object value, int rowNumber, int colNumber)
{
Issue issue = issues.get(rowNumber);
switch (colNumber)
{
case 1:
issue.setDate((String) value);
break;
case 2:
issue.setDescription((String) value);
break;
case 3:
issue.setStatus((Boolean) value);
break;
default:
assert false : "Wrong colNumber " + colNumber;
}
}
@Override
public boolean isCellEditable(int rowNumber, int colNumber)
{
if (colNumber == 4)
{
return false;
}
return true;
}
public void addIssue()
{
issues.add(new Issue(i++));
int newRowNumber = issues.size();
super.fireTableRowsInserted(newRowNumber, newRowNumber);
}
public void updateIssueAtID(Issue changeIssue)
{
if (changeIssue.getID() >= 0)
{
updateIssueAt(searchRowNumberByID(changeIssue.getID()), changeIssue);
}
}
public void updateIssueAt(int rowNumber, Issue changeIssue)
{
if (rowNumber >= 0 && rowNumber < issues.size())
{
issues.set(rowNumber, changeIssue);
}
}
public void delIssueAtID(int rowID)
{
if (rowID >= 0)
{
delIssueAt(searchRowNumberByID(rowID));
}
}
public void delIssueAt(int rowNumber)
{
if (rowNumber >= 0 && rowNumber < issues.size())
{
issues.remove(rowNumber);
super.fireTableRowsDeleted(rowNumber, rowNumber);
}
}
public int searchRowNumberByID(int rowID)
{
for(int i=0; i < issues.size(); i++)
{
if (issues.get(i).getID() == rowID)
{
return i;
}
}
return -1;
}
public void refresh(int rowNumber)
{
if (rowNumber >= 0 && rowNumber < issues.size())
{
//issues.refresh(rowNumber);
//super.fireTableRowsDeleted(rowNumber, rowNumber);
}
}
}
interface Counter extends Remote
{
public IssuesTableModel addIssue() throws RemoteException;
public IssuesTableModel getModel() throws RemoteException;
public void updateIssueAtID(Issue changeIssue) throws RemoteException;
public void delIssueAtID(int rowID) throws RemoteException;
}
@SuppressWarnings("serial")
class CounterImpl extends UnicastRemoteObject implements Counter
{
private IssuesTableModel issueslist = null;
public CounterImpl() throws RemoteException
{
this.issueslist = new IssuesTableModel();
System.out.println("wenn kein Eintrag, dann addIssue");
this.addIssue();
}
@Override
public synchronized IssuesTableModel getModel() throws RemoteException
{
System.out.println("Methode getModelPendenz() returns " + this.issueslist);
return this.issueslist;
}
@Override
public synchronized IssuesTableModel addIssue() throws RemoteException
{
System.out.println("Methode addIssue() returns " + this.issueslist);
issueslist.addIssue();
return this.issueslist;
}
@Override
public synchronized void updateIssueAtID(Issue changeIssue) throws RemoteException
{
System.out.println("Methode updateIssueAtID() returns " + this.issueslist.getRowCount());
this.issueslist.updateIssueAtID(changeIssue);
}
@Override
public synchronized void delIssueAtID(int rowID) throws RemoteException
{
System.out.println("Methode delIssueAtID() returns " + this.issueslist.getRowCount());
this.issueslist.delIssueAtID(rowID);
}
}
@SuppressWarnings("serial")
class GUI extends JPanel implements ActionListener
{
private Counter model = null;
private JButton addIssue;
private JButton safeIssue;
private JButton delIssue;
private JButton refresh;
JTable table;
JCheckBox checkStat;
public GUI(String serverName, Counter myCounter)
{
this.model = myCounter;
try
{
table = new JTable(this.model.getModel());
}
catch(RemoteException e)
{
}
table.getColumn("Status").setCellRenderer(new BooleanCellRenderer());
table.getColumn("Status").setCellEditor(new BooleanCellEditor());
JFrame frame = new JFrame("Pendenzenverwaltung");
JPanel buttons = new JPanel(new GridLayout(0, 1));
buttons.add(genButtonAdd());
buttons.add(genButtonSaf());
buttons.add(genButtonDel());
buttons.add(genButtonRef());
Container content = frame.getContentPane();
content.add(new JScrollPane(table), BorderLayout.CENTER);
content.add(buttons, BorderLayout.SOUTH);
table.getColumnModel().getColumn(0).setPreferredWidth(20);
table.getColumnModel().getColumn(1).setPreferredWidth(80);
table.getColumnModel().getColumn(2).setPreferredWidth(400);
table.getColumnModel().getColumn(3).setPreferredWidth(20);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private JButton genButtonAdd()
{
this.addIssue = new JButton("Pendenz hinzufügen");
addIssue.addActionListener(this);
return addIssue;
}
private JButton genButtonSaf()
{
this.safeIssue = new JButton("Pendenz speichern");
safeIssue.addActionListener(this);
return safeIssue;
}
private JButton genButtonDel()
{
this.delIssue = new JButton("Pendenz löschen");
delIssue.addActionListener(this);
return delIssue;
}
private JButton genButtonRef()
{
this.refresh = new JButton("Aktualisieren");
refresh.addActionListener(this);
return refresh;
}
public void actionPerformed(ActionEvent event)
{
String varAction = event.getActionCommand();
System.out.println("action = " + event.getActionCommand());
int index = table.getSelectedRow();
if(varAction =="Pendenz hinzufügen")
{
try
{
table.setModel(this.model.addIssue());
System.out.println(this.table.getRowCount());
}
catch(RemoteException e)
{
}
}
else if(varAction == "Pendenz speichern")
{
table.editCellAt(index, 2);
table.getCellEditor().stopCellEditing();
try
{
Issue changeIssue = new Issue(Integer.valueOf(table.getValueAt(index, 0).toString()),
table.getValueAt(index, 1).toString(),
table.getValueAt(index, 2).toString(),
Boolean.valueOf(table.getValueAt(index, 3).toString()));
if (table.getValueAt(index, 2) == null)
{
changeIssue.setDescription(" ");
}
else
{
changeIssue.setDescription(table.getValueAt(index, 2).toString());
}
System.out.println(changeIssue.getDescription() + " " + changeIssue.getID());
model.updateIssueAtID(changeIssue);
}
catch(RemoteException e)
{
}
}
else if(varAction == "Pendenz löschen")
{
if (index >= 0)
{
try
{
model.delIssueAtID(Integer.valueOf(table.getValueAt(index, 0).toString()));
}
catch(RemoteException e)
{
}
}
}
try
{
table.setModel(this.model.getModel());
}
catch(RemoteException e)
{
}
}
class BooleanCellEditor extends DefaultCellEditor
{
public BooleanCellEditor()
{
super(new JCheckBox());
JCheckBox checkBox = (JCheckBox)getComponent();
checkBox.setHorizontalAlignment(JCheckBox.CENTER);
}
}
class BooleanCellRenderer extends JCheckBox implements TableCellRenderer
{
public BooleanCellRenderer()
{
super();
setHorizontalAlignment(JLabel.CENTER);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
if (isSelected)
{
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
}
else
{
setForeground(table.getForeground());
setBackground(UIManager.getColor("Checkbox.background"));
}
setSelected((value != null && ((Boolean)value).booleanValue()));
return this;
}
}
}