JavaFX TableView自定义单元格渲染拆分菜单按钮 [英] JavaFX TableView custom cell rendering split menu button

查看:330
本文介绍了JavaFX TableView自定义单元格渲染拆分菜单按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在java fx表视图组件中使用自定义单元格渲染时出现问题。我能够渲染分割菜单按钮,但只能从第二行表格渲染。

i've a problem with a custom cell render in a java fx table view component. I'm able to render the split menu button, but is only rendered from second row of table.

下面我将创建的代码生成该图像。

Below i put the code created to generate that image.

SplitMenuButtonApp.java

package com.example.splimenubtn;

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class SplitMenuButtonApp extends Application {

 private class Contact {

 private StringProperty firstName;
 private StringProperty lastName;

 public Contact() {}

 public Contact(String fName, String lName) {
  firstName = new SimpleStringProperty(fName);
  lastName = new SimpleStringProperty(lName);
 }

 public String getFirstName() {
  return firstName.get();
 }

 public void setFirstName(String fName) {
  firstName.set(fName);
 }

 public StringProperty firstName() {
  return firstName;
 }

 public String getLastName() {
  return lastName.get();
 }

 public void setLastName(String lName) {
  lastName.set(lName);
 }

 public StringProperty lastName() {
  return lastName;
 }
}

private ObservableList<Contact> data;
protected List<MenuItemFactory<Contact>> menuItemsList;
private TableView<Contact> table;

@Override
public void start(Stage primaryStage) throws Exception {
 // Init data list
 data = FXCollections.observableArrayList();
 data.add(new Contact("Mickey", "Mouse"));
 data.add(new Contact("Donald", "Duck"));
 data.add(new Contact("Fantasy", "Name"));
 initMenuButton();
 SplitMenuButtonFactory<Contact> sMBtn = new SplitMenuButtonFactory<>();
 sMBtn.setMenuItems(menuItemsList);
 SplitMenuButton actions = sMBtn.buildButton();
 // Build the list
 table = new TableView<>();
 TableColumn<Contact, String> col = new TableColumn<>("First Name");
 col.setCellValueFactory(c -> c.getValue().firstName);
 table.getColumns().add(col);
 col = new TableColumn<>("Last Name");
 col.setCellValueFactory(c -> c.getValue().lastName);
 table.getColumns().add(col);
 TableColumn<Contact, SplitMenuButton> aCol = new TableColumn<>("Action");
 aCol.setCellValueFactory(new PropertyValueFactory<>(""));
 aCol.setCellFactory(new ButtonCellFactory<>(actions));
 table.getColumns().add(aCol);
 table.setItems(data);
 AnchorPane root = new AnchorPane();
 AnchorPane.setTopAnchor(table, 5.0);
 AnchorPane.setRightAnchor(table, 5.0);
 AnchorPane.setBottomAnchor(table, 5.0);
 AnchorPane.setLeftAnchor(table, 5.0);
 root.getChildren().add(table);
 Scene s = new Scene(root, 600d, 300d);
 primaryStage.setScene(s);
 primaryStage.setTitle("Split menu button on table row");
 primaryStage.show();
}

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

private void initMenuButton() {
 if (menuItemsList == null) {
  menuItemsList = new ArrayList<>();
  menuItemsList.add(new MenuItemFactory<Contact>(MenuItemActions.EDIT, "Edit", true).setDataList(table));
menuItemsList.add(new MenuItemFactory<Contact>(MenuItemActions.DELETE, "Delete", false).setDataList(table));
 }
}

}

MenuItemActions.java
package com.example.splimenubtn;

MenuItemActions.java package com.example.splimenubtn;

public enum MenuItemActions {
/**
 * Detail item
 */
 DETAILS,
/**
 * Edit/Update item
 */
EDIT,
/**
 * Delete item
 */
 DELETE;
}

MenuItemFactory.java

package com.example.splimenubtn;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableView;

public class MenuItemFactory<S> {
 private MenuItemActions itemType;
 private String itemLbl;
 private TableView<S> table;
 private boolean defaultAction;

 public MenuItemFactory() {}

 public MenuItemFactory(MenuItemActions itemType, String itemLabel, boolean dA) {
  this.itemType = itemType;
  itemLbl = itemLabel;
  defaultAction = dA;
 }

