javafx无法访问自定义listcell

时间:2016-10-30 02:48:42

标签: java javafx javafx-2

问题的核心是我无法从另一个类(此处为NamePriceCell)刷新或更改场景节点(此处为TablesMain)的内容。

我正在使用主StackPane(TableMainController扩展StackPane)构建和应用程序,其中包含其他节点,其中一些是ListView。在一个特定的ListView(比如'readitemslistview')中,我创建了一个自定义ListCell(公共类NamePriceCell extends ListCell),这个NamePriceCell listcell包含一个按钮(plusbtn)。当用户点击plusbtn时,一个arraylist(比如'selecteditemslist')会填满特定单元格中显示的项目,同时堆栈窗口中的另一个listview(比如'ordereditemslist')应该触发显示'selecteditemslist'arraylist的内容。

我还没有找到从主控制器引用NamePriceCell的plusbtn的方法。而且这篇文章 Get ListCell via ListView

  

不幸的是,现在没有API可以通过索引获取List Cell   获取ListView的所有子项(listcells)。

让我远离了这种尝试(我无法理解那里提供的解决方案是否适合我的需求,因为我不想刷新相同的列表视图而是来自同一场景中的另一个)。

因此,我发现从plusbtn获取鼠标单击操作的唯一方法是使用同一类中的EventHandler(NamePriceCell)。即使我可以根据NamePriceCell按钮的点击(NamePriceCell在另一个类中使用静态arraylist调用静态方法)来填充arraylist,我可以通过让用户点击另一个来获得我的orderedlistview中的结果TableMain StackPane的按钮节点,当用户点击NamePriceCell按钮时,我找不到办法。 我试过的事情是在TablesMainController中设置一个静态方法,我可以从NamePriceCell EventHandler访问它(但是我必须使ordereditemslist的holder节点静态,即便如此,它还没有工作), 为包含ordereditemslist的VBox写一个单独的fxml和一个相应的独立控制器,这样我就可以在那里创建一个方法来创建ordereditemslist并设置cellFactory(但即使fxml文件正确显示并从NamePriceCell的EventHandler中调用方法也可以 - 显示System.out - 它不会影响屏幕上的任何内容,也不会影响ordereditemslist,甚至不会影响我测试的标签。

我是一个相对java的新手,尤其是javafx。非常需要和感谢您的帮助。

我最后一种方法的代码如下:

VboxList.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.VBox?>
<VBox>
    <Label text="Label" id="label1"/>
    <Label text="Label" id="label2"/>
    <Label text="sdfsdf" id="label3"/>
    <ListView nodeOrientation="LEFT_TO_RIGHT" id="orderedlist" prefHeight="200.0" prefWidth="200.0"  />
</VBox>

VboxListController.java

public class VboxListController extends VBox{
    FXMLLoader fxmlLoader;
    @FXML
    private Label label1;

    @FXML
    private Label label2;

    @FXML
    private ListView<OrderItem> orderedlist;

    public VboxListController() {
        fxmlLoader = new FXMLLoader(getClass().getResource("fxml/VboxList.fxml"));
        //fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public void getorderedlist(ArrayList<OrderItem> chosenitems){
        ObservableList<OrderItem> myObservableList = FXCollections.observableList(chosenitems);

        this.getChildren().remove(orderedlist);

        orderedlist = new ListView<>();
        orderedlist.setItems(myObservableList);
        orderedlist.setCellFactory(new Callback<ListView<OrderItem>, ListCell<OrderItem>>() {

            @Override
            public ListCell<OrderItem> call(ListView<OrderItem> p) {

                ListCell<OrderItem> cell = new ListCell<OrderItem>() {

                    @Override
                    protected void updateItem(OrderItem dataobj, boolean bln) {
                        super.updateItem(dataobj, bln);
                        if (dataobj != null) {
                            setText(dataobj.read_item_name);
                        }
                    }

                };
                return cell;
            }
        });
        this.getChildren().add(orderedlist);
        orderedlist.setItems(null);
        orderedlist.setItems(myObservableList);
        label1 = null;
        this.getChildren().remove(label1);
        label1 = new Label();
label1.setText("oooops!");
        System.out.println("sdf");
        this.getChildren().add(label1);


    }


}

NamePriceCell.java

public class NamePriceCell extends ListCell<ReadItemChoiceObj> {
    int count=0;
    @FXML
    Label namelbl;

    @FXML
    Label pricelbl;

    @FXML
    Button plusbtn;

    @FXML
    Region spacer;

    @FXML
    HBox cellHbox;

    FXMLLoader mLLoader;

    ReadItemChoiceObj readitem;
    ArrayList<ReadItemChoiceObj> chosenreaditems;
    @Override
    protected void updateItem(ReadItemChoiceObj readitem, boolean empty) {
        super.updateItem(readitem, empty);
        chosenreaditems = new ArrayList<>();

        if(empty || readitem == null) {

            setText(null);
            setGraphic(null);

        } else {

            this.readitem = readitem;
            if (mLLoader == null) {
                mLLoader = new FXMLLoader(getClass().getResource("fxml/NamePriceCell.fxml"));
                mLLoader.setController(this);
                try {
                    mLLoader.load();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }


            namelbl.setText(readitem.getname());
            namelbl.setMaxWidth(500);
            pricelbl.setText(String.format("%.2f", readitem.getprice()));
            pricelbl.setStyle("-fx-font: 8pt  \"Arial\";");
            pricelbl.setMaxWidth(40);
            spacer.setMaxWidth(10);
            spacer.setMinWidth(10);
            plusbtn.setMaxWidth(20);
            cellHbox.setHgrow(namelbl, Priority.ALWAYS);

            cellHbox.setAlignment(Pos.BASELINE_LEFT);

            setText(null);
            setGraphic(cellHbox);

            plusbtn.setOnMouseClicked(whattodohandler);
        }

    }



    EventHandler<MouseEvent> whattodohandler = new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            ChosenItemsStat.getplusbtnclicked(readitem);
            ChosenItemsStat chos = new ChosenItemsStat();

            count+=1;
            plusbtn.setText(String.valueOf(count));
            new VboxListController().getorderedlist(chos.sendchosenlist());
        }
    };

}

