JavaFX Tutorial zu Tableview

MarkusM

Aktives Mitglied
Hallo zusammen,

ich habe jetzt seit Tagen das Netz nach brauchbaren Dingen durchforstet, bin aber nicht wirklich fündig geworden... Und zwar suche ich ein Tutorial, welches mir die Tableview näher bringt, insbesondere Editierung und der Darstellung/Formatierung der Zellen. Ich verstehe da den globalen Zusammenhang noch nicht zwischen (cellValueFactory, cellFactory, PropertyValueFactory und wie die ganzen Factorys noch so heißen!) und wie diese im best-practice eingesetzt werden.

Die meisten Tutorials, wie auch das von Oracle, beschränken sich auf das simple Anzeigen der Daten im Tableview. Datensätze hinzufügen oder löschen ist auch nicht mein Problem, da habe ich mich gut einarbeiten können. Wenn mir einer mal einen Tipp gibt wie und wofür ich die ganzen Factorys einsetze, wäre ich dankbar. Am besten in einem zusammenhängenden, anfängertauglischem Tutorial...

Viele Grüße

Markus
 
Zuletzt bearbeitet:

dzim

Top Contributor
Hinzufügen und Löschen ist ja dank der ObservableList's auch schon geradezu Kinderkram :)

Ich hab ein einigen Stellen ein paar mehr oder weniger komplizierte Controller, die ich dir mal weitestgehen unkommentiert und ungeschnitten reinpasten würde, wenn du interessiert bist. Müsstest dich dann ein wenig durch den nicht immer gerade optimalen Code wühlen. Interessiert?
 

MarkusM

Aktives Mitglied
Wenn Du so nett wärst, sage ich nicht nein :toll:

Dann versuche ich mich da mal durchzuwühlen und stelle vielleicht noch ein, zwei Fragen, wenn ich darf....
 

dzim

Top Contributor
Ok. Vorwort zu dem ersten Block. Es handelt sich dabei um einen Teil eines mit JavaFX geschriebenen Applets (das leider noch immer nicht endgültig freigegeben wurde - und ich konnte trotz möglicher Layout-Probleme mit Java8 auch nicht mehr weiter daran arbeiten), aber die Funktionen stehen alle.
Einige Daten werden in einem Cookie gespeichert und der Grossteil der Kommunikation zwischen den Komponenten oder gar der Webseite und dem Applet finden über einen selbsgestrickten Even-Mechanismus statt.
Der Codeblock (bzw. der Controller) hier macht nichts weiter, als lokal (im Cookie; ausgelesen durch JS) gespeicherte Ergebnisse einer Speedtest-Messung in einer Tabelle anzuzeigen.
Java:
package ch.cnlab.performanceapplet.fx.ui;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import ch.cnlab.performanceapplet.fx.event.TypedEventDispatcher;
import ch.cnlab.performanceapplet.fx.event.TypedEventDispatcher.Event;
import ch.cnlab.performanceapplet.fx.event.TypedEventDispatcher.EventListener;
import ch.cnlab.performanceapplet.fx.res.StringResource;
import ch.cnlab.performanceapplet.fx.test.TestDetails;
import ch.cnlab.performanceapplet.fx.util.JSHelper;
import ch.cnlab.performanceapplet.fx.util.PlatformHelper;
import ch.cnlab.performanceapplet.fx.util.Preferences;
import ch.cnlab.performanceapplet.fx.util.SpeedTestConstants;
import ch.cnlab.performanceapplet.fx.util.Utils;

public class LocalResultsController {
	
	public static final int TEST_DETAIL_COOKIE_LIMIT = 25;
	
	@FXML
	private VBox root;
	@FXML
	private Label labelResultsTitle;
	@FXML
	private TableView<TestDetails> tableResults;
	@FXML
	private TableColumn<TestDetails, TestDetails> tableColumnId;
	@FXML
	private TableColumn<TestDetails, TestDetails> tableColumnDate;
	@FXML
	private TableColumn<TestDetails, TestDetails> tableColumnDown;
	@FXML
	private TableColumn<TestDetails, TestDetails> tableColumnUp;
	@FXML
	private TableColumn<TestDetails, TestDetails> tableColumnRtt;
	
	private EventListener<?> testDetailsEventListener = null;
	private EventListener<?> booleanEventListener = null;
	private EventListener<?> stringEventListener = null;
	
	private EventListener<?> prefsEventListener = null;
	
	private Comparator<TestDetails> testDetailComparator = new Comparator<TestDetails>() {
		@Override
		public int compare(TestDetails o1, TestDetails o2) {
			int compare = 0;
			Long ts1 = o1.getLong(TestDetails.TEST_TIMESTAMP);
			Long ts2 = o2.getLong(TestDetails.TEST_TIMESTAMP);
			compare = ts1.compareTo(ts2);
			if (compare != 0)
				return -compare;
			Long tdSeries1 = o1.getLong(TestDetails.TEST_SERIESID);
			Long tdSeries2 = o2.getLong(TestDetails.TEST_SERIESID);
			compare = tdSeries1.compareTo(tdSeries2);
			if (compare != 0)
				return -compare;
			Long tdTest1 = o1.getLong(TestDetails.TEST_TESTID);
			Long tdTest2 = o2.getLong(TestDetails.TEST_TESTID);
			compare = tdTest1.compareTo(tdTest2);
			if (compare != 0)
				return -compare;
			return 0;
		}
	};
	
