【问题标题】:javafx cannot access button in custom listcelljavafx 无法访问自定义列表单元中的按钮
【发布时间】:2017-03-12 13:24:04
【问题描述】:

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

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

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

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

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

因此,我发现从 plusbtn 获得鼠标单击操作的唯一方法是使用同一类 (NamePriceCell) 中的 EventHandler。即使我可以根据对 NamePriceCell 按钮的点击来填充数组列表(NamePriceCell 调用另一个类中的静态方法,其中包含静态数组列表),并且我可以通过让用户单击另一个来在我的有序列表视图中获得结果TableMain StackPane 的按钮节点,当用户单击 NamePriceCell 按钮时,我找不到这样做的方法。 我尝试过的事情之一是在 TablesMainController 中设置一个静态方法,我可以从 NamePriceCell EventHandler 访问它(但是我必须使ordereditemslist的持有者节点静态,即使这样,它也没有工作), 为包含ordereditemslist的VBox编写一个单独的fxml,并使用相应的单独控制器,这样我就可以有一个方法来创建ordereditemslist并设置cellFactory(但即使fxml文件正确显示并从NamePriceCell的EventHandler调用该方法也可以- 显示 System.out - 它不会影响屏幕上的任何内容,而不是有序项目列表,甚至不会影响我测试的标签。

相对而言,我是 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());
    }

...
}

【问题讨论】:

  • 我得到了 StringProperty 的解决方案,它可以从我的问题中提到的帖子连接到监听器。我知道这不是最好的东西,更像是一个黑客,所以如果有更好的解决方案,请分享。我很乐意接受任何好主意作为答案。

标签: java javafx javafx-2


【解决方案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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多