JavaFX Запрос фокуса в пользовательской ячейке редактирования - PullRequest
0 голосов
/ 19 февраля 2019

В настоящее время у меня есть два TableView с на одном экране, правый имеет динамический столбец, а правый статический с двумя столбцами, ячейки правой таблицы имеют возможность изменить на редактируемый, щелкнув правой кнопкой мыши наячейку и выбирая первый вариант меню, моя проблема в том, что я не понимаю, что TextField запрашивает фокус, я пытался добавить следующий код, но он не работает.

tableScroll.getFocusModel().focus(row, param);
tableScroll.requestFocus();

Любая помощьбудет признателен.

Я добавляю пример:

Файл FXML:

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

<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SyncrTwoTablesController">
   <children>
      <HBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
  <TableView fx:id="tableNoScroll" prefHeight="200.0" prefWidth="200.0">
    <columns>
      <TableColumn fx:id="tcName" prefWidth="75.0" text="Name" />
    </columns>
  </TableView>
            <ScrollPane fx:id="scPane" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
              <content>
                <AnchorPane>
                     <children>
              <TableView fx:id="tableScroll" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                <columns>
                  <TableColumn prefWidth="75.0" text="Column X" />
                  <TableColumn prefWidth="75.0" text="Column X" />
                </columns>
              </TableView>
                     </children>
                  </AnchorPane>
              </content>
            </ScrollPane>
         </children>
      </HBox>
   </children>
</AnchorPane>

Main.java:

package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
           Parent root = FXMLLoader.load(getClass().getResource("syncrtwotablesGridPane.fxml"));
            Scene scene = new Scene(root,400,400);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

SyncrTwoTablesController.java:

package application;
//*****************************************************************************



import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import bean.ColBean;
import bean.RowBean;
import bean.TestBean;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.util.Callback;

public class SyncrTwoTablesController implements Initializable {

   @FXML
   private ScrollPane          scPane;

   @FXML
   private HBox                hBox;

   @FXML
   private TableView<RowBean> tableNoScroll;

   @FXML
   private TableView<RowBean> tableScroll;



   private TestBean            testBean;
   @FXML
   private TableColumn<RowBean, String> tcName;

   @Override
   public void initialize(URL location, ResourceBundle resources) {
      System.out.println("Controller");
      initializeBean();
      fillTables();

   }