	/**
	 * implicit method
	 */
	@FXML
	public void initialize() {
		
		if (testDetailsEventListener == null) {
			testDetailsEventListener = new InternalTestDetailsEventListener();
			TypedEventDispatcher.getInstance().addListener(testDetailsEventListener, Integer.toString(SpeedTestConstants.EVT_TEST_DETAILS));
		}
		if (booleanEventListener == null) {
			booleanEventListener = new InternalBooleanEventListener();
			TypedEventDispatcher.getInstance().addListener(booleanEventListener, Integer.toString(SpeedTestConstants.EVT_UI_ENABLED));
		}
		if (stringEventListener == null) {
			stringEventListener = new InternalStringEventListener();
			TypedEventDispatcher.getInstance().addListener(stringEventListener, (JSHelper.APPLET_READ_HISTORY + JSHelper.RESPONSE));
		}
		
		if (prefsEventListener == null) {
			prefsEventListener = new InternalPreferenceEventListener();
			TypedEventDispatcher.getInstance().addListener(prefsEventListener, Preferences.EventName.INTERNAL_EVENT_LANGUAGE);
		}
		
		setTableColumnSortable(false, tableColumnId, tableColumnDate, tableColumnDown, tableColumnUp, tableColumnRtt);
		
		Callback<TableColumn.CellDataFeatures<TestDetails, TestDetails>, ObservableValue<TestDetails>> contentCallback = new Callback<TableColumn.CellDataFeatures<TestDetails, TestDetails>, ObservableValue<TestDetails>>() {
			@Override
			public ObservableValue<TestDetails> call(CellDataFeatures<TestDetails, TestDetails> param) {
				return new SimpleObjectProperty<TestDetails>(param.getValue());
			}
		};
		setTableColumnCellValueFactory(contentCallback, tableColumnId, tableColumnDate, tableColumnDown, tableColumnUp, tableColumnRtt);
		
		tableColumnId.setCellFactory(new Callback<TableColumn<TestDetails, TestDetails>, TableCell<TestDetails, TestDetails>>() {
			@Override
			public TableCell<TestDetails, TestDetails> call(TableColumn<TestDetails, TestDetails> param) {
				return new ResultDetailsTableCell(TestDetails.TEST_SERIESID);
			}
		});
		tableColumnDate.setCellFactory(new Callback<TableColumn<TestDetails, TestDetails>, TableCell<TestDetails, TestDetails>>() {
			@Override
			public TableCell<TestDetails, TestDetails> call(TableColumn<TestDetails, TestDetails> param) {
				return new ResultDetailsTableCell(TestDetails.TEST_TIMESTAMP);
			}
		});
		tableColumnDown.setCellFactory(new Callback<TableColumn<TestDetails, TestDetails>, TableCell<TestDetails, TestDetails>>() {
			@Override
			public TableCell<TestDetails, TestDetails> call(TableColumn<TestDetails, TestDetails> param) {
				return new ResultDetailsTableCell(TestDetails.DOWNLOAD_AVERAGE);
			}
		});
		tableColumnUp.setCellFactory(new Callback<TableColumn<TestDetails, TestDetails>, TableCell<TestDetails, TestDetails>>() {
			@Override
			public TableCell<TestDetails, TestDetails> call(TableColumn<TestDetails, TestDetails> param) {
				return new ResultDetailsTableCell(TestDetails.UPLOAD_AVERAGE);
			}
		});
		tableColumnRtt.setCellFactory(new Callback<TableColumn<TestDetails, TestDetails>, TableCell<TestDetails, TestDetails>>() {
			@Override
			public TableCell<TestDetails, TestDetails> call(TableColumn<TestDetails, TestDetails> param) {
				return new ResultDetailsTableCell(TestDetails.RTT_AVERAGE);
			}
		});
		
		updateLanguage();
	}
	
