git仓库
https://gitee.com/ichiva_admin/vue4j-core.git
介绍
vue for java (vue4j) 是一个采用vue设计思想Java GUI框架,
软件在Javafx基础上扩展了双向绑定和组件化,实现了vue基于数据驱动的设计思想.
使用vue4j可以带来以下优势:
- 更直观的组件化,更容易构建复杂的GUI
- 数据驱动,避免Javafx必须使用主线程刷新UI带来的复杂性,可以更好的专注于业务
安装教程
vue4j 依赖Java8提供的Javafx
采用maven构建
com.gome
vue4j-core
8.0-PREVIEW
xwintop-maven
https://gitee.com/ichiva_admin/vue4j-core/tree/v8/repository
使用说明
- hello world! 直接把xml写在代码中有点蠢,后续Java支持文本块的版本中还是可以尝试一下的,接下来我们会把xml放在fxml文件中试试
public class L1Bind extends Application {
@Override
public void start(Stage stage) throws Exception {
Scene scene = Vue4jLoader.loadScene(new L1BindComponent(), 320, 200);
stage.setScene(scene);
stage.setTitle("直接fxml方式,小型组件勉强可用");
stage.show();
}
}
class L1BindComponent extends AbstractVue4jComponent {
@Override
public CharSequence render() {
imports(VBox.class, Insets.class, Label.class, Button.class);
return "\n" +
" \n" +
" ";
}
@FXML
StringProperty welcomeText = new SimpleStringProperty();
@FXML
void onHelloButtonClick(){
welcomeText.set("hello world!");
}
}
- 简单的数据绑定
Java代码
public class L1Z2Bind extends Application {
@Override
public void start(Stage stage) throws Exception {
Scene scene = Vue4jLoader.loadScene(new L1Z2BindComponent(),320,600);
stage.setScene(scene);
stage.setTitle("简单的数据绑定");
stage.show();
}
}
@FXMLPath("/base/l1z2-view.fxml")
class L1Z2BindComponent extends AbstractVue4jComponent {
@FXML
StringProperty message = new SimpleStringProperty("简单数据绑定");
}
l1z2-view.fxml代码
- 样式绑定
L3Style 代码
public class L3Style extends Application {
@Override
public void start(Stage stage) throws Exception {
L3StyleComponent component = new L3StyleComponent();
Scene scene = Vue4jLoader.loadScene(component,320,600);
stage.setScene(scene);
stage.setTitle("样式绑定");
stage.show();
}
}
L3StyleComponent 代码
@FXMLPath("/base/l3-view.fxml")
public class L3StyleComponent extends AbstractVue4jComponent {
@FXML
StringProperty style = new SimpleStringProperty("-fx-text-fill: red;");
@FXML
void addBorder(){
style.set(style.get() + "-fx-border-width: 1;-fx-border-style: solid;-fx-border-color: red");
}
}
l3-view.fxml
- 类绑定
L3Z1StyleClass代码,为stage添加样式表
public class L3Z1StyleClass extends Application {
@Override
public void start(Stage stage) throws Exception {
L3Z1StyleClassComponent component = new L3Z1StyleClassComponent();
Scene scene = Vue4jLoader.loadScene(component,320,600);
scene.getStylesheets().add(L3Z1StyleClass.class.getResource("/css/LabeledTextTest.css").toExternalForm());
stage.setScene(scene);
stage.setTitle("类绑定");
stage.show();
}
}
LabeledTextTest.css 样式表
.yellowBackground{
-fx-background-color: yellow;
}
.red{
-fx-text-fill: red;
}
.redBorder{
-fx-border-width: 1;
-fx-border-style: solid;
-fx-border-color: red
}
动态绑定类型
@FXMLPath("/base/l3z1-view.fxml")
public class L3Z1StyleClassComponent extends AbstractVue4jComponent {
@FXML
StringProperty message = new SimpleStringProperty("类型绑定");
@FXML
List classList = FXCollections.observableArrayList();
@FXML
public void setRed(){
String red = "red";
if(!classList.contains(red)){
classList.add(red);
}else {
classList.remove(red);
}
}
@FXML
public void yellowBackground(){
String red = "yellowBackground";
if(!classList.contains(red)){
classList.add(red);
}else {
classList.remove(red);
}
}
@FXML
public void setBorder(){
String red = "redBorder";
if(!classList.contains(red)){
classList.add(red);
}else {
classList.remove(red);
}
}
}
l3z1-view.fxml
- if条件渲染,条件渲染需要改变dom,因此需要主动调用update()
@FXMLPath("/base/l4-view.fxml")
public class L4IfComponent extends AbstractVue4jComponent {
@FXML
boolean flag = true;
@FXML
public void toggle(){
flag = !flag;
update();
}
}
l4-view.fxml
-
for指令,集合渲染需要改变dom,因此需要主动调用update(),本列中可以实现动态添加群众演员
L5ForComponent代码
@FXMLPath("/base/l5-view.fxml")
public class L5ForComponent extends AbstractVue4jComponent {
@FXML
public List actors = new ArrayList<>(Arrays.asList(
new Actor(1L,"张飞",28),
new Actor(2L,"关羽",32),
new Actor(3L,"刘备",36)
));
@FXML
void addActor(){
long id = System.currentTimeMillis();
actors.add(new Actor(id,"群众" + id,22));
update();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Actor{
Long id;
String name;
int age;
}
}
l5-view.fxml
- for可对list和map集合进行渲染,list遍历出来的是列表的序号,map遍历出来的是key值,一般都需要配合表达式使用,表达式相当于在外部调用控制器的属性和方法,因此必须设置为public
- 对map的遍历
L5Z1ForComponent代码,LinkedHashMap可以保证map集合的顺序
@FXMLPath("/base/l5z1-view.fxml")
public class L5Z1ForComponent extends AbstractVue4jComponent {
@FXML
public Map actors = new LinkedHashMap(){
{
put("张飞",new Actor(1L,"张飞",28));
put("关羽",new Actor(2L,"关羽",32));
put("刘备",new Actor(3L,"刘备",36));
}
};
@FXML
void addActor(){
long id = System.currentTimeMillis();
String name = "群众" + id;
actors.put(name,new Actor(id, name,22));
update();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Actor{
Long id;
String name;
int age;
}
}
l5z1-view.fxml
- 直接遍历数字
- template 遍历
- 监听数据编号
L6ListenerComponent代码
@FXMLPath("/base/l6-view.fxml")
public class L6ListenerComponent extends AbstractVue4jComponent {
@FXML
StringProperty counter = new SimpleStringProperty("0"){
{
addListener((observableValue, number, newNumber) -> {
System.out.println("数字发生变化:" + newNumber);
});
}
};
@FXML
void add(){
int n =Integer.parseInt(counter.get()) + 1;
counter.set("" + n);
}
}
l6-view.fxml
- 事件处理,这个我们已经很熟悉了
@FXMLPath("/base/l7-view.fxml")
public class L7ActionComponent extends AbstractVue4jComponent {
@FXML
public StringProperty counter = new SimpleStringProperty("0");
@FXML
void add(){
int i = Integer.parseInt(counter.get());
counter.set("" + ++i);
}
public void sub(){
int i = Integer.parseInt(counter.get());
counter.set("" + --i);
}
}
- l7-view.fxml
- 组件
定义一个简单的按钮组件,我们这里直接把fxml代码写在代码中
public class L11RedButton extends AbstractVue4jComponent {
@Override
public CharSequence render() {
imports(Button.class);
return "";
}
@FXML
void hi(){
System.out.println("红色按钮被点击");
}
}
使用自定义的组件,我们这里还是直接把fxml代码写在代码中
public class L11ComponentBox extends AbstractVue4jComponent {
@Override
public CharSequence render() {
imports(VBox.class, Label.class,L11RedButton.class);
return "\n" +
" \n" +
" \n" +
" ";
}
}
- 组件传参,复杂一点的组件就不方便写在代码里了
定义一个带标签的输入框组件,重新setProps方法接收参数
@FXMLPath("/comp/label-text-field-view.fxml")
public class L11Z1LabelTextField extends AbstractVue4jComponent {
@FXML
StringProperty labelText;
@FXML
StringProperty fieldText;
@Override
public void setProps(Map props) {
super.setProps(props);
this.labelText = (StringProperty) props.get("labelText");
this.fieldText = (StringProperty) props.get("fieldText");
}
}
label-text-field-view.fxml
使用这个组件,并给组件传递参数
@FXMLPath("/comp/l11z2-view.fxml")
public class L11Z2Box extends AbstractVue4jComponent {
@FXML
StringProperty labelText = new SimpleStringProperty("父组件参数");
@FXML
StringProperty fieldText = new SimpleStringProperty("父组件参数值");
}
使用props传递参数
更多示例可以在源代码的test中查看
git仓库
https://gitee.com/ichiva_admin/vue4j-core.git
参与贡献
- Fork 本仓库
- 新建 Feat_xxx 分支
- 提交代码
- 新建 Pull Request