   private void fillTables() {
      tableNoScroll.setItems(FXCollections.observableList(testBean.getLstRow()));
      tableScroll.setItems(FXCollections.observableList(testBean.getLstRow()));
      tcName.setCellValueFactory(new PropertyValueFactory<RowBean, String>("nameRow"));

      List<TableColumn<RowBean, String>> lstColums = new ArrayList<TableColumn<RowBean, String>>();
      //TableColumn<RowBean, String> col = null;
      tableScroll.getColumns().clear();
      if (testBean.getLstRow().size() > 0) {
         for(int i = 0; i < testBean.getLstRow().get(0).getLstColBean().size(); i++) {
            TableColumn<RowBean, String> col = new TableColumn<RowBean, String>("col"+ i);
            int id = i;
            col.setCellValueFactory(
                  new Callback<CellDataFeatures<RowBean, String>, ObservableValue<String>>() {
                     @Override
                     public ObservableValue<String> call(CellDataFeatures<RowBean, String> p) {
                        return p.getValue().getLstColBean().get(id) != null
                              ? p.getValue().getLstColBean().get(id).getColValue()
                              : new SimpleStringProperty("");
                     }
                  });
            col.setCellFactory(
                  new Callback<TableColumn<RowBean, String>, TableCell<RowBean, String>>() {
                     @Override
                     public TableCell<RowBean, String> call(
                           TableColumn<RowBean, String> param) {
                        EditingCell<RowBean, String> cell = new EditingCell(id);
                        cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
                           @Override
                           public void handle(MouseEvent event) {
                              addMenuMonthColumns(param, cell, id);

                           }


                        });
                        return cell;
                     }
                  });
            lstColums.add(col);
         }
         tableScroll.getColumns().addAll(lstColums);
      }
   }

   private void addMenuMonthColumns(TableColumn<RowBean, String> param, EditingCell<RowBean, String> cell, int i) {
      ContextMenu menu = new ContextMenu();
      menu.getItems().addAll(optionOne(param, i), optionTwo());
      cell.setContextMenu(menu);

   }

   private MenuItem optionOne(TableColumn<RowBean, String> param, int i) {
      MenuItem menuPlan = new MenuItem("Option 1");
      menuPlan.setOnAction(new EventHandler<ActionEvent>() {
         @Override
         public void handle(ActionEvent event) {
            int row = tableScroll.getSelectionModel().getSelectedIndex();
            RowBean rowBean = tableScroll.getItems().get(row);
            ColBean colBean = rowBean.getLstColBean().get(i);
            colBean.setEditable(true);

            tableScroll.getFocusModel().focus(row, param);
            tableScroll.requestFocus();
            refresh(tableScroll, tableScroll.getItems());
         }
      });
      return menuPlan;
   }

   private MenuItem optionTwo() {
      MenuItem menuPlan = new MenuItem("Option 2");
      menuPlan.setOnAction(new EventHandler<ActionEvent>() {
         @Override
         public void handle(ActionEvent event) {

         }
      });
      return menuPlan;
   }

   private void initializeBean() {
      ColBean colBean = new ColBean(new SimpleStringProperty("hola"));
      ColBean colBean2 = new ColBean(new SimpleStringProperty("hola"));
      ColBean colBean3 = new ColBean(new SimpleStringProperty("hola"));
      ColBean colBean4 = new ColBean(new SimpleStringProperty("hola"));
      ColBean colBean5 = new ColBean(new SimpleStringProperty("hola"));
      ColBean colBean6 = new ColBean(new SimpleStringProperty("hola"));
      List<ColBean> lstColBean = new ArrayList<ColBean>();
      lstColBean.add(colBean);
      lstColBean.add(colBean2);
      lstColBean.add(colBean3);
      lstColBean.add(colBean4);
      lstColBean.add(colBean5);
      lstColBean.add(colBean6);
      ColBean colBean7 = new ColBean(new SimpleStringProperty("adios"));
      ColBean colBean8 = new ColBean(new SimpleStringProperty("adios"));
      ColBean colBean9 = new ColBean(new SimpleStringProperty("adios"));
      ColBean colBean10 = new ColBean(new SimpleStringProperty("adios"));
      ColBean colBean11= new ColBean(new SimpleStringProperty("adios"));
      ColBean colBean12 = new ColBean(new SimpleStringProperty("adios"));
      List<ColBean> lstColBean2 = new ArrayList<ColBean>();
      lstColBean2.add(colBean7);
      lstColBean2.add(colBean8);
      lstColBean2.add(colBean9);
      lstColBean2.add(colBean10);
      lstColBean2.add(colBean11);
      lstColBean2.add(colBean12);
      RowBean rowBean = new RowBean(new SimpleStringProperty("hola"), lstColBean);
      RowBean rowBean2 = new RowBean(new SimpleStringProperty("adios"), lstColBean2);


      List<RowBean> lstRow = new ArrayList<RowBean>();
      lstRow.add(rowBean);
      lstRow.add(rowBean2);

      testBean = new TestBean(new SimpleStringProperty("test"), lstRow);

   }

   /**
    * Method that refresh the contains of the table.
    * 
    * @param table
    *           of type <code>TableView<T></code>
    * @param tableList
    *           of type <code>List<T></code>
    */
   public static <T> void refresh(final TableView<T> table, final List<T> tableList) {
//      table.setItems(null);
//      table.layout();
//      table.setItems(FXCollections.observableList(tableList));
     FXCollections.copy(table.getItems(), tableList);
   }


}

EditingCell.java:

package application;


import bean.RowBean;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;

public class EditingCell<S, T> extends TableCell<RowBean, String> {

   private TextField textField;

   private int col;

   public EditingCell(int col) {

      this.col = col;

   }

   @Override
   public void updateItem(String item, boolean empty) {
      super.updateItem(item, empty);

      if (empty) {
         setText(null);
         setGraphic(null);
      } else {
         if (item != null) {
            if (getTableView().getItems().get(getIndex()).getLstColBean().get(col).isEditable()) {
               if (textField == null) {
                  textField = new TextField();
               }
               textField.setText(item);
               textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
                  @Override
                  public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean newValue) {
                     if (newValue) {
                        System.out.println("requested");
                        textField.selectAll();
                     }
                  }
               });
               setGraphic(textField);
               setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

            } else {
               setText(item);
               setContentDisplay(ContentDisplay.TEXT_ONLY);
            }
         } else {
            setText(null);
            setGraphic(null);
         }
      }
   }

}

