JavaFX Table mit MenuButton

ZebaX

Mitglied
Hallo,

gibt es die Möglichkeit, wenn ich ein Objekt auf eine Zelle legen auch ein anderes Value anzeigen zu lassen in dieser Zelle?

dazu mal bischen Code:


Java:
	private Callback<TableColumn, TableCell> cellFactory;
	private ObservableList<TableColumn<PortAdmin, ?>> columnList;
	
	private Settings_Port() {
		cellFactory = new Callback<TableColumn, TableCell>() {
			@Override
			public TableCell call(TableColumn param) {
				return new EditingCell();
			}
			
		};
	}

        public void setList(ObservableList<TableColumn<PortAdmin,?>> list){
		this.columnList = list;
		setCellValueFactory();
	}
        
        private void setCellValueFactory() {
                TableColumn tc = this.columnList.get(0);
		tc.setCellValueFactory(new PropertyValueFactory<PortAdmin, Ports>("port"));
		tc.setCellFactory(cellFactory);
        }

Java:
class EditingCell<T> extends TableCell<PortAdmin, Object>{
		private TextField textField;
		private ToggleButton toggleButton;
		private ChoiceBox<Boolean> choiceBox;
		private MenuButton choice;
			
		public EditingCell(){
		}
		
		@Override
        public void startEdit() {
            if (!isEmpty()) {
                super.startEdit();
                createSelector();
            }
        }
 
        @Override
        public void cancelEdit() {
            super.cancelEdit();
 
            setText(String.valueOf(getItem()));
            setGraphic(null);
        }
 
        @Override
        public void updateItem(Object item, boolean empty) {
            super.updateItem(item, empty);
           
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {            
                if (isEditing()) {
                    if (textField != null) {
                        textField.setText(getString());
                    }
                    setText("");
                    setGraphic(textField);
                } else {
                    setText(getString());
                    setGraphic(null);
                }
            }
        }
        
        private void createSelector(){
        	Object o = getItem();
        	if(o instanceof Integer){
        		createTextField();
        		setText(null);
                setGraphic(textField);
                textField.selectAll();	
        	}
        	
        	if(o instanceof Boolean){
        		createChoiceBox();
        		setText(null);
        		setGraphic(choiceBox);
        		choiceBox.selectionModelProperty();
        	}
        	
        	if(o instanceof IPropertieValues){
        		createChoiceMenu();
        		setText(null);        		
        		setGraphic(choice);        		
        	}
        }
 
        private void createChoiceMenu(){        	
        	final IPropertieValues pv = (IPropertieValues)getItem();
        	choice = new MenuButton();
        
        	setSize(choice);
        	
        	ObservableList<CheckMenuItem> cmi = FXCollections.observableArrayList();

        	for(Entry<IPort, Boolean> e : pv.getList().entrySet()){
        		CheckMenuItem item = new CheckMenuItem(e.getKey().getName());
        		item.setSelected(e.getValue());
        		cmi.add(item);
        	}
  
        	choice.getItems().addAll(cmi);
        	choice.setText(String.valueOf(pv.countSelectedItems()));
        	        	
        	for(final CheckMenuItem item : cmi){
        		item.selectedProperty().addListener(new ChangeListener<Boolean>() {
					@Override
					public void changed(
							ObservableValue<? extends Boolean> observable,
							Boolean oldValue, Boolean newValue) {
						
						if(newValue){
							pv.addSelectedItem(pv.getPortByName(item.getText()),true);
							choice.setText(String.valueOf(pv.countSelectedItems()));
							choice.arm();
							
						}else{
							pv.addSelectedItem(pv.getPortByName(item.getText()),false);
							choice.setText(String.valueOf(pv.countSelectedItems()));
						}
						
					}
				});
        	}
        }
        