	private void setTableColumnSortable(boolean sortable, TableColumn<?, ?>... columns) {
		for (TableColumn<?, ?> tc : columns) {
			tc.setSortable(sortable);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void setTableColumnCellValueFactory(
			Callback<TableColumn.CellDataFeatures<TestDetails, TestDetails>, ObservableValue<TestDetails>> callback, TableColumn... columns) {
		for (TableColumn<TestDetails, TestDetails> tc : columns) {
			tc.setCellValueFactory(callback);
		}
	}
	
	private void updateLanguage() {
		
		String average = StringResource.getString("utf8.oWithStroke");
		
		labelResultsTitle.setText(StringResource.getString("root.results.title"));
		tableColumnId.setText(StringResource.getString("root.table.column.seriesTest"));
		tableColumnDate.setText(StringResource.getString("root.table.column.date"));
		tableColumnDown.setText(String.format("%s%s", average != null ? (average + " ") : "", StringResource.getString("root.table.column.down")));
		tableColumnUp.setText(String.format("%s%s", average != null ? (average + " ") : "", StringResource.getString("root.table.column.up")));
		tableColumnRtt.setText(String.format("%s%s", average != null ? (average + " ") : "", StringResource.getString("root.table.column.rtt")));
	}
	
	private class InternalTestDetailsEventListener extends TypedEventDispatcher.EventListener<TestDetails> {
		@Override
		public void handleEvent(Event<TestDetails> event) {
			if (event == null || event.getName() == null || event.getName().isEmpty()) {
				return;
			}
			final int what = Integer.parseInt(event.getName());
			if (event.getContent() == null)
				return;
			final TestDetails details = event.getContent();
			switch (what) {
			case SpeedTestConstants.EVT_TEST_DETAILS:
				PlatformHelper.run(new Runnable() {
					@Override
					public void run() {
						tableResults.getItems().add(details);
						FXCollections.sort(tableResults.getItems(), testDetailComparator);
						storeResult();
					}
				});
				break;
			}
		}
		
		private void storeResult() {
			List<TestDetails> dest = new ArrayList<>(tableResults.getItems());
			Collections.sort(dest, testDetailComparator);
			String testDetailsString = Utils.getTestDetailsString(dest, TEST_DETAIL_COOKIE_LIMIT);
			if (testDetailsString != null) {
				TypedEventDispatcher.getInstance().fireEvent(JSHelper.APPLET_WRITE_HISTORY, new Object[] { testDetailsString });
			}
		}
	}
	
	private class InternalStringEventListener extends TypedEventDispatcher.EventListener<String> {
		@Override
		public void handleEvent(Event<String> event) {
			if (event == null || event.getName() == null || event.getName().isEmpty()) {
				return;
			}
			switch (event.getName()) {
			case JSHelper.APPLET_READ_HISTORY + JSHelper.RESPONSE:
				if (event.getContent() == null || event.getContent().isEmpty())
					break;
				List<TestDetails> testDetails = Utils.getTestDetailsList(event.getContent());
				if (testDetails == null || testDetails.isEmpty())
					break;
				long series = Preferences.getPreference(Preferences.ReadWrite.SERIES_ID);
				long test = Preferences.getPreference(Preferences.ReadWrite.TEST_ID);
				for (TestDetails td : testDetails) {
					tableResults.getItems().add(td);
					long tdSeries = td.getLong(TestDetails.TEST_SERIESID);
					long tdTest = td.getLong(TestDetails.TEST_TESTID);
					if (tdSeries > series) {
						series = tdSeries;
						test = tdTest;
					} else if (tdSeries == series) {
						if (tdTest > test) {
							test = tdTest;
						}
					}
				}
				FXCollections.sort(tableResults.getItems(), testDetailComparator);
				Preferences.putPreference(Preferences.ReadWrite.SERIES_ID, series);
				Preferences.putPreference(Preferences.ReadWrite.TEST_ID, test);
				break;
			default:
				break;
			}
		}
	}
	
	private class InternalBooleanEventListener extends TypedEventDispatcher.EventListener<Boolean> {
		
		@Override
		public void handleEvent(final Event<Boolean> event) {
			if (event == null || event.getName() == null || event.getName().isEmpty()) {
				return;
			}
			final int what = Integer.parseInt(event.getName());
			if (event.getContent() == null)
				return;
			final Boolean b = event.getContent();
			switch (what) {
			case SpeedTestConstants.EVT_UI_ENABLED:
				disableNode(tableResults, !b);
				break;
			default:
				break;
			}
		}
		
		private void disableNode(final Node n, final Boolean b) {
			PlatformHelper.run(new Runnable() {
				@Override
				public void run() {
					n.setDisable(b);
				}
			});
		}
	}
	
	private class InternalPreferenceEventListener extends TypedEventDispatcher.EventListener<Object> {
		@Override
		public void handleEvent(Event<Object> event) {
			if (event == null || event.getName() == null || event.getName().isEmpty()) {
				return;
			}
			switch (event.getName()) {
			case Preferences.EventName.INTERNAL_EVENT_LANGUAGE:
				updateLanguage();
				break;
			default:
				break;
			}
		}
	}
	
	public class ResultDetailsTableCell extends TableCell<TestDetails, TestDetails> {
		
		private final String type;
		
		public ResultDetailsTableCell(final String type) {
			this.type = type;
		}
		
		@Override
		protected void updateItem(TestDetails item, boolean empty) {
			
			super.updateItem(item, empty);
			
			if (empty) {
				setText(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				String text = "";
				if (TestDetails.TEST_SERIESID.equals(type) || TestDetails.TEST_TESTID.equals(type)) {
					text = StringResource.getString("root.table.column.seriesTest.format", item.getFormatedStringByKey(TestDetails.TEST_SERIESID),
							item.getFormatedStringByKey(TestDetails.TEST_TESTID));
				} else if (TestDetails.TEST_TIMESTAMP.equals(type)) {
					DateFormat df = new SimpleDateFormat(StringResource.getString("root.table.column.date.format"), Locale.ENGLISH);
					text = df.format(new Date(item.getLong(TestDetails.TEST_TIMESTAMP)));
				} else if (TestDetails.DOWNLOAD_AVERAGE.equals(type)) {
					text = item.getFormatedStringByKey(TestDetails.DOWNLOAD_AVERAGE);
				} else if (TestDetails.UPLOAD_AVERAGE.equals(type)) {
					text = item.getFormatedStringByKey(TestDetails.UPLOAD_AVERAGE);
				} else if (TestDetails.RTT_AVERAGE.equals(type)) {
					text = item.getFormatedStringByKey(TestDetails.RTT_AVERAGE);
				}
				setText(text);
			}
		}
	}
}

Der InternalTestDetailsEventListener empfängt die Ergebnisse der letzten Messung und fügt sie der Tabelle hinzu. Er löst auch das Event aus, dass die aktuellen Ergebnisse wieder per JS im Cookie speichert.
InternalStringEventListener empfängt das (asynchrone) Ergebnis, nachdem der Controller via JS alle bereits vorhandenen Ergebnisse angefragt hat.
InternalPreferenceEventListener setzt (wieder asynchron, da durch JS ausgelöst) die Sprache der UI.

Die interne Klasse ResultDetailsTableCell bekommt einen Typen und konstruiert anhand dessen eine bestimmte Celle in der Tabelle.

Das angezeigte TestDetail ist übrigens eine Klasse ohne die typischen JavaFX Observable Properties. Daher war die Hilfsmethode mit dem entsprechendem Callback #setTableColumnCellValueFactory() nötig.

Viel Spass! :p
 

dzim

Top Contributor
(kann nur 25000 Zeichen per Post machne... -.- )

In einem anderen kleinen Projekt habe ich mal mit OSGi-Services und ein wenig Eclipse e4-Blackmagic eine kleine auf JavaFX basierte - und relativ einfach zu erweiternde - Platform geschrieben.
Java:
// gekürzt, weil immer noch zu lang :-P
public class ConfigTabController implements Initializable {
	
	@FXML
	private Label cmdPathLabel;
	@FXML
	private TextField cmdPathText;
	@FXML
	private Button cmdPathButton;
	
	@FXML
	private Label licenseLabel;
	@FXML
	private Button licenseButton;
	
	@FXML
	private Label updownPathLabel;
	@FXML
	private TextField updownPathText;
	@FXML
	private Button updownPathButton;
	
	@FXML
	private Label labelUploadURL;
	@FXML
	private TextField textFieldUploadURL;
	@FXML
	private Label labelUploadKey;
	@FXML
	private TextField textFieldUploadKey;
	
	@FXML
	private Label labelAGPSUrl;
	@FXML
	private TextField textFieldAGPSUrl;
	@FXML
	private Label labelAGPSUser;
	@FXML
	private TextField textFieldAGPSUser;
	@FXML
	private Label labelAGPSPasswd;
	@FXML
	private TextField textFieldAGPSPasswd;
	
	@FXML
	private Label labelDeviceTable;
	@FXML
	private ScrollPane scrollPaneDevices;
	@FXML
	private TableView<Device> deviceTable;
	@FXML
	private TableColumn<Device, Device> tableColumnDetected;
	@FXML
	private TableColumn<Device, String> tableColumnMac;
	@FXML
	private TableColumn<Device, Device> tableColumnName;
	@FXML
	private TableColumn<Device, Device> tableColumnInterval;
	@FXML
	private TableColumn<Device, Device> tableColumnDataUsage;
	
	@FXML
	private Button buttonConfigure;
	@FXML
	private Button buttonAdd;
	@FXML
	private Button buttonRemove;
	
	@Inject
	private IEclipseContext context;
	@Inject
	private IEventBroker broker;
	
	// @Inject private UIComponent parent;
	
	private ResourceBundle bundle = null;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		
		this.bundle = resources;
		
		cmdPathLabel.setText(bundle.getString("configuration.path.cmd.label"));
		cmdPathText.setPromptText(bundle.getString("configuration.path.cmd.tooltip"));
		cmdPathButton.setText(bundle.getString("configuration.path.cmd.button"));
		cmdPathText.textProperty().bind(UIComponentImpl.getPreferences().getPreferenceProperty(String.class, UIComponentImpl.PREF_EXEC_DIR));
		
		licenseLabel.setText(StringResource.getString("configuration.license.label"));
		licenseButton.setText(StringResource.getString("configuration.license.button"));
		
		BooleanBinding cmdPathBinding = new BooleanBinding() {
			{
				super.bind(deviceTable.getSelectionModel().getSelectedItems());
			}
			
			@Override
			protected boolean computeValue() {
				String path = UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_EXEC_DIR);
				return path == null || path.isEmpty();
			}
		};
		licenseButton.disableProperty().bind(cmdPathBinding);
		
		updownPathLabel.setText(bundle.getString("configuration.path.updown.label"));
		updownPathText.setPromptText(bundle.getString("configuration.path.updown.tooltip"));
		updownPathButton.setText(bundle.getString("configuration.path.updown.button"));
		updownPathText.textProperty().bind(UIComponentImpl.getPreferences().getPreferenceProperty(String.class, UIComponentImpl.PREF_DATA_DIR));
		
		if (buttonConfigure.getGraphic() == null) {
			ImageView iv = ImageResource.getImageView("fugue/gear--pencil.png");
			if (iv != null)
				buttonConfigure.setGraphic(iv);
		}
		if (buttonAdd.getGraphic() == null) {
			ImageView iv = ImageResource.getImageView("fugue/plus.png");
			if (iv != null)
				buttonAdd.setGraphic(iv);
		}
		if (buttonRemove.getGraphic() == null) {
			ImageView iv = ImageResource.getImageView("fugue/minus.png");
			if (iv != null)
				buttonRemove.setGraphic(iv);
		}
		
		BooleanBinding selectionBinding = new BooleanBinding() {
			{
				super.bind(deviceTable.getSelectionModel().getSelectedItems());
			}
			
			@Override
			protected boolean computeValue() {
				return deviceTable.getSelectionModel().getSelectedItems() == null || deviceTable.getSelectionModel().getSelectedItems().isEmpty();
			}
		};
		
		buttonConfigure.disableProperty().bind(selectionBinding);
		buttonRemove.disableProperty().bind(selectionBinding);
		
		// TODO bind to settings
		labelUploadURL.setText(bundle.getString("configuration.upload.url.label"));
		textFieldUploadURL.setPromptText(bundle.getString("configuration.upload.url.desc"));
		textFieldUploadURL.setText(UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_UP_URL));
		
		labelUploadKey.setText(bundle.getString("configuration.upload.key.label"));
		textFieldUploadKey.setPromptText(bundle.getString("configuration.upload.key.desc"));
		textFieldUploadKey.setText(UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_UP_KEY));
		