 public MenuItemFactory<S> setDataList(TableView<S> t) {
  table = t;
  return this;
 }

 public boolean isDefault() {
  return defaultAction;
 }

 public MenuItem buildMenuItem() {
  MenuItem mI = new MenuItem();
  switch (itemType) {
   case DETAILS:
    mI.setText(itemLbl);
    mI.setOnAction(handleDetails());
   break;
   case EDIT:
    mI.setText(itemLbl);
    mI.setOnAction(handleEdit());
   break;
   case DELETE:
    mI.setText(itemLbl);
    mI.setOnAction(handleDelete());
   break;
   default:
   break;
  }
  return mI;
 }

 private EventHandler<ActionEvent> handleDetails() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** DETAIL REQUESTED ***");
   }
  };
 }

 private EventHandler<ActionEvent> handleEdit() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** EDIT REQUESTED ***");
   }
  };
 }

 private EventHandler<ActionEvent> handleDelete() {
  return new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent aE) {
    System.out.println("*** DELETE REQUESTED ***");
   }
  };
 }
}

ButtonCellFactory.java

package com.example.splimenubtn;

import javafx.scene.control.ContentDisplay;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;

 public class ButtonCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {

 private SplitMenuButton btn;

 public ButtonCellFactory() {}

 public ButtonCellFactory(SplitMenuButton b) {
  btn = b;
 }

 @Override
 public TableCell<S, T> call(TableColumn<S, T> param) {
  return new TableCell<S, T>() {
   @Override
   public void updateItem(T item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
     setGraphic(null);
     setText(null);
    } else {
     setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
     setGraphic(btn);
    }
   }
  };
 }
}

SpliMenuButtonFactory.java

package com.example.splimenubtn;

import java.util.List;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitMenuButton;

public class SplitMenuButtonFactory<T> {

private List<MenuItemFactory<T>> menuItems;

public SplitMenuButtonFactory() {}

public SplitMenuButtonFactory<T> setMenuItems(List<MenuItemFactory<T>> items) {
  menuItems = items;
  return this;
 }

 public SplitMenuButton buildButton() {
  SplitMenuButton menuBtn = new SplitMenuButton();
  for (MenuItemFactory<?> mIF : menuItems) {
   MenuItem btn = mIF.buildMenuItem();
   if (mIF.isDefault()) {
    menuBtn.setText(btn.getText());
    menuBtn.setOnAction(btn.getOnAction());
   }
   menuBtn.getItems().add(btn);
  }
  return menuBtn;
 }
}

如图所示,使用此代码我能够创建spli菜单按钮并将其添加到ta表中,但仅在最后一行呈现。

As you see in the image, with this code i'm able to create the spli menu button and add it to ta table, but is only rendered on last row.

我需要建议渲染分割菜单按钮其他行,任何帮助表示赞赏。

I need suggestion to render the split menu button in the other row, any help is appreciated.

推荐答案

因为你在每个单元格中使用相同的按钮,所以它只设置一个按钮最后一个单元格值。

Cause you have use the same button in every cell, So it's set a button only last of the cell Value.

在SplitMenuButtonApp类中删除此行

Remove this line in SplitMenuButtonApp class

 SplitMenuButton actions = sMBtn.buildButton();

并替换此行

aCol.setCellFactory(新的ButtonCellFactory<>(操作));

到下面的代码

Callback<TableColumn<Contact, SplitMenuButton>, TableCell<Contact, SplitMenuButton>> actionsCol = new Callback<TableColumn<Contact, SplitMenuButton>, TableCell<Contact, SplitMenuButton>>() {
                @Override
                public TableCell call(final TableColumn<Contact, SplitMenuButton> param) {
                    final TableCell<Contact, SplitMenuButton> cell = new TableCell<Contact, SplitMenuButton>() {
                        SplitMenuButton actions = sMBtn.buildButton();
                        @Override
                        public void updateItem(SplitMenuButton item, boolean empty) {
                            super.updateItem(item, empty);
                            if (empty) {
                                setGraphic(null);
                                setText(null);
                            } else {
                                setGraphic(actions);
                                setText(null);
                            }
                        }
                    };
                    return cell;
            }
 };

aCol.setCellFactory(actionsCol);

我希望此代码适合您:)

I hope this code is working for you:)

这篇关于JavaFX TableView自定义单元格渲染拆分菜单按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