        private void createChoiceBox(){
        	choiceBox = new ChoiceBox<Boolean>(FXCollections.observableArrayList(true,false));
        	choiceBox.setValue(Boolean.valueOf(getItem().toString()));
        	setSize(choiceBox);

        	choiceBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Boolean>(){
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) {
                        if (!arg2) {
                        	commitEdit(valueToString(String.valueOf(choiceBox.getValue())));
                            
                        }
                }
            });
            
            
        }
        
        private void createToggleButton(){
        	toggleButton = new ToggleButton();
        	toggleButton.setSelected(false);
        	setSize(toggleButton);
        	toggleButton.focusedProperty().addListener(new ChangeListener<Boolean>(){
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) {
                        if (!arg2) {
                            commitEdit(valueToString(String.valueOf(toggleButton.isSelected())));
                        }
                }
            });
        	
        }
        
        private void createTextField() {
            textField = new TextField(getString());
            setSize(textField);
            textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) {
                        if (!arg2) {
                            commitEdit(valueToString(textField.getText()));
                        }
                }
            });
        }
        
        private void setSize(Control c){
        	c.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
        }
 
        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
               
        private T valueToString(String s){
        	Object object = null;
        	        	
        	if(getItem() instanceof Integer)
        		object = Integer.parseInt(s);
        	
        	if(getItem() instanceof Boolean)
        		object = Boolean.parseBoolean(s);
        	
        	
        		
        	return (T) object;
        }
        
}

Den code hab ich mehr oder weniger von Oracle so übernommen und ausgebaut. Das mit dem auswählen aus dem ChoiceMenu klapt auch soweit nur wenn ich eine andere zelle bearbeite dann ist diese mit dem ChoiceMenu immer leer rein von der ansicht her. Hätt da gern nen String oder int wert stehe oder im ideal fall das der MenuButton permanent angezeigt wird und nicht nur wenn man die zelle doppelClicked
 
Das Beispiel ist schon etwas unübersichtlich - was nicht deine Schuld ist, das liegt leider fast schon in der Natur der Sache.

Nur zu deinem Verständnis, was hier eigentlich passiert:
* im Normalzustand, zeige nur den Text
* wenn im Edit-Modus, dann zeige nur den Graphics-Node

Soweit ist es klar denke ich, aber es gibt da ein Problem: Du setzt jedes mal den Text auf null, was nicht nötig ist. Setze im Edit-Modus (#startEdit()-Methode) einfach das Flag
Java:
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Wenn du den Edit-Modus beendest (#cancelEdit()) dann entsprechend
Java:
setContentDisplay(ContentDisplay.TEXT_ONLY);
Damit musst du nicht jedes Mal den Text löschen und hinzufügen.

Aber das ist eigentlich nur eine Randnotiz, denn du möchtest - wenn ich es richtig verstehe - das eigentlich vorne der Text steht und dahinter ein Menü-Knopf, oder?

Wenn ja, musst du in deiner #updateItem-Methode eigentlich nur wie oben genannt
Code:
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setzen und am besten eine HBox mit einem Label und einem Button erstellen und in den Graphics-Node einfügen (ich finde immer noch, dass der Graphics-Node super toll ist, weil man eben eine komplette UI einfügen kann, aber denkbar beschissen benannt wurde - sicher, meist befüllt man es nur mit einem ImageView, aber trotzdem). Ein Klick auf den Button öffnet dann einfach ein Menü. Wenn das Dein Ziel ist und du hast das soweit und ärgerst dich, dass das Menü falsch positioniert wird, dann schreib noch einmal hier und ich poste den Code zu dem Menü mit korrekter Platzierung auch noch.

Wenn nein - dann erkläre es bitte noch einmal.
 
Zuletzt bearbeitet:
Ok ein Problem hätt ich noch wie... wie schaff ich es das von anfang an die richtigen Graphics angezeigt werden? Die werden ja momentan nur angezeigt nachdem ich das erste mal in der zelle war...
 
Gibt es auch "falsche" Graphics??? Eher nein.

Wie gesagt: Einfach in #updateItem()
Code:
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setzen. Wichtig ist nur: Du solltest den Graphics-Node natürlich auch mit Zeug befüllen. Sonst ist die Zelle einfach nur leer.
 
Also anfangs waren die zellen komplett leer ohne Graphic aber egal das ist gelöst nun aber zum nächsten problem.
Zum einen warum wird die updateMethode so oft aufgerufen, was auch steigt sobald ich eine weitere Zeile hinzufüge.
Und das andere ist das ständig meine Werte gelöscht werden sobald ich eine Zeile hinzufüge.

Hinzufügen geschieht durch das adden eines objects in die zur Tabelle gehörende ObservableList.
Das adden ansich geht auch nur das er alle werte löscht ;(
 

Zurück
Oben