【问题标题】:JavaFX Change Color of Table Row when Button is clicked单击按钮时JavaFX更改表格行的颜色
【发布时间】:2020-12-18 10:12:29
【问题描述】:

我希望我的表格根据是否选中列或单击按钮来更改行的颜色。 我寻找解决方案,但它从来没有按照我想要的方式工作。我很高兴为您提供的每个关键字或帮助。也许我只是在寻找错误的东西?

我的代码如下所示:

public class Cellexample_presenter implements Initializable{
@FXML 
TableColumn<ExampleData, Boolean> checkcol;
@FXML 
TableView<ExampleData> testtable;

@Override
public void initialize(URL arg0, ResourceBundle arg1) {

    checkcol.setText("Check");
    ObservableList<ExampleData> exList = FXCollections.observableArrayList();
    exList.add(new ExampleData(true));
    exList.add(new ExampleData(false));
    
    checkcol.setCellValueFactory(
            new Callback<CellDataFeatures<ExampleData, Boolean>, ObservableValue<Boolean>>() {
                
                @Override
                public ObservableValue<Boolean> call(CellDataFeatures<ExampleData, Boolean> param) {
                    return param.getValue().checkProperty();
                }
            });

    testtable.setItems(exList);
    testtable.setEditable(true);
    checkcol.setCellFactory(CheckBoxTableCell.forTableColumn(checkcol));
    
    
}

@FXML
private void clicked() {
    ObservableList<ExampleData> tabledata = testtable.getItems();
    for (ExampleData e : tabledata) {
        System.out.println(e.isCheck());
    }
}
}

我找到了另一个 setCellFactory 的解决方案,但是当我已经有一个 setCellFactory 并且我无法合并时,我似乎无法工作。此外,仍然缺少与 更改Checkbox。 我遇到的另一个解决方案是PseudoClass,但这也需要另一个setCellFactory

method private void clicked() 我用来检查我的对象中的数据是否真的改变了。 我还希望作为另一个功能单击按钮并更改具有错误数据的行的颜色。 我希望有一种方法可以遍历表格,检查数据,如果某些东西不等于其他东西。它改变颜色。 像这样的伪代码

for (tablerow row: table)
     if (row.ischecked()) {
           row.changecolor();
  }

这是用于将所有内容组合在一起的 .FXML:

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

 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.TableColumn?>
 <?import javafx.scene.control.TableView?>
 <?import javafx.scene.layout.AnchorPane?>
 <?import javafx.scene.layout.Pane?>

 <AnchorPane prefHeight="254.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/11.0.1" 
  xmlns:fx="http://javafx.com/fxml/1" 
  fx:controller="pathToFXML/Cellexample_presenter">
  <children>
  <Pane layoutX="-269.0" prefHeight="315.0" prefWidth="700.0" AnchorPane.bottomAnchor="0.0" 
  AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
     <children>
        <TableView fx:id="testtable" layoutX="142.0" layoutY="27.0" prefHeight="200.0" 
       prefWidth="340.0">
          <columns>
            <TableColumn fx:id="checkcol" prefWidth="75.0" text="C1" />
          </columns>
        </TableView>
        <Button fx:id="checkbtn" layoutX="70.0" layoutY="36.0" mnemonicParsing="false" 
     onAction="#clicked" text="isChecked" />
     </children>
     </Pane>
   </children>
  </AnchorPane>

【问题讨论】:

  • 没有看到你做任何事情来改变颜色..按照你(说)找到的例子;)回来minimal reproducible example 展示它们如何不按预期工作。不:循环遍历行是完全错误的方法(行被虚拟化,这意味着它们被重复使用!)

标签: javafx tablerow


【解决方案1】:

您可以为此使用自定义TableRow。我也更喜欢使用 CSS 和 PseudoClasses 来管理行的颜色。

这里需要做的是,该行需要知道该行当前显示的ExampleData 实例中的checked 属性是否发生了变化,如果发生这种情况需要改变颜色。

当然,对于任何给定的表格行,该表格行显示的ExampleData 实例也可能发生变化(例如,如果底层数据列表发生变化,或者如果用户滚动表格等)

所以这里的基本策略是:

  1. 创建一个监听器来观察当前项目的checked 属性,如果有,则更新伪类状态(这反过来会导致样式发生变化)。在下面的代码中,我将此侦听器称为checkListener
  2. 如果行显示的项目发生变化,我们需要停止观察旧项目的checked属性,而开始观察新项目的checked属性。这可以通过表行的item 属性上的侦听器来实现。 itemProperty 上的那个监听器然后可以从旧项目的checkedProperty 中删除checkListener(如果有旧项目),并将其添加到新项目的checkedProperty(如果有的话) .它还需要根据新项目的checkedProperty的当前状态更新伪类状态。
@Override
public void initialize(URL arg0, ResourceBundle arg1) {

    // Existing code....

    testTable.setRowFactory(tv -> new TableRow<ExampleData>() {

        private final PseudoClass checkedPC = PseudoClass.getPseudoClass("checked");

        private final ChangeListener<Boolean> checkListener = (obs, wasChecked, isNowChecked) -> 
            pseudoClassStateChanged(checkedPC, isNowChecked);

        {
             itemProperty().addListener((obs, oldItem, newItem) -> {
                 if (oldItem != null) {
                     oldItem.checkedProperty().removeListener(checkListener);
                 }
                 if (newItem == null) {
                     pseudoClassStateChanged(checkedPC, false);
                 } else {
                     pseudoClassStateChanged(checkedPC, newItem.isChecked());
                     newItem.checkedProperty().addListener(checkListener);
                 }
            });
        }
    });
}

然后在你的外部 CSS 文件中包含

.table-row-cell:checked {
    -fx-background-color: red ;
}

【讨论】:

  • 谢谢!那工作得很好。只是为了理解代码,ChangeListener 是监听列,而添加到 itemProperty 中的 SecondListener 是指 TableRow?所以我将检查员添加到 Tablerow 中?并且删除和添加监听器是必要的,因为 rowFactory 总是产生新的项目?
  • @GrimSqueaker 不,这不太正确(看起来您需要查看表视图的工作方式)。我会在答案中添加一些解释。
  • 看来您需要仔细检查表格视图的工作原理 ;)
  • 非常感谢!并且会做!我还有很多东西要学,我觉得这些工厂和回调对我来说仍然很难理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 2012-12-06
  • 1970-01-01
  • 2020-09-02
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
相关资源
最近更新 更多