和TablesMain.java的一部分

 @FXML
    Label label1;

    @FXML
    BorderPane borderpane;

    @FXML
    Pane tablepane;

    @FXML
    ListView<DataObj> tabcatlist;

    @FXML
     VBox VboxList;

    @FXML
     VboxListController vboxListController;

  /*  @FXML
    ListView<OrderItem> orderedlist;*/

    @FXML
    VBox leftVbox;

 public TablesMain(Order order) {
        this.order = order;
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml/tablesmain.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {

            throw new RuntimeException(exception);
        }

        ObservableList<DataObj> myObservableList = FXCollections.observableList(gettable_categories());
        tabcatlist.setItems(myObservableList);
        tabcatlist.setCellFactory(new Callback<ListView<DataObj>, ListCell<DataObj>>() {

            @Override
            public ListCell<DataObj> call(ListView<DataObj> p) {

                ListCell<DataObj> cell = new ListCell<DataObj>() {

                    @Override
                    protected void updateItem(DataObj dataobj, boolean bln) {
                        super.updateItem(dataobj, bln);
                        if (dataobj != null) {
                            setText(dataobj.getname());
                        }
                    }

                };
                return cell;
            }
        });
        if (table_categoryID == 0) table_categoryID = tablecategories.get(0).getid();
        gettables(table_categoryID);
    }

 private void make_readitemlist(int itemcategoryID) {
             readitems = new ArrayList<>();


            .... the readitems  arraylist gets filled up...


        ObservableList<ReadItemChoiceObj> myObservableList = FXCollections.observableList(readitems);
        readitemlist.setItems(myObservableList);

        readitemlist.setCellFactory(new Callback<ListView<ReadItemChoiceObj>,
                                            ListCell<ReadItemChoiceObj>>() {
                                        @Override
                                        public ListCell<ReadItemChoiceObj> call(ListView<ReadItemChoiceObj> list) {
                                            readitemlistcell = new NamePriceCell();

                                            return readitemlistcell;
                                        }

                                    }
        );

        readitemlist.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                ReadItemChoiceObj dataobj = (ReadItemChoiceObj) readitemlist.getSelectionModel().getSelectedItem();
                System.out.println(String.valueOf(dataobj.getid()));

               // showorderedlist(new ChosenItemsStat().sendchosenlist());
            }
        });
        System.out.println(readitemlist.cellFactoryProperty().getClass().toString());
    }

...
}

1 个答案:

答案 0 :(得分:1)

由于已经差不多5个月没有其他贡献,我想发布我的解决方案作为答案。这不是我的,而是受到我的问题中提到的帖子的启发(或复制)(或另一个,现在我不记得了,请原谅我可能的错误信用)。 更准确地说,我在TableMain文件(主要的Controller类)中创建了一个静态StringProperty。每次点击plusbtn(扩展ListCell的NamePriceCell类)时,在TableMain控制器类的静态StringProperty中强制转换为字符串的随机数。在这个类中,StringProperty添加了一个ChangeListener,它反过来触发(从主控制器内部 - 这是线索)刷新有序列表(必须用添加的项刷新列表视图)。

NamePriceCell.java

