Java在服务端领域能够独占鳌头,然而,在客户端领域一直不温不火。Java的客户端技术,从AWT,SWING,SWT,一直到JAVAFX,即使每一代都有非常大的改善,但仍改变不了它尴尬的地位。依我看来,使用JAVA来开发桌面应用,大概只有我有我们这批javaer了
不管怎样,javafx的设计理念还是非常优秀的。它借鉴了html开发的特点,将代码,界面,样式三者分离。使用java代码来控制逻辑,使用xml来设计界面,使用css来控制样式。
本文将使用一个简单的例子,来演示javafx的开发案例。
fxml里面有各种id定义,有了这些id,我们就可以用java代码对其进行控制。在fxml里,有一个fx:controller元素就是用来定义对应的控制器的。
public class LoginViewController implements ControlledStage, Initializable {
@FXML
private Button login;
@FXML
private TextField userId;
@FXML
private PasswordField password;
@FXML
private CheckBox rememberPsw;
@FXML
private CheckBox autoLogin;
@FXML
private ImageView closeBtn;
@FXML
private void login() throws IOException {
final long useId = Long.parseLong(userId.getText());
final String psw = password.getText();
if (!IoBaseService.INSTANCE.isConnectedSever()) {
errorPane.setVisible(true);
errorTips.setText(I18n.get("login.failToConnect"));
return;
}
loginProgress.setVisible(true);
login.setVisible(false);
LoginManager.getInstance().beginToLogin(useId, psw);
}
}
类似于LoginViewController里,如果我们需要控制xml里面的控件,我们就需要在代码里对控件类型写上@FXML的注解,变量的名字就是fxml里的id了。同时,控件的各种触发事件,例如点击,滑动事件,也需要写上@FXML注解,方法名称也要跟fxml文件里的命名一样,例如 onMouseClicked="#login"。
/**
* 将任务转移给fxapplication线程延迟执行
* @param task
*/
public void runTaskInFxThread(Runnable task){
Platform.runLater(task);
}
URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
FXMLLoader loader = new FXMLLoader(url);
loader.setResources(ResourceBundle.getBundle("i18n/message"));
这样,fxml就可以使用 text="%login.rememberPsw" 的方式引入国际化资源了。
/**
* 国际化资源池
* @author kingston
*/
public class I18n {
private static ResourceBundle resourcePool;
static {
try {
resourcePool = ResourceBundle.getBundle("i18n/message");
} catch (Exception e) {
e.printStackTrace();
}
}
public static String get(String key, Object... args) {
if (!resourcePool.containsKey(key)) {
return "国际化资源不存在";
}
String message = resourcePool.getString(key);
if (args != null) {
return MessageFormat.format(message, args);
} else {
return message;
}
}
}
在代码里,使用 I18n.get("register.operateSucc") 即可。
public class StageController {
private Map stages = new HashMap<>();
private Map controllers = new HashMap<>();
public void addStage(String name, Stage stage) {
this.stages.put(name, stage);
}
public Stage getStageBy(String name) {
return this.stages.get(name);
}
public void setPrimaryStage(String name, Stage stage) {
this.addStage(name, stage);
}
public Stage loadStage(String name, String resource, StageStyle... styles) {
Stage result = null;
try{
URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
FXMLLoader loader = new FXMLLoader(url);
loader.setResources(ResourceBundle.getBundle("i18n/message"));
Pane tmpPane = (Pane)loader.load();
ControlledStage controlledStage = (ControlledStage)loader.getController();
this.controllers.put(name, controlledStage);
Scene tmpScene = new Scene(tmpPane);
result = new Stage();
result.setScene(tmpScene);
for (StageStyle style:styles) {
result.initStyle(style);
}
this.addStage(name, result);
}catch(Exception e) {
e.printStackTrace();
}
return result;
}
@SuppressWarnings("unchecked")
public T load(String resource, Class clazz) {
try{
URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
FXMLLoader loader = new FXMLLoader(url);
return (T)loader.load();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
@SuppressWarnings("unchecked")
public T load(String resource, Class clazz, ResourceBundle resources) {
try{
URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
return (T)FXMLLoader.load(url, resources);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public Stage setStage(String name) {
Stage stage = this.getStageBy(name);
if (stage == null) {
return null;
}
stage.show();
return stage;
}
public boolean switchStage(String toShow, String toClose) {
getStageBy(toClose).close();
setStage(toShow);
return true;
}
public void closeStge(String name) {
Stage target = getStageBy(name);
target.close();
}
public boolean unloadStage(String name) {
return this.stages.remove(name) != null;
}
public ControlledStage getController(String name) {
return this.controllers.get(name);
}
}
全部代码已在github上托管
服务端代码请移步 --> netty聊天室服务器
客户端代码请移步 --> netty聊天室客户端