- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想要实现的目标是或多或少拥有 Sale 对象,当它扩展为在该 Sale 对象下显示 SaleTransaction 对象时。类似于 Code Project 的图像中显示了想要的内容
除了读取之外,我还可以执行其他 CRUD 功能(即创建、更新和删除)。
我尝试使用 TreeTableView 来实现它,如下所示:
List<CreditSale> lstData = new ArrayList<CreditSale>(creditsaleservice.findAllCreditSales());
TreeItem root = new TreeItem<>();
for (CreditSaleTransaction cst : lstData.get(0).getCreditSaleTransaction()) {
root.getChildren().addAll(new TreeItem<>(cst));
}
TreeTableColumn<CreditSaleTransaction, Product> productColumn = new TreeTableColumn<>("Product Name");
productColumn.setPrefWidth(150);
productColumn.setEditable(true);
productColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<CreditSaleTransaction, Product> p)
-> new ReadOnlyObjectWrapper<>(p.getValue().getValue().getProduct()));
TreeTableColumn<CreditSaleTransaction, Float> quantityColumn = new TreeTableColumn<>("Quantity");
quantityColumn.setPrefWidth(150);
quantityColumn.setEditable(true);
quantityColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<CreditSaleTransaction,Float> p)
-> new ReadOnlyObjectWrapper<>(p.getValue().getValue().getAmount()));
TreeTableColumn<CreditSaleTransaction, Float> unitPColumn = new TreeTableColumn<>("Unit Price");
unitPColumn.setPrefWidth(150);
unitPColumn.setEditable(true);
unitPColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<CreditSaleTransaction,Float> p)
-> new ReadOnlyObjectWrapper<>(p.getValue().getValue().getUnitPrice()));
TreeTableView<CreditSaleTransaction> treeTableView = new TreeTableView<>();
treeTableView.setRoot(root);
treeTableView.getColumns().addAll(productColumn,quantityColumn,unitPColumn);
treeviewanchorpane.getChildren().add(treeTableView);
但没有显示任何内容。
最佳答案
如果您不介意丢失这些内部 header ,则可以使用 TreeTableView
实现类似的输出:
Jewelsea 提供了一个很好的示例来说明如何实现此目的:
<小时/>**自定义实现的建议方法**如果标题很重要,您可以创建自定义控件来获得所需的布局。我的建议是在一个容器中包含多个 TitledPane
,例如 VBox
,其中外部项目作为标题,内部项目作为 TableView
中的内容。 TitledPane
需要 String
作为标题,但通过 setGraphic
和 setContentDisplay
的组合,可以将其更改为 Node
,从而允许您保持一致的布局
这种方法允许多个项目(内部和外部)同时可见。
如果您只想一次看到内部代码,Accordian
将是 VBox
的合适替代方案,因为它只允许在任何给定时间展开一个 TitledPane
本 Oracle 教程涵盖了 TitledPane
和 Accordian
:
(我在本答案末尾提供了一个有关如何实现此方法的示例以及显示输出的图像)
<小时/>**监控变化**JavaFX 提供了 ObservableList
,它会通知监听器任何更改。有效地利用这一点将允许用户界面自动反射(reflect)任何更改。
例如,一个 ListChangeListener
来检测何时添加/删除元素,这已被 here 覆盖。
注意:如果 ObservableList
中的子元素被修改(例如嵌套销售项目中的价格),则可能不会有更新事件。在这种情况下,应将提取器添加到列表中,该列表指定应观察的其他值,如果这些值中的任何一个发生变化,则触发事件更新
还有一系列可用的属性/绑定(bind),这些内容在以下文档中进行了介绍:
(该示例包含如何使用上述内容的示例)
<小时/>在“TableView”上实现 CRUD 功能的建议:Button
栏:您可以将其放置在每个 TableView
或 nestedView
下,使用选定的单元格来确定何时启用按钮以及要修改哪些对象EventHandler
上放置 TableView
:参见 setOnEditCommit() TableView
: 有几个示例可介绍如何创建单击时删除行的自定义 TableCell
。 ContextMenu
示例:
我已尽可能添加了代码注释,但如果有任何问题或建议的改进,请发表评论
NestedTableView
:
public class NestedTableView extends VBox {
private ObservableList<Node> titledPanes = FXCollections.observableArrayList();
private Region parent;
public NestedTableView(Region parent, ObservableList<ProductBundle> bundlesToDisplay){
this.parent = parent;
VBox nestedView = new VBox();
Bindings.bindContentBidirectional(nestedView.getChildren(), titledPanes);
titledPanes.addAll(bundlesToDisplay.stream()
.map(TablePane::new).collect(Collectors.toList()));
getChildren().setAll(createHeader(), nestedView);
getStylesheets().add("CSS/nestedTableViewStyles.css");
}
private HBox createHeader(){
//Set up widths to align with the content headers beneath the header
Label symbol = new Label("#");
symbol.setPrefWidth(25); //Sum of the values used by the "arrow" region
Label productId = new Label("Product Id");
productId.prefWidthProperty().bind(parent.widthProperty().multiply(0.15));
Label productName = new Label("Product Name");
productName.prefWidthProperty().bind(parent.widthProperty().multiply(0.35)); //Give name extra space
Label amount = new Label("Amount");
amount.prefWidthProperty().bind(parent.widthProperty().multiply(0.15));
Label date = new Label("Order Date");
date.prefWidthProperty().bind(parent.widthProperty().multiply(0.15));
Label quantityAvailable = new Label("#Available");
quantityAvailable.prefWidthProperty().bind(parent.widthProperty().multiply(0.15));
HBox header = new HBox(symbol, productId, productName, amount, date, quantityAvailable);
header.getStyleClass().add("header");
return header;
}
private class TablePane extends TitledPane {
private ProductBundle productBundle;
private HBox header;
private TableView contentTableView;
private MenuItem addToBundle, deleteBundle;
public TablePane(ProductBundle productBundle){
this.productBundle = productBundle;
setupMenuItems();
setupContentHeader();
setGraphic(header);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
if(!productBundle.getBundleItems().isEmpty()){
createTableView();
setContent(contentTableView);
}
//Only display the expandable "arrow" if there is content to display
collapsibleProperty().bind(contentProperty().isNotNull());
//If the "arrow" isn't displayed, pad the area to mimic the arrow being present to align headers
header.paddingProperty().bind(
Bindings.when(collapsibleProperty()).then(Insets.EMPTY).otherwise(new Insets(0,0,0,15)));
/* For testing purposes. With more rows this will clutter the UI
ToDo: add logic to determine how many panes to expand before the viewport has been filled
*/
setExpanded(true);
}
private void setupMenuItems(){
addToBundle = new MenuItem("Add to bundle");
addToBundle.setOnAction(event -> {
//ToDo: Add CRUD create logic here
System.out.println("Add to bundle: " + productBundle.idProperty());
});
deleteBundle = new MenuItem("Delete bundle");
deleteBundle.setOnAction(event -> {
//ToDo: Add CRUD delete logic here
System.out.println("Delete bundle: " + productBundle.idProperty());
});
}
private void setupContentHeader(){
header = new HBox();
//Bind the content header to the root so that it aligned with the initial header
header.prefWidthProperty().bind(parent.widthProperty());
header.maxWidthProperty().bind(parent.widthProperty());
/* Set up each TextField with widths to align with the TableView
Each TextField is editable with the exception of id as it would be the primary key
and amount as it's value is calculated from the sub items */
TextField id = new TextField();
id.setEditable(false);
modifyTextFieldContextMenu(id);
id.textProperty().bind(productBundle.idProperty());
id.prefWidthProperty().bind(header.widthProperty().multiply(0.15));
TextField name = new TextField();
modifyTextFieldForCRUDFunctionality(name);
name.textProperty().bindBidirectional(productBundle.nameProperty());
name.prefWidthProperty().bind(header.widthProperty().multiply(0.35)); //Give name extra space
TextField amount = new TextField();
amount.setEditable(false);
Bindings.bindBidirectional(amount.textProperty(), productBundle.amountProperty(),
new NumberStringConverter(NumberFormat.getCurrencyInstance(Locale.US)));
amount.prefWidthProperty().bind(header.widthProperty().multiply(0.15));
TextField date = new TextField();
modifyTextFieldForCRUDFunctionality(date);
date.textProperty().bind(productBundle.orderDateProperty());
date.prefWidthProperty().bind(header.widthProperty().multiply(0.15));
TextField quantityRemaining = new TextField();
modifyTextFieldForCRUDFunctionality(quantityRemaining);
//Only display a quantity if it's a valid value (to match example screen shot)
quantityRemaining.textProperty().bind(
Bindings.when(productBundle.quantityAvailableProperty().greaterThan(0))
.then(productBundle.quantityAvailableProperty().asString()).otherwise("N/A"));
quantityRemaining.prefWidthProperty().bind(header.widthProperty().multiply(0.15));
header.getChildren().setAll(id, name, amount, date, quantityRemaining);
header.getStyleClass().add("content-header");
}
private void modifyTextFieldContextMenu(TextField textField){
TextFieldSkin skin = new TextFieldSkin(textField){
@Override
public void populateContextMenu(ContextMenu contextMenu) {
super.populateContextMenu(contextMenu);
contextMenu.getItems().add(0, addToBundle);
contextMenu.getItems().add(1, deleteBundle);
contextMenu.getItems().add(2, new SeparatorMenuItem());
}
};
textField.setSkin(skin);
}
private void modifyTextFieldForCRUDFunctionality(TextField textField){
textField.setEditable(true);
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
private String previousText;
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
String currentText = textField.getText();
if(newValue){
previousText = currentText;
}
//ToDo: Add CRUD update logic here
else if(!previousText.equals(currentText)){
System.out.println("Value has been changed from: " + previousText + " to: " + currentText);
}
}
});
}
private void createTableView(){
TableColumn<BundleItem, String> idColumn = new TableColumn<>("#ID");
idColumn.setCellValueFactory(param -> param.getValue().getItem().itemIdProperty());
TableColumn<BundleItem, String> nameColumn = new TableColumn<>("Item");
nameColumn.setCellValueFactory(param -> param.getValue().getItem().itemNameProperty());
TableColumn<BundleItem, String> amountColumn = new TableColumn<>("Amount");
amountColumn.setCellValueFactory(param -> param.getValue().getItem().amountProperty().asString("$%.2f"));
TableColumn<BundleItem, Number> quantityColumn = new TableColumn<>("Qty");
quantityColumn.setCellValueFactory(param -> param.getValue().quantityProperty());
TableView<BundleItem> tableView = new TableView<>(productBundle.getBundleItems());
tableView.setPadding(new Insets(10));
//Equal column widths
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableView.getColumns().setAll(idColumn, nameColumn, amountColumn, quantityColumn);
//Only show visible shows
tableView.setFixedCellSize(30);
tableView.prefHeightProperty().bind(Bindings.size(productBundle.getBundleItems())
.multiply(tableView.getFixedCellSize()).add(tableView.getFixedCellSize()*1.5));
contentTableView = tableView;
}
}
}
销售相关对象:
public class ProductBundle {
private ObservableList<BundleItem> bundleItems = FXCollections.observableArrayList();
private SimpleStringProperty productId, productName, orderDate;
private SimpleDoubleProperty amount = new SimpleDoubleProperty();
private SimpleIntegerProperty quantityAvailable;
private ProductBundle(String productId, String productName, String orderDate, int quantityAvailable){
this.productId = new SimpleStringProperty(productId);
this.productName = new SimpleStringProperty(productName);
this.orderDate = new SimpleStringProperty(orderDate);
this.quantityAvailable = new SimpleIntegerProperty(quantityAvailable);
}
public ProductBundle(String productId, String productName, String orderDate,
int quantityAvailable, ObservableList<BundleItem> bundleItems){
this(productId, productName, orderDate, quantityAvailable);
//Setup an extractor to "Observe" changes on the amount/quantity of any items in the bundle
this.bundleItems = FXCollections.observableArrayList(new Callback<BundleItem, Observable[]>() {
@Override
public Observable[] call(BundleItem param) {
return new Observable[]{param.amountProperty(), param.quantityProperty()};
}
});
this.bundleItems.addAll(bundleItems);
//Calculate the total worth of this bundle
amount.bind(Bindings.createDoubleBinding(()->
bundleItems.stream().collect(Collectors.summingDouble(BundleItem::getAmount)), this.bundleItems)
.multiply(quantityAvailable));
}
public ProductBundle(String productId, String productName, String orderDate,
int quantityAvailable, double amount){
this(productId, productName, orderDate, quantityAvailable);
this.amount.set(amount);
}
public ObservableList<BundleItem> getBundleItems(){
return bundleItems;
}
public SimpleStringProperty idProperty(){
return productId;
}
public SimpleStringProperty nameProperty(){
return productName;
}
public SimpleIntegerProperty quantityAvailableProperty(){
return quantityAvailable;
}
public SimpleStringProperty orderDateProperty(){
return orderDate;
}
public SimpleDoubleProperty amountProperty(){
return amount;
}
public double getAmount(){
return amount.get();
}
}
public class BundleItem {
private Item item;
private SimpleIntegerProperty quantity;
private SimpleDoubleProperty amount = new SimpleDoubleProperty();
public BundleItem(Item item, int quantity){
this.item = item;
this.quantity = new SimpleIntegerProperty(quantity);
amount.bind(item.amountProperty().multiply(quantity));
}
public Item getItem(){
return item;
}
public SimpleIntegerProperty quantityProperty(){
return quantity;
}
public SimpleDoubleProperty amountProperty(){
return amount;
}
public double getAmount(){
return amount.get();
}
}
public class Item {
private SimpleStringProperty itemId, itemName;
private SimpleDoubleProperty amount;
public Item(String itemId, String itemName, double amount){
this.itemId = new SimpleStringProperty(itemId);
this.itemName = new SimpleStringProperty(itemName);
this.amount = new SimpleDoubleProperty(amount);
}
public SimpleStringProperty itemIdProperty(){
return itemId;
}
public SimpleStringProperty itemNameProperty(){
return itemName;
}
public SimpleDoubleProperty amountProperty(){
return amount;
}
public double getAmount(){
return amount.get();
}
public void setAmount(double newValue){
amount.set(newValue);
}
}
nestedTableViewStyles.css:
.header {
-fx-background-color: darkorange;
-fx-pref-height: 30;
-fx-padding: 5 0 0 0;
}
.header > .label {
-fx-text-fill: white;
}
.header > .label, .content-header > .text-field {
-fx-alignment: center;
-fx-text-alignment: center;
}
.content-header > .text-field, .content-header > .text-field:focused {
/* Make the TextField's display similar to a Label */
-fx-background-color: transparent;
}
.content-header, .titled-pane > .title, .table-view {
-fx-background-color: white;
}
.titled-pane > .title {
-fx-border-color: lightgray;
-fx-border-width: 0 0 1 0;
}
.table-view {
-fx-table-cell-border-color: transparent;
}
.table-view .column-header-background {
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
}
.table-view .column-header-background, .table-row-cell {
-fx-background-color: lightgray;
-fx-border-color: gray;
-fx-border-width: 0 0 1 0;
}
.table-view .column-header-background .label {
-fx-background-color: lightgray;
-fx-text-fill: black;
-fx-font-weight: bold;
}
.table-view .column-header {
-fx-background-color: transparent;
}
.table-column {
-fx-alignment: center;
}
用法:
public class NestedTableViewExample extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<ProductBundle> bundles =
FXCollections.observableArrayList(
new ProductBundle("1001456", "Spring Season Gift", "02/14/2015", 1,
FXCollections.observableArrayList(
new BundleItem(new Item("17890", "PS 3", 150.00), 1),
new BundleItem(new Item("17891", "Heart shape ring", 100.00), 1)
)),
new ProductBundle("1001457", "Christmas Season Gift", "04/14/2015", 1,
FXCollections.observableArrayList(
new BundleItem(new Item("17900", "Chocolate Giftbox", 150.00), 1),
new BundleItem(new Item("17901", "Xbox 360", 199.00), 1)
)),
new ProductBundle("1001458", "Birthday Gift", "", 1, 200)
);
VBox root = new VBox();
root.getChildren().setAll(new NestedTableView(root, bundles));
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("Nested TableView example");
primaryStage.show();
}
}
<小时/>**输出:**
关于java - 在 TreeTableView 中显示销售信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37492977/
我的学校项目是创建一个销售和出租产品的电子商务网站。 我的主要问题是我找不到“出租”部分的最佳设计。现在我正在考虑两种设计: 第一个数据库设计建议: 第二条数据库设计建议: 如您所见,两种设计中都有相
如果 Mono 项目成功,它将为非 Windows 平台上的商业软件铺平道路。 我对根据我们现有的 Smoke Vector Graphics (OCaml) 和 F# for Visualizati
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
是否有出售 .net 控件的网站?我似乎找不到任何东西。我想知道是否有人可以将我指向一个站点。我宁愿它不是一个需要提供源代码的网站(如果可以的话,无论如何都包括它们)。 最佳答案 有1个站点CodeC
免责声明:我主要是一名后端开发人员,没有广泛的 FE 知识。 我正在编写一个生成 HTML 的非 SPA Golang Web 应用程序,然后将其发送给用户。因为我想更好地更新和监控我的 Javasc
我尝试了几种不同的方法来从 Magento 中删除测试订单。 使用插件(http://www.magentocommerce.com/magento-connect/asperience-delete
我们有一个 Woocommerce 网站,并在 Facebook 和 Instagram 上转换广告。当潜在客户点击这些广告时,我们的网站将加载到 Facebook 和 Instagram 使用的应用
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 7年前关闭。 Improve this qu
我们已经在数据库中看到了销售数据,但在 Appstore Connect 控制台中看不到任何销售数据。有谁知道什么会导致这种情况吗? 只有当苹果应用内购买的 .purchased 状态回调被触发时,我
假设我有一个应用程序,我可以在其中以 iBook 的形式出售补充内容。无论哪种方式,他们都会收取 30%,但我可以将该应用程序用作销售它的平台。有没有一种方法可以通过应用程序本身销售它,但保留 iBo
我使用 BlueSnap API 通过 PayPal 销售产品。在我的网站上,我将购物者发送到 PayPal,而无需他们填写任何运输详细信息 - 一旦他们登录到 PayPal,我就会从他们的 Blue
最近,中国大型发行商联系了我,他们在越狱设备上拥有自己的“AppStore”。他们也让我通过他们的平台销售我的应用程序。我只是想知道有没有人有这方面的经验?合法吗? Apple 会在 AppStore
我正在尝试为 PayPal 交易提取 Sale Id。我正在使用 PayPalAndroidSDK 和 PayPal_MPL 到目前为止,我可以检索支付资源,例如PAY-... 使用这个: Paym
我已经安装了 Magento 2.2 并将支付方式配置为“PayPal Express Checkout” When i have payment with PayPal Express Checko
我有一个网站,人们可以在其中比较驾校。我已经使用 schema.org 标记将我知道的这些学校的所有详细信息(名称、描述、位置、价格范围等)添加到他们在我网站上的页面。 几周以来,人们还可以直接在我的
我需要知道一种向 magento admin 添加打印订单功能的方法。 最佳答案 您可以使用这个 extension .我没有测试它。于是手动安装。复制粘贴其扩展 key 并下载 here . 编辑:
我需要知道一种向 magento admin 添加打印订单功能的方法。 最佳答案 您可以使用这个 extension .我没有测试它。于是手动安装。复制粘贴其扩展 key 并下载 here . 编辑:
我有以下表格作为 MySQL Workbench 8.0CE 中更大架构的一部分; 订单 - Order_ID、Customer_ID、Payment_ID、Delivery_ID、Order_Dat
我正在使用亚马逊 MWS api 来获取完整的亚马逊订单列表。拥有这样的 api 非常好,它返回由亚马逊 (AFN) 完成和由卖家 (MFN) 订单完成。 登录到亚马逊卖家中心后,我可以看到所有销售
我是一名优秀的程序员,十分优秀!