I am wrtiting a simple GUI port scanner in JavaFX. It is using multiple threads to discover online hosts in the local network. I have hostDiscovery
button that I want to disable before host discovery process is started. When I execute my code, the host discovery process will finish and only after it is finished my button will become disabled.
Part of my FXML file
<Button fx:id="hostDiscovery" layoutX="470.0" layoutY="370.0" mnemonicParsing="false" prefHeight="60.0" prefWidth="200.0" text="Start Host Discovery" AnchorPane.bottomAnchor="30.0" AnchorPane.rightAnchor="30.0" />
Debug code in Controller class
public class FXMLController implements Initializable
{
@FXML
private Button hostDiscovery;
@Override // This method is called by the FXMLLoader when initialization is complete
public void initialize(URL fxmlFileLocation, ResourceBundle resources)
{
assert hostDiscovery != null : "fx:id=\"hostDiscovery\" was not injected: check your FXML file 'PortScanner.fxml'.";
// initialize your logic here: all @FXML variables will have been injected
hostDiscovery.setOnAction(event -> {
System.out.println("HD Test Start");
hostDiscovery.setDisable(true); //Here I want to disable the button
final int hostDiscoveryTimeout = 1000;
final int threads = 25;
final ExecutorService exService = Executors.newFixedThreadPool(threads);
final List<Future<HostDiscoveryResult>> futures = new ArrayList<>();
String ipAddress = "192.168.0.";
for (int i = 1; i < 255; i++)
{
StringBuilder currentIPAddress = new StringBuilder().append(ipAddress).append(i);
HostDiscovery dHost = new HostDiscovery(currentIPAddress.toString(), hostDiscoveryTimeout);
futures.add(dHost.multithreadedHostDicovery(exService));
}
try
{
exService.shutdown();
exService.awaitTermination(hostDiscoveryTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e)
{
System.out.println(e);
}
for (final Future<HostDiscoveryResult> i : futures)
{
try
{
if (i.get().isOnline())
{
System.out.print(i.get().getIpAddress() + " ");
System.out.println(i.get().getHostName());
}
} catch (Exception e)
{
System.out.println(e);
}
}
System.out.println("HD Test Stop");
});
}
}
OK, after reading this thread that James_D posted Using threads to make database requests I managed to modify my code to run as expected. Here is the modified version
hostDiscovery.setOnAction(event -> {
Task<Void> hostDiscoveryTask = new Task<Void>()
{
@Override
protected Void call() throws Exception
{
System.out.println("HD Test Start");
final int hostDiscoveryTimeout = 1000;
final int threads = 25;
final ExecutorService exService = Executors.newFixedThreadPool(threads);
final List<Future<HostDiscoveryResult>> futures = new ArrayList<>();
String ipAddress = "192.168.0.";
for (int i = 1; i < 255; i++)
{
StringBuilder currentIPAddress = new StringBuilder().append(ipAddress).append(i);
HostDiscovery dHost = new HostDiscovery(currentIPAddress.toString(), hostDiscoveryTimeout);
futures.add(dHost.multithreadedHostDicovery(exService));
}
try
{
exService.shutdown();
exService.awaitTermination(hostDiscoveryTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e)
{
System.out.println(e);
}
for (final Future<HostDiscoveryResult> i : futures)
{
try
{
if (i.get().isOnline())
{
System.out.print(i.get().getIpAddress() + " ");
System.out.println(i.get().getHostName());
}
} catch (Exception e)
{
System.out.println(e);
}
}
System.out.println("HD Test Stop");
Platform.runLater(() -> hostDiscovery.setDisable(false));
Platform.runLater(() -> hostDiscovery.setText("Restart Host Discovery"));
return null;
}
};
Thread thr = new Thread(hostDiscoveryTask);
hostDiscovery.setDisable(true);
hostDiscovery.setText("WORKING");
thr.setDaemon(true);
thr.start();
});
}
}