- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
好吧,我对 Java 编程并不陌生,但我对在 Java 程序中使用线程很陌生。我正在上学,刚刚读完关于线程和 Java 网络的章节。我正在编写一个客户端 GUI,将贷款信息(年利率、年数和贷款金额)发送到服务器。服务器有自己的 GUI,计算每月还款额和贷款总额,并将其发送回客户端并显示给用户,并更新服务器 GUI。
书中有这样的代码作为示例:
public class Server extends Application {
/** Variables */
private TextArea textArea = new TextArea();
private double rate;
private int year;
private double loan;
public void start(Stage serverStage)
{
// Creating server GUI
Scene scene = new Scene(new ScrollPane(textArea), 400, 200);
serverStage.setTitle("Server");
serverStage.setScene(scene);
serverStage.show();
new Thread(() ->{
try
{
// create server socket
ServerSocket serverSocket = new ServerSocket(8000);
textArea.appendText("Server started at " + new Date() + "\n");
while(true)
{
// listen for a connection request
Socket socket = serverSocket.accept();
Platform.runLater(() -> {
InetAddress inetAddress = socket.getInetAddress();
textArea.appendText("Connected to " + inetAddress.getHostAddress() + " at " + new Date() + "\n");
});
// create and start a new thread for every connection
new Thread(new HandleAClient(socket)).start();
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}).start();
}
class HandleAClient implements Runnable {
private Socket socket; // A connected socket
private double rate;
private int year;
private double loan;
/** costruct a thread */
public HandleAClient(Socket socket)
{
this.socket = socket;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
rate = inputFromClient.readDouble();
year = inputFromClient.readInt();
loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
Platform.runLater( () -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
// calculateMonthlyPayment method calculates the monthly payment of a loan given
// the required information
public double calculateMonthlyPayment(double interestRate, int years, double loanAmt)
{
double monthlyRate;
int termInMonths;
double monthlyPayment;
// Convert the interest rate to a decimal
interestRate = interestRate / 100;
// convert annual interest rate to monthly interest rate
monthlyRate = interestRate / 12;
// calculate the term in months which is years * 12
termInMonths = years * 12;
monthlyPayment = (loanAmt*monthlyRate) / (1-Math.pow(1+monthlyRate, -termInMonths));
return monthlyPayment;
}
// method that calculates and returns the total payment of the loan
public double calculateTotalPayment(double rate, int year, double loan)
{
double totalPayment;
double monthlyPay;
monthlyPay = calculateMonthlyPayment(rate, year, loan);
totalPayment = monthlyPay * 12 * year;
return totalPayment;
}
}
正如您在示例代码中看到的,他们(本书的作者)使用一个新的线程来附加服务器 GUI 的文本。然而,为了能够处理多个客户端,需要在 while 循环内部创建一个新线程来处理每个单独的客户端。
我尝试将 HandleAClient 类创建为单独的 Java 类,而不是将其插入到 Server 类中,但这导致服务器 GUI 未使用 Platform.runLater 代码进行更新
Platform.runLater( () -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
所以我的问题是:为什么当 HandleAClient 类位于 Server 类内部时它可以工作,而当 HandleAClient 类位于扩展 Server 的单独 Java 类文件中时它不起作用?我认为它必须与线程做一些事情?为了能够在自己的 Java 类文件中包含 HandleAClient 类,我需要进行哪些更改?
我很好奇并试图很好地理解线程是如何工作的。预先感谢您。
更新这是独立的类(class),对我来说不起作用。我扩展了 Server 类,并在 Server 类中保护了 TextArea 字段。
class HandleAClient extends Server implements Runnable {
private Socket socket; // A connected socket
private double rate;
private int year;
private double loan;
public HandleAClient(Socket socket)
{
this.socket = socket;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
rate = inputFromClient.readDouble();
year = inputFromClient.readInt();
loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
Platform.runLater( () -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Platform.runLater 中的代码不会像该类位于 Server 类内部时那样出现在服务器 GUI 中。我想了解为什么会发生这种情况。
最佳答案
您需要您的HandleAClient
实例来更新属于 Server
的文本区域创建它们的对象:textArea
属于那个Server
实例是在 UI 中显示的实例。根据您的设置,每个 HandleAClient
实例有自己的 textArea
,并且每个都更新自己的 textArea
。当然,这些都不会显示。
对于我来说 HandleAClient
真的没有意义延长Server
。您需要做的(无论您是否拥有该继承)是为 HandleAClient
提供一种方法。更新属于 Server
的文本区域。最简单(但不一定是最好)的方法是将文本区域传递给 HandleAClient
实例:
class HandleAClient implements Runnable {
private Socket socket; // A connected socket
private double rate;
private int year;
private double loan;
private final TextArea textArea ;
public HandleAClient(Socket socket, TextArea textArea)
{
this.socket = socket;
this.textArea = textArea ;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
rate = inputFromClient.readDouble();
year = inputFromClient.readInt();
loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
Platform.runLater( () -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
然后当然是Server
您将其修改为
while(true)
{
// listen for a connection request
Socket socket = serverSocket.accept();
Platform.runLater(() -> {
InetAddress inetAddress = socket.getInetAddress();
textArea.appendText("Connected to " + inetAddress.getHostAddress() + " at " + new Date() + "\n");
});
// create and start a new thread for every connection
new Thread(new HandleAClient(socket, textArea)).start();
}
<小时/>
让 HandleAClient
感觉有点不自然类(负责通信)依赖于对 TextArea
的引用(这是特定于 UI 的)。更自然的方法如下。
我可能会定义一个简单的类来表示利率、年份和贷款:
public class LoanData {
private final double rate ;
private final int year ;
private final double loan ;
public LoanData(double rate, int year, double loan) {
this.rate = rate ;
this.year = year ;
this.loan = loan ;
}
public double getRate() {
return rate ;
}
public int getYear() {
return year ;
}
public double getLoan() {
return loan ;
}
}
然后给出HandleAClient
A类Consumer<LoanData>
用于处理贷款数据:
class HandleAClient implements Runnable {
private Socket socket; // A connected socket
private final Consumer<LoanData> dataProcessor ;
public HandleAClient(Socket socket, Consumer<LoanData> dataProcessor)
{
this.socket = socket;
this.dataProcessor = dataProcessor ;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
double rate = inputFromClient.readDouble();
double year = inputFromClient.readInt();
double loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
dataProcessor.accept(new LoanData(rate, year, loan));
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
现在在服务器中执行
Consumer<LoanData> textAreaUpdater =
loanData -> Platform.runLater(() -> {
textArea.appendText("The rate is : " + loanData.getRate() + "\n");
textArea.appendText("The number of years is: " + loanData.getYear() + "\n");
textArea.appendText("Loan amount is: " + loanData.getLoan() + "\n\n");
});
new Thread(new HandleAClient(socket, textAreaUpdater)).start();
这使得 UI 数据功能正确地隔离在 UI 类中。
关于java - 有没有办法在 JavaFX 中的不同类文件中使用线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42428801/
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
在现代 IDE 中,有一个键盘快捷键可以通过键入文件名称来打开文件,而无需将手放在鼠标上。例如: Eclipse:Cmd|Ctrl + Shift + R -> 打开资源 IntelliJ:Cmd|C
有什么东西会等待事件发生(我正在等待的是 WebBrowser.DocumentCompleted),然后执行代码吗?像这样: If (WebBrowser.DocumentCompleted) 不会
我使用 PHP Minify,它很棒。但我的问题是,是否有任何 PHP 插件或其他东西可以自动检测 javascript/css 代码并自动缩小它?谢谢。 最佳答案 Javascript 压缩器? 看
有没有一种语言,类似什么CoffeeScript是JavaScript,编译成windows batch|cmd|command line的语言? 我指的cmd版本是基于NT的,尤其是XP sp3及以
我知道我可以 ,但是,我真的宁愿有一个任务,我可以从任何可以使用所有(或至少大部分)属性的操作系统调用 copy ,但这并没有消除 unix 上的权限。 我想知道是否已经有解决方案,或者我必须自己编
我正在使用 Vuejs(不使用 jQuery)开发一个项目,该项目需要像 jvectormap 这样的 map 但正如我所说,我没有使用 jQuery,那么是否有任何其他库可以在不使用 jQuery
想要进行一个简单的民意调查,甚至不需要基于 cookie,我不在乎投了多少票。有没有类似的插件或者简单的东西? 最佳答案 这是一个有用的教程 - 让我知道它是否适合您 using jQuery to
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
var FileBuff: TBytes; Pattern: TBytes; begin FileBuff := filetobytes(filename); Result := Co
我想要一个 vqmod xml 文件来添加一次上传多个图像的功能。身边有这样的事吗? 编辑:Opencart版本:2.1.0.1 最佳答案 最后我写了一个xml来添加到opencart 2.1.0.1
所以考虑这样的函数: public void setTemperature(double newTemperatureValue, TemperatureUnit unit) 其中Temperatur
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我是 ggplot2 的新手,一直在尝试找到一个全面的美学列表。我想我理解它们的目的,但很难知道哪些可以在各种情况下使用(主要是几何图形?)。 Hadley 的网站偶尔会在各个几何图形的页面上列出可用
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
是否有任何 PHP 函数可以将整数转换为十万和千万? 900800 -> 9,00,800 500800 -> 5,00,800 最佳答案 由于您已在问题标签中添加了 Yii,因此您可以按照 Yii
使用 Clojure 一段时间后,我积累了一些关于它的惰性的知识。我知道诸如map之类的常用API是否是惰性的。然而,当我开始使用一个不熟悉的API(例如with-open)时,我仍然感到怀疑。 是否
我的项目需要一个像 AvalonDock 这样的对接系统,但它的最后一次更新似乎是在 2013 年 6 月。是否有更多...积极开发的东西可以代替它? 最佳答案 AvalonDock 实际上相当成熟并
我正在寻找一个可以逆转 clojure 打嗝的函数 所以 turns into [:html] 等等 根据@kotarak的回答,这现在对我有用: (use 'net.cgrand.enliv
我是一名优秀的程序员,十分优秀!