JavaFX学习之样例1

代码老外的,学习学习

该代码主要功能是通过JavaFX的concurrent实现异步的数据库操作。

package h2app;

import java.sql.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class H2Tasks extends Application {
private static final Logger logger = Logger.getLogger(H2Tasks.class
.getName());
private static final String[] SAMPLE_NAME_DATA = { "John", "Jill", "Jack",
"Jerry" };

public static void main(String[] args) {
launch(args);
}

// executes database operations concurrent to JavaFX operations.
private ExecutorService databaseExecutor;

// the future's data will be available once the database setup has been
// complete.
private Future databaseSetupFuture;

// initialize the program.
// setting the database executor thread pool size to 1 ensures
// only one database command is executed at any one time.
@Override
public void init() throws Exception {
databaseExecutor = Executors.newFixedThreadPool(1,
new DatabaseThreadFactory());

// run the database setup in parallel to the JavaFX application setup.
DBSetupTask setup = new DBSetupTask();
databaseSetupFuture = databaseExecutor.submit(setup);
}

// shutdown the program.
@Override
public void stop() throws Exception {
databaseExecutor.shutdown();
if (!databaseExecutor.awaitTermination(3, TimeUnit.SECONDS)) {
logger.info("Database execution thread timed out after 3 seconds rather than shutting down cleanly.");
}
}

// start showing the UI.
@Override
public void start(Stage stage) throws InterruptedException,
ExecutionException {
// wait for the database setup to complete cleanly before showing any
// UI.
// a real app might use a preloader or show a splash screen if this
// was to take a long time rather than just pausing the JavaFX
// application thread.
databaseSetupFuture.get();

final ListView<String> nameView = new ListView();
final ProgressIndicator databaseActivityIndicator = new ProgressIndicator();
databaseActivityIndicator.setVisible(false);

final Button fetchNames = new Button("Fetch names from the database");
fetchNames.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
fetchNamesFromDatabaseToListView(fetchNames,
databaseActivityIndicator, nameView);
}
});

final Button clearNameList = new Button("Clear the name list");
clearNameList.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
nameView.getItems().clear();
}
});

VBox layout = new VBox(10);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;");
layout.getChildren().setAll(
HBoxBuilder
.create()
.spacing(10)
.children(fetchNames, clearNameList,
databaseActivityIndicator).build(), nameView);
layout.setPrefHeight(200);

stage.setScene(new Scene(layout));
stage.show();
}

private void fetchNamesFromDatabaseToListView(final Button triggerButton,
final ProgressIndicator databaseActivityIndicator,
final ListView listView) {
final FetchNamesTask fetchNamesTask = new FetchNamesTask();
triggerButton.setDisable(true);
databaseActivityIndicator.setVisible(true);
databaseActivityIndicator.progressProperty().bind(
fetchNamesTask.progressProperty()); //进度条绑定任务
fetchNamesTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() { //task的成功执行事件
@Override
public void handle(WorkerStateEvent t) {
listView.setItems(fetchNamesTask.getValue()); //task.getValue()获取task.call()方法返回的值
}
});
fetchNamesTask.runningProperty().addListener(
new ChangeListener<Boolean>() {
@Override
public void changed(
ObservableValue<? extends Boolean> observable,
Boolean wasRunning, Boolean isRunning) {
if (!isRunning) {
triggerButton.setDisable(false);
databaseActivityIndicator.setVisible(false);
}
};
});
databaseExecutor.submit(fetchNamesTask);
}

abstract class DBTask<T> extends Task<T> {
DBTask() {
setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent t) {
logger.log(Level.SEVERE, null, getException());
}
});
}
}

class FetchNamesTask extends DBTask<ObservableList<String>> {
@Override
protected ObservableList<String> call() throws Exception {
// artificially pause for a while to simulate a long running
// database connection.
Thread.sleep(1000);

Connection con = getConnection();
return fetchNames(con);

}

private ObservableList<String> fetchNames(Connection con)
throws SQLException {
logger.info("Fetching names from database");
ObservableList<String> names = FXCollections.observableArrayList();

Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select name from employee");
while (rs.next()) {
names.add(rs.getString("name"));
}

logger.info("Found " + names.size() + " names");

return names;
}
}

class DBSetupTask<Void> extends DBTask {
@Override
protected Void call() throws Exception {

Connection con = getConnection();
if (!schemaExists(con)) {
createSchema(con);
populateDatabase(con);
}

return null;
}

private boolean schemaExists(Connection con) {
logger.info("Checking for Schema existence");
try {
Statement st = con.createStatement();
st.executeQuery("select count(*) from employee");
logger.info("Schema exists");
} catch (SQLException ex) {
logger.info("Existing DB not found will create a new one");
return false;
}

return true;
}

private void createSchema(Connection con) throws SQLException {
logger.info("Creating schema");
Statement st = con.createStatement();
String table = "create table employee(id integer, name varchar(64))";
st.executeUpdate(table);
logger.info("Created schema");
}

private void populateDatabase(Connection con) throws SQLException {
logger.info("Populating database");
Statement st = con.createStatement();
for (String name : SAMPLE_NAME_DATA) {
st.executeUpdate("insert into employee values(1,'" + name
+ "')");
}
logger.info("Populated database");
}
}

private Connection getConnection() throws ClassNotFoundException,
SQLException {
logger.info("Getting a database connection");
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&noAccessToProcedureBodies=true", "root", "root");
}

static class DatabaseThreadFactory implements ThreadFactory {
static final AtomicInteger poolNumber = new AtomicInteger(1);

@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "Database-Connection-"
+ poolNumber.getAndIncrement() + "-thread");
thread.setDaemon(true);

return thread;
}
}
}


代码里是通过java的多线程执行task,并不是通过javafx的service。代码很简单通过二个task,一个初始化数据库,一个查询数据库。结果返回显示。


		
fetchNamesTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() { //task的成功执行事件
@Override
public void handle(WorkerStateEvent t) {
listView.setItems(fetchNamesTask.getValue()); //task.getValue()获取task.call()方法返回的值
}
});

没想到过task.getValue()既是call的返回值,学习到了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值