public class NamePriceCell extends ListCell<ReadItemChoiceObj> {
@FXML
Label namelbl;

@FXML
Label pricelbl;

@FXML
Button plusbtn;

@FXML
Region spacer;

@FXML
HBox cellHbox;

FXMLLoader mLLoader;

ReadItemChoiceObj readitem;

@Override
protected void updateItem(ReadItemChoiceObj readitem, boolean empty) {
    super.updateItem(readitem, empty);

    if(empty || readitem == null) {

        setText(null);
        setGraphic(null);

    } else {

        this.readitem = readitem;
        if (mLLoader == null) {
            mLLoader = new FXMLLoader(getClass().getResource("fxml/NamePriceCell.fxml"));
            mLLoader.setController(this);
            try {
                mLLoader.load();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        namelbl.setText(readitem.getname());
        namelbl.setMaxWidth(500);
        pricelbl.setText(String.format("%.2f", readitem.getprice()));
        pricelbl.setStyle("-fx-font: 8pt  \"Arial\";");
        pricelbl.setMaxWidth(40);
        spacer.setMaxWidth(10);
        spacer.setMinWidth(10);
        plusbtn.setMaxWidth(20);
        cellHbox.setHgrow(namelbl, Priority.ALWAYS);

        cellHbox.setAlignment(Pos.BASELINE_LEFT);

        setText(null);
        setGraphic(cellHbox);

        plusbtn.setOnMouseClicked(whattodohandler);
    }

}



EventHandler<MouseEvent> whattodohandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {


        OrderItem orderitem = new OrderItem();
        orderitem.read_item_name = readitem.getname();
        orderitem.read_item_price=readitem.getprice();
        orderitem.read_itemID=readitem.getid();
        orderitem.choice_name_list = new ArrayList<String>();
        orderitem.choice_price_list = new ArrayList<Float>();
        orderitem.choice_id_list = new ArrayList<Integer>();

        ChosenItemsStat.getplusbtnclicked(orderitem);
        Random rand = new Random();
        TablesMain.stringProperty.setValue(String.valueOf(rand));
    }
};

}

ChosenItemsStat.java(接收列表添加内容的静态类)

public class ChosenItemsStat {
static ArrayList<OrderItem> chosenorderitemsstat  = new ArrayList<>();
static void getplusbtnclicked(OrderItem orderitem){
    chosenorderitemsstat.add(orderitem);
    }
}

我没有使用VboxList.fxml或VboxListController.java,因为我将它包含在TablesMain.java中(见下文)

TablesMain.java(在问题中,但有这个添加)

stringProperty = new SimpleStringProperty();
    stringProperty.setValue("");
    tablelbl.setText(stringProperty.getValue());
    stringProperty.addListener(new ChangeListener(){
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {
            showselectedlist();
        }
    });

而通过更改StringProperty值调用的showselectedlist()是下面的那个(在此方法中,单元格正在被删除的类中被构造(VboxListController)

private void showselectedlist(){
    orderitems.addAll(ChosenItemsStat.chosenorderitemsstat);
    ChosenItemsStat.chosenorderitemsstat.clear();
    ListView<OrderItem> selectedlist = new ListView<>();
    ObservableList<OrderItem> myObservableList = FXCollections.observableList(orderitems);
    selectedlist.setItems(myObservableList);
    selectedlist.setMaxWidth(220);
    selectedlist.setCellFactory(new Callback<ListView<OrderItem>, ListCell<OrderItem>>() {

        @Override
        public ListCell<OrderItem> call(ListView<OrderItem> p) {
            ListCell<OrderItem> cell = new ListCell<OrderItem>(){
                OrderedCell ordcell= new OrderedCell();
                @Override
                protected void updateItem(OrderItem orderitem, boolean bln) {
                    super.updateItem(orderitem, bln);
                    if (orderitem != null) {
                        Float price = ordcell.getitemTempPrice(orderitem,orderitem.read_item_price);

                        HBox namepriceHbox = new HBox();
                        Label lblprice= new Label(String.format("%.2f",price));
                        Region betweenregion = new Region();
                        Label lblname = new Label();

                        lblname.setText(orderitem.read_item_name );
                        lblname.setStyle("-fx-font: 10pt  \"Arial\";-fx-font-weight:bold");

                        namepriceHbox.setHgrow(betweenregion, Priority.ALWAYS);
                        namepriceHbox.getChildren().addAll(lblname,betweenregion,lblprice);

                        VBox allVbox = new VBox();
                        Text lblchoices = new Text();

                        String choices = ordcell.choicestostring(orderitem);
                        lblchoices.setText(choices);
                        lblchoices.setWrappingWidth(listpane.getLayoutBounds().getWidth());

                        if (choices.equals("")) allVbox.getChildren().addAll(namepriceHbox);
                        else allVbox.getChildren().addAll(namepriceHbox, lblchoices);

                        double namepricewidth = listpane.getLayoutBounds().getWidth();
                        System.out.println("namepricewidth is "+String.valueOf(namepricewidth));

                        //allVbox.setPadding(new Insets(10,0,10,0));
                        setGraphic(allVbox);
                    }
                }

            };
            return cell;
        }
    });
    listpane.getChildren().add(selectedlist);
}