Listview 没有正确显示实时 Observable 列表更改
Listview doesn't show realtime Observable list changes correctly
我的应用程序的一部分有问题,无法正常工作,我有一个 java fx listview 就像一个日志,我正在尝试创建一个简单的日志它。看代码,
我尝试添加一个任务,该任务每秒使用 "writeLog" 函数写入日志并且它有效(列表视图使用新字符串正确刷新)。第二个代码是相同的,但没有任务,它不能像我想要的那样工作,在这种情况下,writeLog 将被其他 类 调用。
当从其他 类 调用 writeLog("any string..") 时,Observable 列表将正确更改并且文件 ( log ) 也会更改,但列表视图不想显示添加到日志中的新字符串。
public class ControllerServer implements Initializable {
@FXML
public ListView myListView;
private ObservableList<String> logList = FXCollections.observableArrayList();
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
fillLogList();
MyTask task = new MyTask();
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(task,4000,4000);
} catch (IOException e) {
e.printStackTrace();
}
if (logList!= null) {
for (int i = 0; i < logList.size(); i++) {
System.out.println(logList.get(i));
}
logList.addListener((javafx.beans.Observable observable)->{
System.out.println("changed list");
});
}
myListView.setItems(logList);
}
//METHODS
public void fillLogList() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("samplefile1.txt"));
String line;
while((line = reader.readLine())!=null) {
logList.add(line);
}
}
public void writeLog(String log) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("samplefile1.txt", true));
writer.write(log);
if(logList!=null){
logList.add(log);
System.out.println("i'm writing this log inside the file, log say : " + log);
}else
writer.newLine();
writer.close();
}
class MyTask extends TimerTask {
@Override
public void run(){
try {
writeLog("Hello, i'm working inside this task, why?");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class ControllerServer implements Initializable {
@FXML
public ListView myListView;
private ObservableList<String> logList = FXCollections.observableArrayList();
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
fillLogList();
} catch (IOException e) {
e.printStackTrace();
}
if (logList!= null) {
for (int i = 0; i < logList.size(); i++) {
System.out.println(logList.get(i));
}
logList.addListener((javafx.beans.Observable observable)->{
System.out.println("changed list");
});
}
myListView.setItems(logList);
}
//METHODS
public void fillLogList() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("samplefile1.txt"));
String line;
while((line = reader.readLine())!=null) {
logList.add(line);
}
}
public void writeLog(String log) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("samplefile1.txt", true));
writer.write(log);
if(logList!=null){
logList.add(log);
System.out.println("i'm writing this log inside the file, log say : " + log);
}else
writer.newLine();
writer.close();
}
}
public class Server extends Application {
private static ServerLog serverLog = new ServerLog();
private static ControllerServer controllerServer = new ControllerServer();
public static void main(String[] args) throws IOException {
Runnable r = () -> {
new File("users").mkdir();
try {
ServerSocket socket = new ServerSocket(8189);
while(true) {
Socket s = socket.accept();
ServiceHandler client = new ServiceHandler(s);
}
}catch(IOException e){e.printStackTrace();}
};
new Thread(r).start();
controllerServer.writeLog("server starting..");
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("View/server.fxml"));
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.setTitle("Server Log");
primaryStage.show();
}
}
package server;
import server.Controller.ControllerServer;
import server.Model.*;
import java.io.*;
import java.net.Socket;
import static common.ServiceID.*;
import static common.ServiceID.FAILURE_RESPONSE;
public class ServiceHandler extends Thread{
private static Object lock = new Object();
private static ServerLog serverLog = new ServerLog();
private static ControllerServer controllerServer = new ControllerServer();
private Socket s;
public ServiceHandler(Socket s){
this.s = s;
this.start();
}
public void run()
{
try
{
controllerServer.writeLog("client address "+s.getInetAddress());
InputStream inputStream = s.getInputStream();
int servId = inputStream.read();
OutputStream outputStream = s.getOutputStream();
Thread t;
switch(servId) {
case WRITE_EMAIL:
controllerServer.writeLog("Writing Email, id : " + WRITE_EMAIL);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailReceiver(s,lock, servId));
t.start();
break;
case READ_ALL_EMAILS:
controllerServer.writeLog("Loading users list, id : " + READ_ALL_EMAILS);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailReader(s));
t.start();
break;
case USER_LIST:
controllerServer.writeLog("Caricamento lista utenti, id : " + USER_LIST);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new UserGetter(s));
t.start();
break;
case LOGIN:
controllerServer.writeLog("Login, id " + LOGIN);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new UserLogin(s));
t.start();
break;
case DELETE_EMAIL:
controllerServer.writeLog("delete email, id " + DELETE_EMAIL);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailDelete(s));
t.start();
break;
default:
controllerServer.writeLog("Error");
outputStream.write(FAILURE_RESPONSE);
break;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
问题是您要在其他 class 中创建新的 ControllerServer
。
当您从那些 class 中调用 controllerServer.writeLog()
时,您实际上是在写入与绑定到 ListView
的完全不同的 List
。
相反,您应该只有一个 ControllerServer
并将对它的引用传递给需要它的任何其他 classes。
例如,您可以这样更新 ServiceHandler
class:
public class ServiceHandler extends Thread {
private static Object lock = new Object();
private static ServerLog serverLog = new ServerLog();
private Socket s;
private ControllerServer controllerServer; // Do NOT instantiate it here!
// Pass your single ControllerServer to the constructor
public ServiceHandler (Socket socket, ControllerServer controllerServer) {
this.s = socket;
this.controllerServer = controllerServer;
this.start();
}
}
现在,当您稍后调用 controllerServer.writeLog()
时,您将在 ControllerServer
的正确实例上执行此操作。
我的应用程序的一部分有问题,无法正常工作,我有一个 java fx listview 就像一个日志,我正在尝试创建一个简单的日志它。看代码,
我尝试添加一个任务,该任务每秒使用 "writeLog" 函数写入日志并且它有效(列表视图使用新字符串正确刷新)。第二个代码是相同的,但没有任务,它不能像我想要的那样工作,在这种情况下,writeLog 将被其他 类 调用。 当从其他 类 调用 writeLog("any string..") 时,Observable 列表将正确更改并且文件 ( log ) 也会更改,但列表视图不想显示添加到日志中的新字符串。
public class ControllerServer implements Initializable {
@FXML
public ListView myListView;
private ObservableList<String> logList = FXCollections.observableArrayList();
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
fillLogList();
MyTask task = new MyTask();
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(task,4000,4000);
} catch (IOException e) {
e.printStackTrace();
}
if (logList!= null) {
for (int i = 0; i < logList.size(); i++) {
System.out.println(logList.get(i));
}
logList.addListener((javafx.beans.Observable observable)->{
System.out.println("changed list");
});
}
myListView.setItems(logList);
}
//METHODS
public void fillLogList() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("samplefile1.txt"));
String line;
while((line = reader.readLine())!=null) {
logList.add(line);
}
}
public void writeLog(String log) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("samplefile1.txt", true));
writer.write(log);
if(logList!=null){
logList.add(log);
System.out.println("i'm writing this log inside the file, log say : " + log);
}else
writer.newLine();
writer.close();
}
class MyTask extends TimerTask {
@Override
public void run(){
try {
writeLog("Hello, i'm working inside this task, why?");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class ControllerServer implements Initializable {
@FXML
public ListView myListView;
private ObservableList<String> logList = FXCollections.observableArrayList();
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
fillLogList();
} catch (IOException e) {
e.printStackTrace();
}
if (logList!= null) {
for (int i = 0; i < logList.size(); i++) {
System.out.println(logList.get(i));
}
logList.addListener((javafx.beans.Observable observable)->{
System.out.println("changed list");
});
}
myListView.setItems(logList);
}
//METHODS
public void fillLogList() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("samplefile1.txt"));
String line;
while((line = reader.readLine())!=null) {
logList.add(line);
}
}
public void writeLog(String log) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("samplefile1.txt", true));
writer.write(log);
if(logList!=null){
logList.add(log);
System.out.println("i'm writing this log inside the file, log say : " + log);
}else
writer.newLine();
writer.close();
}
}
public class Server extends Application {
private static ServerLog serverLog = new ServerLog();
private static ControllerServer controllerServer = new ControllerServer();
public static void main(String[] args) throws IOException {
Runnable r = () -> {
new File("users").mkdir();
try {
ServerSocket socket = new ServerSocket(8189);
while(true) {
Socket s = socket.accept();
ServiceHandler client = new ServiceHandler(s);
}
}catch(IOException e){e.printStackTrace();}
};
new Thread(r).start();
controllerServer.writeLog("server starting..");
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("View/server.fxml"));
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.setTitle("Server Log");
primaryStage.show();
}
}
package server;
import server.Controller.ControllerServer;
import server.Model.*;
import java.io.*;
import java.net.Socket;
import static common.ServiceID.*;
import static common.ServiceID.FAILURE_RESPONSE;
public class ServiceHandler extends Thread{
private static Object lock = new Object();
private static ServerLog serverLog = new ServerLog();
private static ControllerServer controllerServer = new ControllerServer();
private Socket s;
public ServiceHandler(Socket s){
this.s = s;
this.start();
}
public void run()
{
try
{
controllerServer.writeLog("client address "+s.getInetAddress());
InputStream inputStream = s.getInputStream();
int servId = inputStream.read();
OutputStream outputStream = s.getOutputStream();
Thread t;
switch(servId) {
case WRITE_EMAIL:
controllerServer.writeLog("Writing Email, id : " + WRITE_EMAIL);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailReceiver(s,lock, servId));
t.start();
break;
case READ_ALL_EMAILS:
controllerServer.writeLog("Loading users list, id : " + READ_ALL_EMAILS);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailReader(s));
t.start();
break;
case USER_LIST:
controllerServer.writeLog("Caricamento lista utenti, id : " + USER_LIST);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new UserGetter(s));
t.start();
break;
case LOGIN:
controllerServer.writeLog("Login, id " + LOGIN);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new UserLogin(s));
t.start();
break;
case DELETE_EMAIL:
controllerServer.writeLog("delete email, id " + DELETE_EMAIL);
outputStream.write(SUCCESS_RESPONSE);
t = new Thread(new EmailDelete(s));
t.start();
break;
default:
controllerServer.writeLog("Error");
outputStream.write(FAILURE_RESPONSE);
break;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
问题是您要在其他 class 中创建新的 ControllerServer
。
当您从那些 class 中调用 controllerServer.writeLog()
时,您实际上是在写入与绑定到 ListView
的完全不同的 List
。
相反,您应该只有一个 ControllerServer
并将对它的引用传递给需要它的任何其他 classes。
例如,您可以这样更新 ServiceHandler
class:
public class ServiceHandler extends Thread {
private static Object lock = new Object();
private static ServerLog serverLog = new ServerLog();
private Socket s;
private ControllerServer controllerServer; // Do NOT instantiate it here!
// Pass your single ControllerServer to the constructor
public ServiceHandler (Socket socket, ControllerServer controllerServer) {
this.s = socket;
this.controllerServer = controllerServer;
this.start();
}
}
现在,当您稍后调用 controllerServer.writeLog()
时,您将在 ControllerServer
的正确实例上执行此操作。