Начал изучать javafx
для создания GUI
. До этого учил swing
В swing
можно создать такую таблицу:
private DefaultTableModel dataTableModel;
private JTable dataTable;
private Double valueOfX, valueOfY;
private ArrayList<Ellipse2D.Double> pointList = new ArrayList<>();
public void addDataInTable(){
DefaultTableModel model = (DefaultTableModel)dataTable.getModel();
model.addRow(new Vector<>());
}
public void deleteDataFromTableRow (){
DefaultTableModel model = (DefaultTableModel)dataTable.getModel();;
model.removeRow(dataTable.getRowCount()-1);
}
public void clearDataTable(){
DefaultTableModel model = (DefaultTableModel)dataTable.getModel();
model.setRowCount(0);
}
// в конструкторе класса
dataTableModel = new DefaultTableModel();
dataTableModel.addColumn("X");
dataTableModel.addColumn("Y");
dataTable = new JTable(dataTableModel);
dataTable.setPreferredSize(new Dimension(300, 300));
JScrollPane tableScroll = new JScrollPane(dataTable);
DefaultTableModel model = (DefaultTableModel) dataTable.getModel();
RowSorter<DefaultTableModel> sorter = new TableRowSorter<DefaultTableModel>(model);
((TableRowSorter<DefaultTableModel>) sorter).setSortable(1, false);
dataTable.setRowSorter(sorter);
JPanel tableButtonPanel = new JPanel();
JButton addDataButton = new JButton("Добавить точку");
JButton deleteDataButton = new JButton("Удалить точку");
JButton clearDataButton = new JButton("Очистить таблицу");
addDataButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addDataInTable();
}
});
tableButtonPanel.add(addDataButton);
deleteDataButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteDataFromTableRow();
}
});
tableButtonPanel.add(deleteDataButton);
clearDataButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clearDataTable();
}
});
tableButtonPanel.add(clearDataButton);
В итоге получается что-то типа этого
Специально добавил две новые строки. Двойным щелчком мыши по ячейке запускается возможность ее редактирования, то есть можно вписать туда значение.
Теперь таблица на javafx
public class Main extends Application implements EventHandler<ActionEvent> {
private TableView <PointOfGraphic> dataTable;
private Button addDataInTableButton;
private Button deleteDataFromTableButton;
private Button clearTableButton;
private ObservableList <PointOfGraphic> pointObservableList;
@Override
public void start(Stage primaryStage) throws Exception{
ddDataInTableButton = new Button("Добавить точку");
deleteDataFromTableButton = new Button("Удалить точку");
clearTableButton = new Button("Очистить таблицу");
addDataInTableButton.setOnAction(this);
deleteDataFromTableButton.setOnAction(this);
clearTableButton.setOnAction(this);
VBox vBox = new VBox();
pointObservableList = FXCollections.observableArrayList();
dataTable = new TableView<>();
TableColumn <PointOfGraphic, Double> XColumn = new TableColumn<>("X");
TableColumn <PointOfGraphic, Double> YColumn = new TableColumn<>("Y");
XColumn.setCellValueFactory(new PropertyValueFactory<>("X"));
YColumn.setCellValueFactory(new PropertyValueFactory<>("Y"));
dataTable.getColumns().addAll(XColumn, YColumn);
XColumn.setMinWidth(50);
YColumn.setMinWidth(50);
vBox.getChildren().add(dataTable);
HBox hBox = new HBox();
hBox.getChildren().add(addDataInTableButton);
hBox.getChildren().add(deleteDataFromTableButton);
hBox.getChildren().add(clearTableButton);
hBox.setPadding(new Insets(10,10,10,10));
vBox.getChildren().add(hBox);
Scene scene = new Scene(vBox,500,500);
primaryStage.setScene(scene);
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void addButtonClicked(){
dataTable.getItems().add(new PointOfGraphic());
}
private void deleteButtonClicked() {
dataTable.getItems().removeAll(dataTable.getSelectionModel().getSelectedItem());
}
public void handle(ActionEvent e){
if(e.getSource()==addDataInTableButton){
addButtonClicked();
}
if (e.getSource()==deleteDataFromTableButton){
deleteButtonClicked();
}
}
}
В итоге получается такая таблица
Когда я выделяю строку в этой таблице, я не могу поменять значение координаты X
или Y
, как на Swing
. Почему? И как можно это сделать? P.S. PointOfGraphic
это просто наследник Object
с двумя полями Double X, Double Y
Ничего особенного.
Вам необходимо для колонки переопределить cellFactory, в которой реализовать необходимое поведение.
Ниже пример приложения, на котором желаемое поведение работает.
public class TestJavaFx extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
BorderPane pane = new BorderPane();
TableView<Person> tableView = createTableView();
pane.setCenter(tableView);
Button print = new Button("Print table persons");
print.setOnAction(event -> tableView.getItems().forEach(System.out::println));
pane.setBottom(print);
Scene scene = new Scene(pane, 400, 400);
stage.setScene(scene);
stage.show();
}
private TableView<Person> createTableView() {
TableView<Person> tableView = new TableView<>();
tableView.getItems().addAll(new Person("Jack", 13), new Person("Steve", 25), new Person("Michael", 20));
TableColumn<Person, String> nameColumn = new TableColumn<>("name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
nameColumn.setCellFactory(p -> new CustomTableCell<>());
nameColumn.setOnEditCommit(event -> {
String newName = event.getNewValue();
Person person = event.getRowValue();
person.setName(newName);
});
TableColumn<Person, Integer> ageColumn = new TableColumn<>("age");
ageColumn.setCellValueFactory(new PropertyValueFactory<>("age"));
tableView.setEditable(true);
tableView.getColumns().addAll(nameColumn, ageColumn);
return tableView;
}
public static class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return name + "[" + age + "]";
}
}
private static class CustomTableCell<T> extends TableCell<T, String> {
private TextField textField;
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
textField.setText(getString());
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
protected void updateItem(String s, boolean b) {
super.updateItem(s, b);
if (b || s == null) {
setText(null);
setGraphic(null);
} else {
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
private String getString() {
return String.valueOf(getItem());
}
private void createTextField() {
textField = new TextField(getString());
textField.setOnKeyPressed(t -> {
if (t.getCode() == KeyCode.ENTER || t.getCode() == KeyCode.TAB) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
}
}
}
Обратить особое внимание необходимо на метод createTableView
, а конкретно на переменную nameColumn
. Мы ей проставляем
cellValueFactory
- для того, чтобы колонка знала, какую проперти из нашей модели отображать в ячейкеcellFactory
- фабрика для отображения самой ячейки при редактированииonEditCommit
- мы обрабатываем event, который возникает, когда мы сохраняем значение в ячейке ( покидаем ее по enter или tab)так же важно помнить, что еще необходимо выставить tableView.setEditable(true);
иначе редактирование не будет работать.
после изменения имен, можно нажать кнопку "Print table persons" и тогда мы увидим в консоле, что значения имен поменялись (и сохранились) на новые
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Мне нужно сохранить файл в форматеtsv чтобы у него была кодировка в utf-8, насколько это реально сделать? Делало в том что у меня есть строка в которой...
Почему появляется сообщение о возникновении NumberFormatException? Если использовать val initialMoney = nextLine()toInt(), то всё ок!? То есть приходится сначала вводить...
Столкнулся со стандартной проблемой: запуск приложения сразу после включения телефонаВсе советы либо устарели, либо не работают