This question already has answers here:
Javafx tableview not showing data in all columns
(3 answers)
Why should I avoid using PropertyValueFactory in JavaFX?
(1 answer)
Closed 21 days ago.
I am trying to import a CSV file, set it to an ArrayList then populate a table using this data. I have a class setup where a user can open a CSV file then it's read and the contents are set using the setters which are below. My table is always empty but the studentData always gets printed out like com.example.project.CSV_Objects#4f591691
Below is my code:
#FXML
private TableView<CSV_Objects> tableView;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
TableColumn<CSV_Objects, String> studentNumberColumn = new TableColumn<>("Student Number");
studentNumberColumn.setCellValueFactory(new PropertyValueFactory<>("studentNumber"));
TableColumn<CSV_Objects, String> q1Column = new TableColumn<>("Question 1");
q1Column.setCellValueFactory(new PropertyValueFactory<>("q1"));
TableColumn<CSV_Objects, String> q2Column = new TableColumn<>("Question 2");
q2Column.setCellValueFactory(new PropertyValueFactory<>("q2"));
TableColumn<CSV_Objects, String> q3Column = new TableColumn<>("Question 3");
q3Column.setCellValueFactory(new PropertyValueFactory<>("q3"));
TableColumn<CSV_Objects, String> q4Column = new TableColumn<>("Question 4");
q4Column.setCellValueFactory(new PropertyValueFactory<>("q4"));
TableColumn<CSV_Objects, String> q5Column = new TableColumn<>("Question 5");
q5Column.setCellValueFactory(new PropertyValueFactory<>("q5"));
tableView.getColumns().setAll(studentNumberColumn, q1Column, q2Column, q3Column, q4Column, q5Column);
CSV_Objects csvObject = new CSV_Objects();
ObservableList<CSV_Objects> studentData = FXCollections.observableArrayList();
ArrayList<String> students = csvObject.getStudent();
System.out.println(csvObject.getStudent());
for (String student : students) {
studentData.add(new CSV_Objects(student));
}
tableView.setItems(studentData);
In my CSV_Objects class I have the getters and setters setup:
private static ArrayList<String> student = new ArrayList<>();
public void setStudent(ArrayList<String> student) {
this.student = student;
}
public ArrayList<String> getStudent() {
return student;
}
Any advice is greatly appreciated:)
It's not clear what is wrong with your code. There's too much missing. There's also an indication of not enough familiarity with how JavaFX's TableView works nor how to separate concerns in a non-trivial application. This answer does not directly address your code, but hopefully the example provided here can help you solve your problem(s).
That said, I believe part of the problem is that you're not separating the data from how the data is retrieved enough. I don't quite understand what your TableView is supposed to be displaying, but the fact your model is named CSV_Objects would seem to support my belief. You should set up your UI code to display a model regardless of where the instances come from, then later worry about reading the data from a CSV file.
For example, let's say you want a table to display a number of students, where each student has an ID, a name, and a "year" (freshman, sophomore, junior, or senior). You first create a Student class which encapsulates those properties.
Student.java:
package sample;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Student {
private final StringProperty id = new SimpleStringProperty(this, "id");
public final void setId(String id) { this.id.set(id); }
public final String getId() { return id.get(); }
public final StringProperty idProperty() { return id; }
private final StringProperty name = new SimpleStringProperty(this, "name");
public final void setName(String name) { this.name.set(name); }
public final String getName() { return name.get(); }
public final StringProperty nameProperty() { return name; }
private final ObjectProperty<Year> year = new SimpleObjectProperty<>(this, "year");
public final void setYear(Year year) { this.year.set(year); }
public final Year getYear() { return year.get(); }
public final ObjectProperty<Year> yearProperty() { return year; }
public Student() {}
public Student(String id, String name, Year year) {
setId(id);
setName(name);
setYear(year);
}
public enum Year {
FRESHMAN,
SOPHOMORE,
JUNIOR,
SENIOR
}
}
Note: JavaFX properties are used to make interacting with a TableView easier.
Then you set up TableView (FXML is used since you are also using FXML).
Controller.java:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class Controller {
#FXML private TableView<Student> studentTable;
#FXML private TableColumn<Student, String> idColumn;
#FXML private TableColumn<Student, String> nameColumn;
#FXML private TableColumn<Student, Student.Year> yearColumn;
#FXML
private void initialize() {
idColumn.setCellValueFactory(data -> data.getValue().idProperty());
nameColumn.setCellValueFactory(data -> data.getValue().nameProperty());
yearColumn.setCellValueFactory(data -> data.getValue().yearProperty());
// mock data for example
studentTable.getItems().addAll(
new Student("1", "John Smith", Student.Year.FRESHMAN),
new Student("2", "Jane Smith", Student.Year.SOPHOMORE)
);
}
}
Note: Used lambdas instead of PropertyValueFactory. See Why should I avoid using PropertyValueFactory in JavaFX?.
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.layout.StackPane?>
<StackPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.Controller">
<TableView fx:id="studentTable">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
<columns>
<TableColumn fx:id="idColumn" text="ID"/>
<TableColumn fx:id="nameColumn" text="Name"/>
<TableColumn fx:id="yearColumn" text="Year"/>
</columns>
</TableView>
</StackPane>
And here is the application class.
Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(Main.class.getResource("Main.fxml"));
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
}
Note: Expects the Main.fxml file to be in the same package as the sample.Main class.
The above example will run and display two students in a table view. But these students are created in code (specifically, the initialize method of the FXML controller). You want to read the students from a CSV file. For that, we need to write code to parse a CSV file into Student instances.
For example, StudentCsvReader.java:
package sample;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class StudentCsvReader {
/*
* This is really basic CSV-reading code. It assumes a perfectly formatted file
* that has no commas in the actual data (i.e., there's no delimiter-escape
* handling). You may want to find an existing library to parse CSV files; they
* are likely to be more robust. Also, there are libraries out there that will
* "directly" parse a CSV file into POJOs. It could look something like:
*
* List<Student> students = CSVParser.parse(csvFile, Student.class);
*
*
* Note this code also assumes there is no header row.
*/
public List<Student> read(Path csvFile) throws IOException {
try (BufferedReader br = Files.newBufferedReader(csvFile)) {
List<Student> students = new ArrayList<>();
String line;
while ((line = br.readLine()) != null) {
if (!line.isBlank()) {
String[] columns = line.split(",");
String id = columns[0];
String name = columns[1];
String year = columns[2];
students.add(new Student(id, name, Student.Year.valueOf(year.toUpperCase())));
}
}
return students;
}
}
}
And then we modify the Controller class to make use of this StudentCsvReader. Note we use a background thread and a Task to avoid doing I/O work on the JavaFX Application Thread.
Modified Controller.java:
package sample;
import java.nio.file.Path;
import java.util.List;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class Controller {
#FXML private TableView<Student> studentTable;
#FXML private TableColumn<Student, String> idColumn;
#FXML private TableColumn<Student, String> nameColumn;
#FXML private TableColumn<Student, Student.Year> yearColumn;
#FXML
private void initialize() {
idColumn.setCellValueFactory(data -> data.getValue().idProperty());
nameColumn.setCellValueFactory(data -> data.getValue().nameProperty());
yearColumn.setCellValueFactory(data -> data.getValue().yearProperty());
Path csvFile = Path.of(".", "students.csv");
Thread t = new Thread(new ParseStudentCsvTask(csvFile), "parse-csv-thread");
t.setDaemon(true);
t.start();
}
private class ParseStudentCsvTask extends Task<List<Student>> {
private final Path csvFile;
ParseStudentCsvTask(Path csvFile) {
this.csvFile = csvFile;
}
#Override
protected List<Student> call() throws Exception {
return new StudentCsvReader().read(csvFile);
}
#Override
protected void succeeded() {
studentTable.getItems().setAll(getValue());
}
#Override
protected void failed() {
getException().printStackTrace();
}
}
}
Note: Expects a CSV file named students.csv to exist in the working directory.
And here's an example CSV file that will work with the above code:
1,Kate Todd,FRESHMAN
2,Leroy Gibbs,SENIOR
3,Tony DiNozzo,JUNIOR
4,Ellie Bishop,FRESHMAN
5,Nick Torres,FRESHMAN
6,Ziva David,SOPHOMORE
Notice the modifications to the code did nothing to Student or how the TableView is configured. The only difference was how the Student instances were created. Basically, the UI should not know where or how the data is created/found.
You should also consider using an application architecture such as Model-View-Controller (MVC) or Model-View-ViewModel (MVVM). It encourages separation of concerns, making it easier to reason about and develop code. Check out Applying MVC With JavaFx.
Related
**I'm unable to create a constructor from "GUIController".. The program runs if i delete this line
"GUIController(){myModel = new TheModel(this)"
but i still need it in other part. Please help!
**
package theclient;
import java.rmi.RemoteException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class GUIController extends Application {
TheModel myModel;
GUIController(){
myModel = new TheModel(this);
}
//public void init(){}
public TextArea myTextArea;
public TextField myTextField;
// Button and text field actions
public void myButtonAction() {
sendMsg();
}
public void myTextFieldAction() {
sendMsg();
}
// Append coming message
public void displayMsg(String comingMSG) {
System.out.println("Receive 01");
myTextArea.appendText(comingMSG);
}
public void sendMsg() {
try {
System.out.println("Send 01");
myModel.myChatServer.tellOthers(myTextField.getText());
} catch (RemoteException ex) {
Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("GUI.fxml"));
Scene scene = new Scene(root, 600, 400);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
public static void main(String[] args) throws Exception {
new GUIController();
launch(args);
}
}
The Second class. I'd be thankful if you can suggest any edits to the code. Thanks in advance for your efforts.
package theclient;
import common.ChatServerInt;
import common.ClientInt;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TheModel implements ClientInt {
public GUIController myCtrl;
ChatServerInt myChatServer;
TheModel(GUIController myCtrl) {
this.myCtrl = myCtrl;
}
public ChatServerInt connection() {
if (myChatServer == null) {
try {
Registry reg = LocateRegistry.getRegistry(1111);
myChatServer = (ChatServerInt) reg.lookup("ChatService");
myChatServer.register(this);
myChatServer.tellOthers("I'm here!");
} catch (RemoteException | NotBoundException ex) {
Logger.getLogger(TheModel.class.getName()).log(Level.SEVERE, null, ex);
}
} return myChatServer;
}
#Override
public void receive(String msg) throws RemoteException {
myCtrl.displayMsg(msg);
}
}
Following the Model-view-controller design pattern, the model shouldn't be holding a reference to its controller. If the controller needs to respond to changes in the model's data, then this can be done with properties and listeners. The model holds a property (here, a StringProperty) and the controller listens for changes to the property.
For your code, this means storing the msg in a StringProperty. The controller, after constructing the model, attaches a ChangeListener that calls displayMsg when the model receives a message.
Using a property and listener, TheModel no longer stores a reference to GUIController and does not take a GUIController as a parameter in its constructor.
GUIController would look something like this:
public class GUIController extends Application {
...
TheModel myModel;
...
GUIController(){
myModel = new TheModel();
// Listen for changes in the msg StringProperty and call displayMessage when it changes
myModel.getMsgProperty().addListener(msg -> this.displayMsg(msg));
}
...
Note that the constructor for GUIController no longer needs to pass this to the constructor TheModel. (In general, avoid passing this outside of the constructor. An object is not fully constructed until the constructor returns.)
TheModel would look something like this:
public class TheModel implements ClientInt {
...
private StringProperty msgProperty;
...
// remember to add a getter and setter for msgProperty!
...
#Override
public void receive(String msg) throws RemoteException {
// When a message is received, listeners attached to msgProperty will execute when setValue is called
msgProperty.setValue(msg);
}
I have a runnable class "TemperatureSensor" which is periodically adding a new randomized floating point value to an array list TemperatureList as an object Temperature. The last added object in the array (index 0) is then sent from RMI client to RMI server - this happens without problems.
However, when I click a button on GUI to display the size of this object array, I always get a 0. If I print out the size of the array from RMI client class, it shows a correct size.
My question is, how do I access the same array from multiple classes correctly?
Here is the UML:
TemperatureSensor:
import java.text.DecimalFormat;
import java.util.Random;
public class TemperatureSensor implements Runnable
{
private int waitingTime;
private Model model;
public TemperatureSensor(Model model, int waitingTime)
{
this.model = model;
this.waitingTime = waitingTime;
}
#Override
public void run()
{
float temperature = 25.0f;
while(true)
{
temperature = measureTemperature(temperature);
model.addTemperatureData(temperature);
System.out.println("Sending: " + temperature);
waiting();
}
}
private float measureTemperature(float temperature)
{
Random rand = new Random();
float minTempFloat = 0.1f;
float maxTempFloat = 0.2f;
int incrementSwitch = rand.nextInt(3-0) + 0;
if (incrementSwitch == 0)
{
temperature += minTempFloat + rand.nextFloat() * (maxTempFloat - minTempFloat);
}
else if(incrementSwitch == 1)
{
//Do nothing
}
else if (incrementSwitch == 2)
{
temperature -= minTempFloat + rand.nextFloat() * (maxTempFloat -
minTempFloat);
}
return temperature;
}
private void waiting()
{
try
{
Thread.sleep(waitingTime);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Model:
public interface Model
{
public void addTemperatureData(float value);
public Temperature getLatestTemperatureData();
public int getTempListSize();
}
ModelManager:
public class ModelManager implements Model
{
private TemperatureList temperatureList;
public ModelManager()
{
temperatureList = new TemperatureList();
}
#Override
public void addTemperatureData(float value)
{
Temperature temperature = new Temperature(value);
//this.temperatureList.clearTemperatureDataList();
this.temperatureList.addTemperatureDataToList(temperature);
}
#Override
public Temperature getLatestTemperatureData()
{
return temperatureList.getLatestTemperatureDataFromList();
}
#Override
public int getTempListSize()
{
return temperatureList.size();
}
}
RMIsensorClient:
import java.rmi.Naming;
import java.rmi.RemoteException;
public class RMIsensorClient
{
private RMIserverInterface serverInterface;
private static Model model = new ModelManager();
public static void main(String[] args) throws RemoteException, InterruptedException
{
TemperatureSensor tempSensor = new TemperatureSensor(model, 5000);
Thread tempThread = new Thread(tempSensor, "TempSensor");
tempThread.start();
RMIsensorClient sensorClient = new RMIsensorClient();
}
public RMIsensorClient() throws RemoteException
{
super();
try
{
serverInterface = (RMIserverInterface) Naming.lookup("rmi://localhost:1099/rmiServer");
while(true)
{
serverInterface.getTemperature(model.getLatestTemperatureData());
System.out.println(model.getTempListSize());
Thread.sleep(5000);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Controler:
public class Controller
{
private static Model model;
public Controller ()
{
this.model = new ModelManager();
}
public int getNumberOfListElements()
{
return model.getTempListSize();
}
}
GUI:
public class GUItemperatureController implements Initializable
{
private Controller controller = new Controller();
#FXML
private Label tlTemperature;
#FXML
private Pane mainPane;
#FXML
private TextField tfTemperature;
#FXML
private Button btnUpdate;
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
tfTemperature.setEditable(false);
}
#FXML
void showArraySize(ActionEvent event)
{
tfTemperature.setText(Integer.toString(controller.getNumberOfListElements()));
}
}
TemperatureList:
import java.io.Serializable;
import java.util.ArrayList;
public class TemperatureList implements Serializable
{
private ArrayList<Temperature> temperatureList;
public TemperatureList()
{
this.temperatureList = new ArrayList<>();
}
public void addTemperatureDataToList(Temperature temperature)
{
temperatureList.add(0,temperature);
}
public Temperature getLatestTemperatureDataFromList()
{
return this.temperatureList.get(0);
}
public void clearTemperatureDataList()
{
temperatureList.clear();
}
public int size()
{
return temperatureList.size();
}
}
Here is where I launch the GUI:
import java.rmi.RemoteException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class userMain extends Application
{
public FXMLLoader loader;
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception
{
loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML/FXMLtemperature.fxml"));
loader.setController(new GUItemperatureController());
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setTitle("GEMS - Test");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Your problem is not about classes.
You run two separate applications. One runs your RMIsensorClient and one runs your GUI. They know nothing about each other, your RMIsensorClient and your Controller have their own separate instances of ModelManager and you have no code anywhere that would share any data between them.
You need to make the data you want to show in your GUI accessible somehow.
One solution could be to use a network interface for that. Create two different ModelManagers, one that opens and listens to a ServerSocket, and one that uses a Socket in getLatestTemperatureData() to connect to the other one.
Use the former in your RMIsensorClient and the latter in your GUI's Controller.
Research networking in Java.
This is a very crude solution, but there are plenty of great tutorials for networking and sharing data between multiple Java applications.
You haven't included your TemperatureList implementation, but if as you say it's an ArrayList it's likely you're not properly synchronizing access across threads. It's imperative that you properly synchronize cross-thread work otherwise you'll wind up with some sort of undefined behavior, such as changes not propagating or data structures winding up broken.
There are a number of thread-safe collections in java.util.collect.concurrent that you might consider, otherwise you'll need to ensure you use synchronized blocks or methods anywhere you're working with this list.
The most obvious problem that I found(and this might not be all) is that your array list is method specific. it is not static. Meaning that it can only be accessed by the method it originates in. the easiest fix for this is to add a static modifier to your array list when it is created and create it outside of the methods.
I'm trying to use YamlBeans to serialize fxml properties. Specificaly a Property. The class has a private property field and the fxml standard getter and setter methods but the information is not saved to the file when serialization occurs.
Entry point:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
Person person = new Person(5);
YamlSerializer.serialize(person, System.getProperty("user.dir") + "/person.yml");
}
}
Person.java
import javafx.beans.property.Property;
import javafx.beans.property.SimpleDoubleProperty;
public class Person{
private Property<Number> age;
public Person(){
age = new SimpleDoubleProperty();
age.setValue(3);
}
public Person(Number age){
this.age = new SimpleDoubleProperty(age.doubleValue());
}
public Property<Number> ageProperty() {
return this.age;
}
public Number getAge() {
return this.ageProperty().getValue();
}
public void setAge(final Number age) {
this.ageProperty().setValue(age);
}
}
YamlSerializer.java
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import com.esotericsoftware.yamlbeans.YamlReader;
import com.esotericsoftware.yamlbeans.YamlWriter;
public class YamlSerializer {
public static void serialize(Object object, String path) throws IOException{
File file = new File(path);
if(!file.exists())
file.getParentFile().mkdirs();
YamlWriter writer = new YamlWriter(new FileWriter(path));
writer.write(object);
writer.close();
}
public static Object deserialize(String path) throws IOException{
File file = new File(path);
if(!file.exists()){
if(!file.getParentFile().exists())
if (!file.getParentFile().mkdirs()){
System.out.println("Error creating files");
}
}
YamlReader reader = new YamlReader(new FileReader(path));
return reader.read();
}
}
Output file person.yml:
!Person {}
Your code looks OK. What does Beans getProperties return for your class? This is what YamlWriter uses.
Turns out Beans is finding all the properties, then looking for get/set methods. It looks like it should find your number field and then your setNumber and getNumber methods, but you didn't provide the full class code.
I suggest providing an SSCCE. Trying to help someone without that is a shot in the dark and a time waste.
Edit: The way Beans looks for fields, then a matching setter/getter, Property<Number> age doesn't work. Beans looks for a setter/getter of type Property<Number> and doesn't find them. IIRC it used to use Introspector, but that had to be ripped out because it was missing from Android.
To fix this you would need to patch Beans to be smarter about finding setter/getters without a corresponding field. A PR that does that would be merged.
I am building a small scale system that has both workers and managers, manager inherits all of the workers properties because he also is a worker but has higher access within the system. I have a system class which has been reduced in size for clarity,
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Scanner;
public class system {
static Depot depot = new Depot("d1");
//static Depot depot2 = new Depot("d2");
//static Depot depot3 = new Depot("d3");
static ArrayList<Depot> depotArray = new ArrayList<Depot>();
public static void systemSetup() {
depotArray.add(depot);
}
public static void main(String[] args) throws ParseException {
StateThreadClass stateThreadClass = new StateThreadClass();
Thread thread = new Thread(stateThreadClass);
thread.start();
systemSetup();
GetDepot();
}
}
Once I get a depot it brings me to my main depot class which holds most calculations.
import java.io.IOException;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.Scanner;
//import Driver.Manager;
public class Depot{
String name;
int LOCount = 0;
int counter = 0;
#SuppressWarnings("deprecation")
Long date3 = 1478217600000L;
Date date1 = new Date(1478217600000L);
Date date2 = new Date(1479217600000L);
Worker worker = new Worker ("tom", "tom", false);
Worker worker = new Worker ("phil2", "phil2", false);
Worker worker = new Worker ("phil", "phil", true);
-----> Manager manager = new Manager("ben", "ben", true);
etc.....
}
I can instantiate the Worker with no problem and use it within the system but when I attempt to instantiate the Manager I get an error saying "Manager cannot be resolved to a type", I am given the option of importing it. When I do I get another error "The import Worker cannot be resolved"
This is my Worker and Manager class minus unnecessary code,
import java.io.IOException;
public class Worker {
private String username;
private String password;
private boolean available;
public Worker(String username, String password, boolean av) {
this.username = username;
this.password = password;
this.available = av;
}
public Boolean CheckPassword(String password) {
return this.password.equals(password);
}
public Boolean CheckUsername(String username) {
return this.username.equals(username);
}
public class Manager extends Worker {
public Manager(String username, String password, boolean av) {
super(username, password,av);
}
}
Any help would be appreciated, I know I shouldn't be using static but I will deal with that another day!
cheers
Ensure that your Manager class is defined in its own file separately. As it's defined as an inner class of Worker, then it's currently not accessible outside of your Worker class.
Once you have that fixed, then you should be able to refer to your Manager class from your Depot class, provided they are in the same package. If they are not, then simply include the import for your Manager class and you'll be able to access your Manager class.
Some info on inner classes: http://www.javaworld.com/article/2077411/core-java/inner-classes.html.
I'm looking at a GUI program made using MVC and they have this method. What does this method do and when will you need to use it?
attach(this);
Here is one of the classes with the method.
import model.*;
import java.awt.*;
import java.text.*;
import javax.swing.*;
public class IncomePanel extends JPanel implements View
{ private Stadium stadium;
private JLabel label;
public IncomePanel(Stadium stadium)
{ this.stadium = stadium;
for (Group group: stadium.seats())
group.attach(this);
setup();
build(); }
private void setup()
{ setBorder(BorderFactory.createLineBorder(Color.blue));
setLayout(new FlowLayout()); }
private void build()
{ label = new JLabel(income());
label.setForeground(Color.blue);
add(label); }
public void update()
{ label.setText(income()); }
private String income()
{ return "Income is $" + twoDec(stadium.income()); }
private String twoDec(double value)
{ DecimalFormat twoD = new DecimalFormat("#0.00");
return twoD.format(value); }
}
Look inside the model package which is part of your project. In there you'll find a file named group.java. It contains the source for the Group class or interface.
All this snippet tells us is that Group's attach method takes an IncomePanel as an argument. If you want to find out what it does with it you have to look at the Group file.