ColBean.java:

package bean;


import java.io.Serializable;

import javafx.beans.property.SimpleStringProperty;

public class ColBean implements Serializable {

   /**
    * 
    */
   private static final long serialVersionUID = 1L;

   private SimpleStringProperty colValue;

   private boolean editable = false;

   public ColBean() {

   }

   public ColBean(SimpleStringProperty colValue) {
      super();
      this.colValue = colValue;
   }

   /**
    * @return the colValue
    */
   public SimpleStringProperty getColValue() {
      return colValue;
   }

   /**
    * @param colValue the colValue to set
    */
   public void setColValue(SimpleStringProperty colValue) {
      this.colValue = colValue;
   }

   /**
    * @return the editable
    */
   public boolean isEditable() {
      return editable;
   }

   /**
    * @param editable the editable to set
    */
   public void setEditable(boolean editable) {
      this.editable = editable;
   }

} 

RowBean.java:

package bean;

import java.io.Serializable;
import java.util.List;

import javafx.beans.property.SimpleStringProperty;

public class RowBean implements Serializable {

   /**
    * 
    */
   private static final long    serialVersionUID = 1L;

   private SimpleStringProperty nameRow;

   private List<ColBean>        lstColBean;

   public RowBean() {

   }

   public RowBean(SimpleStringProperty nameRow, List<ColBean> lstColBean) {
      super();
      this.nameRow = nameRow;
      this.lstColBean = lstColBean;
   }

   /**
    * @return the lstColBean
    */
   public List<ColBean> getLstColBean() {
      return lstColBean;
   }

   /**
    * @param lstColBean
    *           the lstColBean to set
    */
   public void setLstColBean(List<ColBean> lstColBean) {
      this.lstColBean = lstColBean;
   }

   /**
    * @return the nameRow
    */
   public SimpleStringProperty getNameRowProperty() {
      return nameRow;
   }

   /**
    * @param nameRow
    *           the nameRow to set
    */
   public void setNameRowProperty(SimpleStringProperty nameRow) {
      this.nameRow = nameRow;
   }

   public String getNameRow() {
      return nameRow.get();
   }

   public void setNameRow(String nameRow) {
      this.nameRow = new SimpleStringProperty(nameRow);
   }

}

TestBean.java:

package bean;

import java.io.Serializable;
import java.util.List;

import javafx.beans.property.SimpleStringProperty;

public class TestBean implements Serializable {

   /**
    * 
    */
   private static final long    serialVersionUID = 1L;

   private SimpleStringProperty name;

   private List<RowBean>        lstRow;

   public TestBean(SimpleStringProperty name, List<RowBean> lstRow) {
      super();
      this.name = name;
      this.lstRow = lstRow;
   }

   /**
    * @return the lstRow
    */
   public List<RowBean> getLstRow() {
      return lstRow;
   }

   /**
    * @param lstRow
    *           the lstRow to set
    */
   public void setLstRow(List<RowBean> lstRow) {
      this.lstRow = lstRow;
   }

   /**
    * @return the name
    */
   public SimpleStringProperty getName() {
      return name;
   }

   /**
    * @param name
    *           the name to set
    */
   public void setName(SimpleStringProperty name) {
      this.name = name;
   }

}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Рабочим, но, вероятно, не лучшим решением является вызов метода requestFocus() непосредственно в TextField после его создания в методе updateItem() из EditingCell.

@Override
public void updateItem(String item, boolean empty) {
    super.updateItem(item, empty);
// ...
                boolean focus = false;
                if (textField == null) {
                    textField = new TextField();
                    focus = true;
                }
                textField.setText(item);
// ...
                setGraphic(textField);
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                if (focus) {
                    Platform.runLater(()-> textField.requestFocus());
                }
// ...
}

В концеВы можете удалить следующие строки, которые вы уже тестировали:

tableScroll.getFocusModel().focus(row, param);
tableScroll.requestFocus();
0 голосов
/ 19 февраля 2019

Если вы хотите выделить ячейку и сфокусироваться на ней, вы должны включить выделение для нее, например,

Table.getSelectionModel().setCellSelectionEnabled(true);

Надеюсь, это поможет.

...