		labelAGPSUrl.setText(bundle.getString("configuration.agps.url.label"));
		textFieldAGPSUrl.setPromptText(bundle.getString("configuration.agps.url.desc"));
		textFieldAGPSUrl.setText(UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_AGPS_URL));
		
		labelAGPSUser.setText(bundle.getString("configuration.agps.user.label"));
		textFieldAGPSUser.setPromptText(bundle.getString("configuration.agps.user.desc"));
		textFieldAGPSUser.setText(UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_AGPS_USER));
		
		labelAGPSPasswd.setText(bundle.getString("configuration.agps.passwd.label"));
		textFieldAGPSPasswd.setPromptText(bundle.getString("configuration.agps.passwd.desc"));
		textFieldAGPSPasswd.setText(UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_AGPS_PASSWD));
		
		labelDeviceTable.setText(bundle.getString("configuration.deviceTable.label"));
		
		scrollPaneDevices.viewportBoundsProperty().addListener(new ChangeListener<Bounds>() {
			@Override
			public void changed(ObservableValue<? extends Bounds> observableValue, Bounds oldBounds, Bounds newBounds) {
				scrollPaneDevices.setFitToWidth(newBounds.getWidth() > deviceTable.getPrefWidth());
				scrollPaneDevices.setFitToHeight(newBounds.getHeight() > deviceTable.getPrefHeight());
			}
		});
		
		deviceTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
		deviceTable.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
		
		Callback<TableColumn.CellDataFeatures<Device, Device>, ObservableValue<Device>> contentCallback = new Callback<TableColumn.CellDataFeatures<Device, Device>, ObservableValue<Device>>() {
			@Override
			public ObservableValue<Device> call(CellDataFeatures<Device, Device> param) {
				return new SimpleObjectProperty<Device>(param.getValue());
			}
		};
		
		tableColumnDetected.setCellValueFactory(contentCallback);
		tableColumnDetected.setCellFactory(new Callback<TableColumn<Device, Device>, TableCell<Device, Device>>() {
			@Override
			public TableCell<Device, Device> call(TableColumn<Device, Device> param) {
				return new DeviceDetectedTableCell();
			}
		});
		
		tableColumnName.setEditable(true);
		tableColumnName.setCellValueFactory(contentCallback);
		tableColumnName.setCellFactory(new Callback<TableColumn<Device, Device>, TableCell<Device, Device>>() {
			@Override
			public TableCell<Device, Device> call(TableColumn<Device, Device> param) {
				return new EditDeviceNameTableCell();
			}
		});
		
		tableColumnName.setEditable(true);
		tableColumnInterval.setCellValueFactory(contentCallback);
		tableColumnInterval.setCellFactory(new Callback<TableColumn<Device, Device>, TableCell<Device, Device>>() {
			@Override
			public TableCell<Device, Device> call(TableColumn<Device, Device> param) {
				return new EditDeviceIntervalTableCell();
			}
		});
		
		tableColumnDataUsage.setCellValueFactory(contentCallback);
		tableColumnDataUsage.setCellFactory(new Callback<TableColumn<Device, Device>, TableCell<Device, Device>>() {
			@Override
			public TableCell<Device, Device> call(TableColumn<Device, Device> param) {
				return new DeviceDataUsageTableCell();
			}
		});
		
		deviceTable.setEditable(true);
		deviceTable.setItems(UIComponentImpl.getPreferences().getDevices());
	}
	
	@FXML
	public void handleCmdPath() {
		String exec = UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_EXEC_DIR);
		FileChooser fileChooser = new FileChooser();
		if (exec != null && !exec.isEmpty()) {
			File f = new File(exec);
			if (f.getParentFile().isDirectory())
				fileChooser.setInitialDirectory(f.getParentFile());
		}
		fileChooser.getExtensionFilters().add(
				new ExtensionFilter(bundle.getString("configuration.path.cmd.extension.desc"), bundle.getString("configuration.path.cmd.extension")));
		File file = fileChooser.showOpenDialog(context.get(Stage.class));
		if (file == null)
			return;
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_EXEC_DIR, file.getAbsolutePath());
	}
	
	@FXML
	public void handleLicenseButton() {
		File licenseFile = UIComponentImpl.getLicenseFile();
		if (licenseFile == null) {
			MessageDialog.showWarning(context.get(Stage.class), StringResource.getString("nav.devices.controller.title"),
					StringResource.getString("nav.devices.impossible.license"));
			return;
		}
		LicenseSetUpDialog dialog = new LicenseSetUpDialog(context.get(Stage.class));
		String license = dialog.showDialog(true);
		if (license != null && !license.isEmpty()) {
			String[] split = license.split("[\n]");
			if (licenseFile.isFile()) {
				int i = 1;
				File bakFile = new File(licenseFile.getParentFile(), UIComponentImpl.LICENSE_FILE_NAME + "." + i);
				while (bakFile.isFile()) {
					i += 1;
					bakFile = new File(licenseFile.getParentFile(), UIComponentImpl.LICENSE_FILE_NAME + "." + i);
				}
				licenseFile.renameTo(bakFile);
			}
			PrintWriter writer = null;
			try {
				if (licenseFile.createNewFile()) {
					writer = new PrintWriter(licenseFile);
					for (String line : split) {
						writer.println(line);
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (writer != null) {
					writer.flush();
					writer.close();
				}
			}
		}
	}
	
	@FXML
	public void handleUpdownPath() {
		String dataDir = UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_DATA_DIR);
		DirectoryChooser dirChooser = new DirectoryChooser();
		if (dataDir != null && !dataDir.isEmpty()) {
			File f = new File(dataDir);
			if (f.isDirectory())
				dirChooser.setInitialDirectory(f);
		}
		File file = dirChooser.showDialog(context.get(Stage.class));
		if (file == null)
			return;
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_DATA_DIR, file.getAbsolutePath());
	}
	
	@FXML
	public void handleUploadUrl() {
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_UP_URL, textFieldUploadURL.getText());
	}
	
	@FXML
	public void handleUploadKey() {
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_UP_KEY, textFieldUploadKey.getText());
	}
	
	@FXML
	public void handleAGPSUrl() {
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_AGPS_URL, textFieldAGPSUrl.getText());
	}
	
	@FXML
	public void handleAGPSUser() {
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_AGPS_USER, textFieldAGPSUser.getText());
	}
	
	@FXML
	public void handleAGPSPasswd() {
		UIComponentImpl.getPreferences().setPreferenceValue(UIComponentImpl.PREF_AGPS_PASSWD, textFieldAGPSPasswd.getText());
	}
	
	@FXML
	public void handleButtonConfigure() {
		try {
			ConfigureDevicesDialog2 dialog = new ConfigureDevicesDialog2(context.get(Stage.class), deviceTable.getSelectionModel().getSelectedItems());
			ContextInjectionFactory.inject(dialog, context);
			dialog.showDialog();
		} catch (MalformedURLException e) {}
	}
	
	@FXML
	public void handleButtonAdd() {
		String exec = UIComponentImpl.getPreferences().getPreferenceValue(String.class, UIComponentImpl.PREF_DATA_DIR);
		FileChooser fileChooser = new FileChooser();
		if (exec != null && !exec.isEmpty()) {
			File f = new File(exec);
			if (f.isDirectory())
				fileChooser.setInitialDirectory(f);
		}
		File file = fileChooser.showOpenDialog(context.get(Stage.class));
		if (file == null)
			return;
		Map<String, Device> deviceMap = new HashMap<>();
		ObservableList<Device> devices = UIComponentImpl.getPreferences().getDevices();
		if (devices != null && !devices.isEmpty()) {
			for (Device d : UIComponentImpl.getPreferences().getDevices()) {
				deviceMap.put(d.getAddress(), d);
			}
		}
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String line = "";
			while ((line = reader.readLine()) != null) {
				String[] split = line.split("[;]");
				if (split.length != 2)
					continue;
				String deviceId = split[0].trim();
				String deviceName = split[1].trim();
				if (deviceMap.containsKey(deviceId)) {
					deviceMap.get(deviceId).setName(deviceName);
				} else {
					Device d = new Device();
					d.setAddress(deviceId);
					d.setName(deviceName);
					UIComponentImpl.getPreferences().getDevices().add(d);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null)
				try {
					reader.close();
				} catch (IOException e) {}
		}
	}
	
	@FXML
	public void handleButtonRemove() {
		ObservableList<Device> selection = deviceTable.getSelectionModel().getSelectedItems();
		if (selection == null || selection.isEmpty())
			return;
		boolean res = MessageDialog.showQuestion(context.get(Stage.class), bundle.getString("tab.device.confirm.removal"),
				bundle.getString("tab.device.confirm.removal.msg"));
		if (res) {
			ObservableList<Device> devices = UIComponentImpl.getPreferences().getDevices();
			if (devices != null && !devices.isEmpty()) {
				for (Device d : selection) {
					devices.remove(d);
				}
			}
		}
	}
	
	public class DeviceDetectedTableCell extends TableCell<Device, Device> {
		
		public DeviceDetectedTableCell() {}
		
		@Override
		protected void updateItem(Device item, boolean empty) {
			
			super.updateItem(item, empty);
			// getTableRow().getStyleClass().remove("highlight");
			if (empty) {
				textProperty().unbind();
				setText(null);
				graphicProperty().unbind();
				setGraphic(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				textProperty().bind(new DeviceDetectedStringBinding(item));
				graphicProperty().bind(new DeviceDetectedBinding(item));
				setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			}
		}
	}
	
	private final class DeviceDetectedBinding extends ObjectBinding<Node> {
		
		private final Device device;
		
		// private final TableCell<Device, Device> cell;
		
		public DeviceDetectedBinding(final Device device) {
			this.device = device;
			// this.cell = cell;
			super.bind(device.detected());
			super.bind(device.licensed());
		}
		
		@Override
		protected Node computeValue() {
			Label label = new Label();
			label.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			ImageView iv = null;
			if (device.isDetected()) {
				if (device.isLicensed()) {
					iv = ImageResource.getImageView("fugue/tick-circle.png");
					label.setTooltip(new Tooltip(StringResource.getString("license.deviceStatus.ok", device.getAddress()
							+ (device.getName() != null && !device.getName().isEmpty() ? " '" + device.getName() + "'" : ""), device.getPort())));
				} else {
					iv = ImageResource.getImageView("fugue/fugue_exclamation.png");
					label.setTooltip(new Tooltip(StringResource.getString("license.deviceStatus.problem", device.getAddress()
							+ (device.getName() != null && !device.getName().isEmpty() ? " '" + device.getName() + "'" : ""), device.getPort())));
				}
				// cell.getTableRow().getStyleClass().add("highlight");
			} else {
				iv = ImageResource.getImageView("fugue/cross-circle.png");
				label.setTooltip(new Tooltip(StringResource.getString("license.deviceStatus.unknown", device.getAddress()
						+ (device.getName() != null && !device.getName().isEmpty() ? " '" + device.getName() + "'" : ""))));
				// cell.getTableRow().getStyleClass().remove("highlight");
			}
			if (iv != null) {
				label.setGraphic(iv);
			}
			return label;
		}
	}
	
	private final class DeviceDetectedStringBinding extends StringBinding {
		
		private final Device device;
		
		public DeviceDetectedStringBinding(Device device) {
			this.device = device;
			super.bind(device.detected());
		}
		
		@Override
		protected String computeValue() {
			if (device.isDetected()) {
				return bundle.getString("configuration.deviceTable.header.detected.true");
			} else {
				return bundle.getString("configuration.deviceTable.header.detected.false");
			}
		}
	}
	
	public class EditDeviceNameTableCell extends TableCell<Device, Device> {
		
		private TextField textField;
		
		public EditDeviceNameTableCell() {}
		
		@Override
		public void startEdit() {
			super.startEdit();
			if (isEmpty())
				return;
			if (textField == null) {
				createTextBox();
			} else {
				textField.setText(getItem().getName());
			}
			setGraphic(textField);
			setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			textField.requestFocus();
			textField.selectAll();
		}
		
		@Override
		public void cancelEdit() {
			super.cancelEdit();
			setContentDisplay(ContentDisplay.TEXT_ONLY);
		}
		
		@Override
		public void updateItem(Device item, boolean empty) {
			super.updateItem(item, empty);
			if (!isEmpty()) {
				if (textField != null) {
					textField.setText(item.getName());
				}
				// setText(item.getName());
				textProperty().bind(item.name());
			} else {
				textProperty().unbind();
				setText(null);
				graphicProperty().unbind();
				setGraphic(null);
			}
		}
		
		private void createTextBox() {
			textField = new TextField(getItem().getName());
			// textField.setId(TABLE_EDIT_ID);
			textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
				@Override
				public void handle(KeyEvent t) {
					if (t.getCode() == KeyCode.ENTER) {
						if (textField.getText().isEmpty() || textField.getText().equals(getItem().getName())) {
							cancelEdit();
						} else if (textField.getText().contains(";")) {
							UIEvent event = new UIEvent(UIBaseEvents.STATUS_UPDATE, bundle.getString("configuration.deviceTable.header.name.impossible"));
							broker.send(event.getName(), event);
						} else {
							getItem().setName(textField.getText());
							cancelEdit();
						}
					} else if (t.getCode() == KeyCode.ESCAPE) {
						cancelEdit();
					}
				}
			});
		}
	}
	
	public class EditDeviceIntervalTableCell extends TableCell<Device, Device> {
		
		private final ObservableMap<String, Long> comboBoxContent;
		
		private HBox hBox;
		private ComboBox<String> comboBox;
		private Button button;
		
		public EditDeviceIntervalTableCell() {
			Map<String, Long> content = new TreeMap<>();
			content.put(bundle.getString("configuration.confiurationUpdate.oneHz"), 1000L);
			content.put(bundle.getString("configuration.confiurationUpdate.fiveHz"), 200L);
			comboBoxContent = FXCollections.observableMap(content);
		}
		
		@Override
		public void startEdit() {
			super.startEdit();
			// if (isEmpty())
			if (isEmpty() || !getItem().isDetected())
				return;
			if (hBox == null) {
				createHBox();
			}
			comboBox.getSelectionModel().select(getText());
			button.setDisable(true);
			setGraphic(hBox);
			setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
			comboBox.requestFocus();
		}
		
		@Override
		public void cancelEdit() {
			super.cancelEdit();
			setContentDisplay(ContentDisplay.TEXT_ONLY);
		}
		
		@Override
		public void updateItem(Device item, boolean empty) {
			super.updateItem(item, empty);
			if (!isEmpty()) {
				textProperty().bind(new DeviceIntervalBinding(item, comboBoxContent));
				if (hBox != null) {
					comboBox.getSelectionModel().select(getText());
					button.setDisable(true);
				}
			} else {
				textProperty().unbind();
				setText(null);
				setGraphic(null);
			}
		}
		
		private void createHBox() {
			
			hBox = new HBox(5.0);
			comboBox = new ComboBox<>(FXCollections.observableArrayList(comboBoxContent.keySet()));
			button = new Button(bundle.getString("configuration.confiurationUpdate.button.ok"));
			button.setDisable(true);
			
			comboBox.setMaxWidth(Double.MAX_VALUE);
			HBox.setHgrow(comboBox, Priority.ALWAYS);
			HBox.setHgrow(button, Priority.NEVER);
			
			hBox.getChildren().add(comboBox);
			hBox.getChildren().add(button);
			
			comboBox.setOnAction(new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					if (!comboBox.getSelectionModel().getSelectedItem().equals(getText())) {
						button.setDisable(false);
					}
				}
			});
			button.setOnAction(new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					
					if (!getItem().isLicensed()) {
						comboBox.getSelectionModel().select(getText());
						button.setDisable(true);
						cancelEdit();
						DeviceLicenseProblemDialog dialog = new DeviceLicenseProblemDialog(context.get(Stage.class), FXCollections.observableArrayList(getItem()));
						dialog.showDialog();
						return;
					}
					
					getItem().setInterval(comboBoxContent.get(comboBox.getSelectionModel().getSelectedItem()));
					
					ConfigureGPSDeviceTask task = new ConfigureGPSDeviceTask(broker, context.get(Stage.class), bundle, getItem());
					task.setCancelable(false);
					task.setTitleAsInitialStatus(true);
					UIEvent uiEvent = new UIEvent(UIBaseEvents.PROGRESS_ADD_TASK, task);
					broker.send(uiEvent.getName(), uiEvent);
					
					cancelEdit();
				}
			});
		}
	}
	
	private final class DeviceIntervalBinding extends StringBinding {
		
		private final ObservableMap<String, Long> comboBoxContent;
		
		private final Device device;
		
		public DeviceIntervalBinding(Device device, ObservableMap<String, Long> comboBoxContent) {
			super.bind(device.detected());
			super.bind(device.interval());
			this.device = device;
			this.comboBoxContent = comboBoxContent;
		}
		
		@Override
		protected String computeValue() {
			String interval = "";
			for (String key : comboBoxContent.keySet()) {
				if (comboBoxContent.get(key) == device.getInterval()) {
					interval = key;
					break;
				}
			}
			return device.isDetected() ? interval : "";
		}
	}
	
	public class DeviceDataUsageTableCell extends TableCell<Device, Device> {
		
		public DeviceDataUsageTableCell() {}
		
		@Override
		protected void updateItem(Device item, boolean empty) {
			
			super.updateItem(item, empty);
			
			if (empty) {
				textProperty().unbind();
				setText(null);
			} else {
				setTextOverrun(OverrunStyle.ELLIPSIS);
				textProperty().bind(new DeviceDataUsageStringBinding(item));
			}
		}
	}
	
	private final class DeviceDataUsageStringBinding extends StringBinding {
		
		private final Device device;
		
		public DeviceDataUsageStringBinding(Device device) {
			super.bind(device.detected());
			super.bind(device.dataBytes());
			this.device = device;
		}
		
		@Override
		protected String computeValue() {
			return device.isDetected() && device.getDataBytes() > 0 ? (device.getDataBytes() / InternalPreferences.DEVICE_SIZE_MIB) * 100 + "%" : "";
		}
	}
}

Hier sind vor allem viele Bindings zwishen verschiedenen UI-Komponenten und eine Methode, wie man eine Zelle editieren könnte, verwendet. Schau mal, was es dir bringt.

Weiterhin viel Spass!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D JavaFX JavaFX Tutorial AWT, Swing, JavaFX & SWT 8
I Swing Swing Tutorial für fortgeschrittene AWT, Swing, JavaFX & SWT 1
L [SUCHE] Tutorial zur grafischen Nutzeroberflächengestaltung AWT, Swing, JavaFX & SWT 6
K Jogl tutorial gesucht AWT, Swing, JavaFX & SWT 2
G LookAndFeel Tutorial für Erstellung eines eigenen Look And Feel AWT, Swing, JavaFX & SWT 3
J 3D-Grafik Native Java 3D Tutorial gesucht AWT, Swing, JavaFX & SWT 5
T 2D-Grafik Tutorial für ein einfaches Zeichenprogramm! AWT, Swing, JavaFX & SWT 2
M GEF tutorial Fehler finden AWT, Swing, JavaFX & SWT 4
E Swing Tutorial Buch blättern Effekt gesucht AWT, Swing, JavaFX & SWT 2
jgh SWT Tutorial Imports AWT, Swing, JavaFX & SWT 4
truesoul Quaxli Tutorial = ConcurrentModificationException AWT, Swing, JavaFX & SWT 30
J Jigloo browser tutorial - Anleitung unklar AWT, Swing, JavaFX & SWT 4
N Tutorial für TableCellEditor AWT, Swing, JavaFX & SWT 1
V [SUCHE]GUI Programmier Tutorial[Netbeans] AWT, Swing, JavaFX & SWT 8
H Tutorial bzw. Beispiel eines "GUI Ablaufs" AWT, Swing, JavaFX & SWT 8
S Wizard Tutorial AWT, Swing, JavaFX & SWT 12
S Tutorial zum Excel Tabelle in JTable einlesen? AWT, Swing, JavaFX & SWT 4
G Frage zu Zeichnen in Swing Tutorial AWT, Swing, JavaFX & SWT 4
0 SwingWorker Tutorial ? AWT, Swing, JavaFX & SWT 2
R Sun tutorial code von jcombobox mit image im combobox fehlt! AWT, Swing, JavaFX & SWT 3
S FAQ und JTable Tutorial.Teil.4 Punkt 5 wichtige Bemerkung AWT, Swing, JavaFX & SWT 2
oliver1974 SWT Tutorial -- Gibts tatsächlich so wenige? AWT, Swing, JavaFX & SWT 10
A Zeile in JTable einfügen/löschen- Tutorial gesucht AWT, Swing, JavaFX & SWT 9
F Swing Tutorial AWT, Swing, JavaFX & SWT 4
G Original JFC Tutorial Demo DragListDemo hat einen Bug! AWT, Swing, JavaFX & SWT 4
B Layoutmanager Tutorial AWT, Swing, JavaFX & SWT 15
G Suche Tutorial zum Thema jdbc/SQL/Select/JTable AWT, Swing, JavaFX & SWT 9
clemson gutes JTree Tutorial AWT, Swing, JavaFX & SWT 1
A JTable-Tutorial AWT, Swing, JavaFX & SWT 4
G JAVA Tutorial AWT, Swing, JavaFX & SWT 2
E Tutorial zu SWT AWT, Swing, JavaFX & SWT 4
EagleEye suche Tutorial(s) für JTable AWT, Swing, JavaFX & SWT 2
S SWING TUTORIAL AWT, Swing, JavaFX & SWT 2
Juelin setzen background color für selected Row im Tableview AWT, Swing, JavaFX & SWT 21
M JavaFX TableView nur erste Zeile editable machen und gelb markieren AWT, Swing, JavaFX & SWT 0
Encera TableView Zeilen als Spalten im SceneBuilder AWT, Swing, JavaFX & SWT 0
T TableView Button onAction AWT, Swing, JavaFX & SWT 3
mrbody234 ArrayList<Message> in eine TableView visualisieren AWT, Swing, JavaFX & SWT 2
izoards JavaFX TableView mit Array Inhalt füllen AWT, Swing, JavaFX & SWT 1
A Mit JavaFX einzelne Zeilen in TableView farbig markieren AWT, Swing, JavaFX & SWT 5
I JavaFX Zellen in Tableview editieren AWT, Swing, JavaFX & SWT 0
A TableView updatet sich nicht AWT, Swing, JavaFX & SWT 3
missy72 JavaFX TableView Spalte zwischen den Zeilen AWT, Swing, JavaFX & SWT 5
W TableView füllen AWT, Swing, JavaFX & SWT 18
missy72 JavaFX TableView / IconView mit MousEvent AWT, Swing, JavaFX & SWT 7
missy72 JavaFX Performance / ImageView in TableView über TimeLine AWT, Swing, JavaFX & SWT 1
T TableView aktualisieren AWT, Swing, JavaFX & SWT 1
N JavaFX Tableview nach Löschen von Element falscher Index AWT, Swing, JavaFX & SWT 4
T TableView Zeilen einfärben AWT, Swing, JavaFX & SWT 13
T TableView über Methode befüllen AWT, Swing, JavaFX & SWT 10
missy72 JavaFX TableView / TableColumn / ObservableList / zwei Werte in einer Zelle AWT, Swing, JavaFX & SWT 2
W JavaFX TableView aktualisieren AWT, Swing, JavaFX & SWT 1
S JavaFX - mit Listener Veränderungen in einer TableView abhören AWT, Swing, JavaFX & SWT 3
B JavaFX TableView-Zellen sollen automatisch so groß wie der größte Inhalt sein AWT, Swing, JavaFX & SWT 6
D JavaFX Nullpointerexception wegen TableView AWT, Swing, JavaFX & SWT 2
S Alternative JavaFX TableView AWT, Swing, JavaFX & SWT 1
L JavaFX Tableview row callback AWT, Swing, JavaFX & SWT 0
G Bekomme ResultSet mittels ObservableList nicht ins TableView AWT, Swing, JavaFX & SWT 25
S JavaFX JavaFX TableView scrollen färbt falsche Zeilen AWT, Swing, JavaFX & SWT 1
A checkbox in einer TableView abhängig von einem anderen Celleninhalt disablen AWT, Swing, JavaFX & SWT 1
J JavaFx TableView mit CheckBox AWT, Swing, JavaFX & SWT 4
P JavaFX TableView Zelle markieren AWT, Swing, JavaFX & SWT 3
L JavaFX Tableview Datamodel AWT, Swing, JavaFX & SWT 2
M TableView Zeile hinzufügen AWT, Swing, JavaFX & SWT 5
Bluedaishi TableView mit Combox wert wird nicht in die TableView gesetzt AWT, Swing, JavaFX & SWT 38
J TableView Update/Refresh CPU AWT, Swing, JavaFX & SWT 2
B Text im Tetfeld in einer TableView darstellen AWT, Swing, JavaFX & SWT 20
J Tableview - kann man mit Enter die Zellen wechseln AWT, Swing, JavaFX & SWT 1
ralfb1105 JavaFX Dynamisch TableView Spalten erstellen AWT, Swing, JavaFX & SWT 4
M TableView + Datenbank Aktualisierung AWT, Swing, JavaFX & SWT 4
B TableView als PDF speichern AWT, Swing, JavaFX & SWT 8
B JavaFX TableView eine Zeile markieren AWT, Swing, JavaFX & SWT 5
B JavaFX JavaFX TableView PropertyValueFactory für Werte aus HashMap AWT, Swing, JavaFX & SWT 2
L JavaFX TableView Column Sortierung AWT, Swing, JavaFX & SWT 1
L Java FX Keine Anzeige Im Tableview AWT, Swing, JavaFX & SWT 4
L JavaFX TableView kein content text ändern AWT, Swing, JavaFX & SWT 2
L JavaFX TableView mit Aktionenbuttons AWT, Swing, JavaFX & SWT 1
C JavaFX Edit TableView in Verbindung mit SceneBuilder AWT, Swing, JavaFX & SWT 1
C JavaFX ProGuard -> TableView kein Inhalt AWT, Swing, JavaFX & SWT 7
J SceneBuilder TableView Checkbox AWT, Swing, JavaFX & SWT 1
J JavaFX Elemente werden nicht zu TableView hinzugefügt AWT, Swing, JavaFX & SWT 3
F JavaFX (Tree)TableView korrekt drucken AWT, Swing, JavaFX & SWT 1
robinab JavaFX TableView column resize nach setItems() AWT, Swing, JavaFX & SWT 0
G JavaFX TableView Wert in Spalte ändern AWT, Swing, JavaFX & SWT 0
S JavaFx - ausgewählte Rows in Arraylist (Tableview) AWT, Swing, JavaFX & SWT 4
S JavaFX - Populate TableView AWT, Swing, JavaFX & SWT 2
N JavaFX TableView aus Map AWT, Swing, JavaFX & SWT 2
J TableView Daten werden nicht ausgegeben AWT, Swing, JavaFX & SWT 9
B JavaFX TableView aus Collection befüllen AWT, Swing, JavaFX & SWT 1
S JavaFX TableView einzelne Zelle Layout zuweisen AWT, Swing, JavaFX & SWT 3
zhermann TableView die zweite AWT, Swing, JavaFX & SWT 7
H Java FX List<AlbumsBean> in FXML TableView AWT, Swing, JavaFX & SWT 37
E JavaFX TableView mit Zeilenumbruch in Zellen AWT, Swing, JavaFX & SWT 5
zhermann TableView wird nicht gefüllt AWT, Swing, JavaFX & SWT 14
M JavaFX JavaFX ResultSet in TableView ausgeben AWT, Swing, JavaFX & SWT 2
W JavaFX Mehrere Klassen in ein TableView AWT, Swing, JavaFX & SWT 6
MaxG. JavaFX Inhalt in Tableview wird nicht angezeigt AWT, Swing, JavaFX & SWT 11
M JavaFX berechneten Wert in TableView schreiben AWT, Swing, JavaFX & SWT 1
K JavaFX Message in TableView AWT, Swing, JavaFX & SWT 2
H TableView mit variabler Anzahl Spalten AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben