I'm trying to delete items in my ListView when delete Button is clicked, but it is not working and I can't figure it out.
Here is an Example of my Code for deleting an entry based on the instance "Student":
public void deleteButton(ActionEvent actionEvent) {
if (notesListView.getSelectionModel().isEmpty()) {
InfoModal.show("Bitte wählen Sie die zu löschende Notiz aus.");
return;
}
boolean delete = ConfirmationModal.show("Soll die Notiz gelöscht werden?");
if (delete) {
Dao<Notepad, Integer> notepadDao = db.getNotepadDao();
try {
if (this.objectType instanceof Student) {
Dao<StudentNotepad, Integer> studentNotepadDao = db.getStudentNotepadDao();
for (StudentNotepad n : studentNotepadDao) {
if (notesListView.getSelectionModel().getSelectedItem().equals(n.getNotepad())) {
SceneManager.getInstance().getLoaderForScene(SceneType.NOTESTAB_WINDOW).
<NotesTabController>getController().notesListView.getItems().remove(n.getNotepad());
studentNotepadDao.delete(n);
notepadDao.delete(n.getNotepad());
}
}
}
}
}
}
This is how my ListView/ListCell is initiated:
public void setObject(Object object) {
//Getting Object Type (Group, Groupage or Student)
this.objectType = object;
try {
if (this.objectType instanceof Student) {
ObservableList<Notepad> list = FXCollections.observableArrayList();
for (StudentNotepad s : db.getStudentNotepadDao()) {
if ((db.getLoggedInUser() == s.getNotepad().getUser()) && ((((Student) this.objectType).getId() == s.getStudent().getId()))) {
list.add(s.getNotepad());
}
}
notesListView.setItems(list);
notesListView.getItems().clear(); //not needed if list is definitly empty
db.getStudentNotepadDao().queryForAll().stream()
.map(StudentNotepad::getNotepad)
.filter(n -> n.getUser().equals(db.getLoggedInUser()))
.forEach(notesListView.getItems()::add);
notesListView.setCellFactory(new Callback<ListView<Notepad>, ListCell<Notepad>>() {
public ListCell<Notepad> call(ListView<Notepad> param) {
return new ListCell<Notepad>() {
#Override
protected void updateItem(Notepad item, boolean empty) {
super.updateItem(item, empty);
String style = "";
if (!empty && item != null) {
setText(item.getNotepadName());
switch (item.getNotepadPriority()) {
case "Hoch":
style = "-fx-background-color: red";
break;
case "Mittel":
style = "-fx-background-color: yellow";
break;
case "Niedrig":
style = "-fx-background-color: green";
break;
case "Neutral":
style = "-fx-background-color: grey";
break;
}
}
else {
setText("");
}
setStyle(style);
}
};
}
});
}
} catch(SQLException e) {
e.printStackTrace();
}
}
Additionally, my List is not refreshing after changing the Object within the same ObjectType. Example: Changing from Student1 to Student2. Changing between ObjectTypes themselves like Student1 to Group1 works. I think that the problem lays in the filter function of my ListCell.
Does someone have an idea? I'm struggeling with this problem for hours and can't figure it out!
Related
i m trying to create a ListView, that some cell base on what they have inside can not be clicked. that works fine for now but the problem is when i click an element that is disabled, it return me the that last element which i clicked.
here is how i create the ListView
public ListView<String> createStringList(int sizeX, int sizeY) {
ListView<String> list = new ListView<String>();
list.setMaxSize(sizeX, sizeY);
list.setMinSize(sizeX, sizeY);
list.setStyle("-fx-font-size:8.0;");
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else if (Main.controller.getGame().chessBot != null) {
setText(item);
String botColor = Main.controller.getGame().chessBot.getBotColor().toString();
if (botColor.equals("BLACK")) {
if (item.contains("Black") || item.contains("Schwarz")) {
setDisable(true);
}else {
setDisable(false);
}
} else {
if (item.contains("White") || item.contains("Weiß")) {
setDisable(true);
}else {
setDisable(false);
}
}
} else {
setText(item);
setDisable(false);
}
}
};
}
});
return list;
}
Here i add the list on the Pane
...
...
historyList = GUIToolCreator.getInstance().createStringList(120, 220);
//TODO:
historyList.setOnMouseClicked(e -> {
int selectedIndex = getSelecetedInHistoryList();
if (selectedIndex >= 0) {
System.out.println(Main.controller.getGame().getHistory().get(selectedIndex).getStart().toSmallString() + "-"
+ Main.controller.getGame().getHistory().get(selectedIndex).getEnd().toSmallString() + ": Color ->"
+ Main.controller.getGame().getHistory().get(selectedIndex).getColor());
} else {
System.out.println("can not be selected!");
}
});
...
...
here all i need is that this method return -1 if the selected cell is disable but instead i recieve the last cell that i clicked
public int getSelecetedInHistoryList() {
int selectedIndex = historyList.getSelectionModel().getSelectedIndex();
if (selectedIndex == -1) {
return selectedIndex;
}
System.out.println(selectedIndex);
if (Main.controller.getGame().chessBot != null) {
if (Main.controller.getGame().chessBot.getBotColor() == Main.controller.getGame().getHistory()
.get(selectedIndex).getColor()) {
selectedIndex = -1;
}
}
return selectedIndex;
}
I'm trying to build custom content into a JavaFX table based on the object in the table cell. My feeling is that I can use the setCellFactory to do this, but I'm at a loss....
for instance...if I have an interface for my data:
public interface dbBase { ... }
then, each of my datatypes implement that interface
public class dbType1 implements dbBase { ... }
public class dbType2 implements dbBase { ... }
public class dbType3 implements dbBase { ... }
then, when setting up my table, I have...
dataColumn.setCellFactory(data -> {
// what should I put here?
});
dataColumn is:
TableColumn<dbBase, object> dataColumn;
So, my question is:
How can I return a custom TableViewCell based on the type of the object in the column?
I couldn't find anyway to determine the type of the class at the time of the setCellFactory call, so I decided to subclass TreeTableCell instead. That way I could change up the GUI anytime an item was updated.
So, my setCellValueFactor and setCellFactory call now looks like this:
dataColumn.setCellValueFactory(p ->
new SimpleObjectProperty<object>(p.getValue().getValue()));
dataColumn.setCellFactory(p -> new CustomTreeTableCell());
and CustomTreeTableCell() looks like this:
public class CANESTreeTableCell extends TreeTableCell<dbBase, object> {
private final Button button;
private final TextField textField;
private final CheckBox checkBox;
private ObservableValue<object> observable;
public CustomTreeTableCell() {
this.button = new Button();
this.textField = new TextField();
this.checkBox = new CheckBox();
}
#Override
public void updateItem(object item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setGraphic(null);
} else {
final TreeTableColumn<dbBase, object> column = getTableColumn();
observable = column==null ? null :
column.getCellObservableValue(getIndex());
if(item instanceof dbType1) {
if(observable != null) {
button.textProperty().bind(
observable.getValue().getNameProperty());
} else if (item!=null) {
button.setText(item.getName());
}
setGraphic(button);
} else if (item instanceof dbType2) {
if(checkBox != null) {
checkBox.textProperty().bind(
observable.getValue().getNameProperty());
} else if (item!=null) {
checkBox.setText(item.getName());
}
setGraphic(checkBox);
} else if (item instanceof dbType3) {
if(observable != null) {
textField.textProperty().bind(
observable.getValue().getNameProperty());
} else if (item!=null) {
textField.setText(item.getName());
}
setGraphic(textField);
} else {
setGraphic(null);
}
}
}
}
I have a combobox which shows list of User objects. I have coded a custom cell factory for the combobox:
#FXML ComboBox<User> cmbUserIds;
cmbUserIds.setCellFactory(new Callback<ListView<User>,ListCell<User>>(){
#Override
public ListCell<User> call(ListView<User> l){
return new ListCell<User>(){
#Override
protected void updateItem(Useritem, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId()+" "+item.getName());
}
}
} ;
}
});
ListView is showing a string(id+name), but when I select an item from listview, Combobox is showing toString() method return value i.e address of object.
I can't override toString() method, because the User domain object should be same as the one at server.
How to display id in combobox? Please suggest
EDIT1
I tried below code. Now combo box shows id when I select a value from the listview.
cmbUserIds.setConverter(new StringConverter<User>() {
#Override
public String toString(User user) {
if (user== null){
return null;
} else {
return user.getId();
}
}
#Override
public User fromString(String id) {
return null;
}
});
The selected value in combo box is cleared when control focus is lost. How to fix this?
EDIT2:
#FXML AnchorPane root;
#FXML ComboBox<UserDTO> cmbUsers;
List<UserDTO> users;
public class GateInController implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
users = UserService.getListOfUsers();
cmbUsers.setItems(FXCollections.observableList(users));
cmbUsers.getSelectionModel().selectFirst();
// list of values showed in combo box drop down
cmbUsers.setCellFactory(new Callback<ListView<UserDTO>,ListCell<UserDTO>>(){
#Override
public ListCell<UserDTO> call(ListView<UserDTO> l){
return new ListCell<UserDTO>(){
#Override
protected void updateItem(UserDTO item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getUserId()+" "+item.getUserNm());
}
}
} ;
}
});
//selected value showed in combo box
cmbUsers.setConverter(new StringConverter<UserDTO>() {
#Override
public String toString(UserDTO user) {
if (user == null){
return null;
} else {
return user.getUserId();
}
}
#Override
public UserDTO fromString(String userId) {
return null;
}
});
}
}
Just create and set a CallBack like follows:
#FXML ComboBox<User> cmbUserIds;
Callback<ListView<User>, ListCell<User>> cellFactory = new Callback<ListView<User>, ListCell<User>>() {
#Override
public ListCell<User> call(ListView<User> l) {
return new ListCell<User>() {
#Override
protected void updateItem(User item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId() + " " + item.getName());
}
}
} ;
}
}
// Just set the button cell here:
cmbUserIds.setButtonCell(cellFactory.call(null));
cmbUserIds.setCellFactory(cellFactory);
You need to provide a functional fromString() Method within the Converter!
I had the same problem as you have and as I implemented the fromString() with working code, the ComboBox behaves as expected.
This class provides a few of my objects, for dev-test purposes:
public class DevCatProvider {
public static final CategoryObject c1;
public static final CategoryObject c2;
public static final CategoryObject c3;
static {
// Init objects
}
public static CategoryObject getCatForName(final String name) {
switch (name) {
case "Kategorie 1":
return c1;
case "Cat 2":
return c2;
case "Steuer":
return c3;
default:
return c1;
}
}
}
The converter object:
public class CategoryChooserConverter<T> extends StringConverter<CategoryObject> {
#Override
public CategoryObject fromString(final String catName) {
//This is the important code!
return Dev_CatProvider.getCatForName(catName);
}
#Override
public String toString(final CategoryObject categoryObject) {
if (categoryObject == null) {
return null;
}
return categoryObject.getName();
}
}
When adding the key it displays key added but then when I type inventory it says backpack empty, also when I go to use the item it wont let me, as its not usable.
public class Get extends AbstractCommand {
public Get (String name, String description){
super (name, description);
}
#Override
public void execute (Game game, String string) {
Item temp = game.getCurrentRoom().getItem(string);
UserInterface ui = game.getUI();
if(temp == null) ui.println("Item added\n");
else if (!(temp instanceof Moveable)) ui.println("item can not be moved");
else if (!game.getBackpack().add(temp)) ui.println("item can not be moved");
else game.getCurrentRoom().removeItem(temp);
}
}
#Override
public void execute(Game game, String string){
Item itemInBag = game.getBackpack().getItem(string);
Item itemInRoom = game.getCurrentRoom().getItem(string);
if(itemInBag!= null) {
if(itemInBag instanceof Useable){
game.setGameState(((Useable)itemInBag).use(game));
}else game.getUI().println("you can not use item");
}else if(itemInRoom!= null){
if(itemInRoom instanceof Useable){
game.setGameState(((Useable)itemInRoom).use(game));
}else game.getUI().println("this item can not be used");
}else {
game.getUI().println("take the item and use when you need to");
}
}
}
public class Inventory extends AbstractCommand {
public Inventory (String name, String description){
super (name, description);
}
#Override
public void execute (Game game, String string) {
if(((BackpackImpl)game.getBackpack()).getCount()==0) {
game.getUI().println("Backpack is empty");
}else {
for(Item i: game.getBackpack().getItems()) {
game.getUI().println(i.getName());
}
}
}
}
List<Item> items;
int maxCapacity;
public BackpackImpl (int maxCapacity){
this.maxCapacity = maxCapacity;
items = new ArrayList<Item>(5);
}
public BackpackImpl () {
this.maxCapacity = 5;
}
#Override
public boolean add(Item item){
if(items.size()>maxCapacity)
{System.out.println("your backpack canot fit no more\n");
return false;
}
items.add(item);
return true;
}
#Override
public Item remove(String string){
for(Item i: items){
if(((i.getName()).toLowerCase()).equals(string.toLowerCase())) {
items.remove(i);
return i;
}
}
return null;
}
#Override
public Item getItem(String string){
for(Item i: items){
if(((i.getName()).toLowerCase()).equals(string.toLowerCase())) {
return i;
}
}
return null;
}
#Override
public int getCapacity(){
return maxCapacity;
}
#Override
public List<Item> getItems(){
return items;
}
public int getCount (){
return items.size();
}
public void clear(){
items.clear();
}
}
Due to the "if/else (if)" construction in your Get.execute method, a new item is never added via the BackpackImpl.add() method.
Revise your Get.execute method and only print "Item added" when your code has actually called the BackpackImpl.add() method. Also, to keep your code readable, always use {} when using "if/else (if)" constructions. E.g.:
if (temp == null) {
ui.println("Item added\n");
} else if (!(temp instanceof Moveable || game.getBackpack().add(temp))) {
ui.println("item can not be moved");
} else {
game.getCurrentRoom().removeItem(temp);
}
Our application displays a CellTable which has an ImageResourceCell column:
Column<Alert, ImageResource> noteColumn = new Column<Alert, ImageResource>(new ImageResourceCell()) {
#Override
public ImageResource getValue(Alert alert) {
if (alert.getNote() != null && alert.getNote().length() > 0) {
return images.note();
} else {
return images.emptyNote();
}
}
};
dataTable.addColumn(noteColumn, "");
We would like to modify this column so that a PopupPanel is displayed when the user moves his mouse over the image. The content of the PopupPanel should be specific for each row in the column. What is the best way to achieve this?
My initial attempt (based on an answer to a somewhat-similar question) looks like this, however the problem here is that I am not able to get the "note" from each Alert for the PopupPanel:
private class MyImageResourceCell extends ImageResourceCell {
#Override
public Set<String> getConsumedEvents() {
Set<String> consumedEvents = new HashSet<String>();
consumedEvents.add("mouseover");
consumedEvents.add("mouseout");
return consumedEvents;
}
#Override
public void onBrowserEvent(Context context,
Element parent,
ImageResource value,
NativeEvent event,
ValueUpdater<ImageResource> imageResourceValueUpdater) {
switch (DOM.eventGetType((Event) event)) {
case Event.ONMOUSEOVER:
// show panel
break;
case Event.ONMOUSEOUT:
// hide panel
break;
default:
break;
}
}
}
private void createAndAddNoteColumn() {
Column<Alert, ImageResource> noteColumn = new Column<Alert, ImageResource>(new MyImageCell()) {
#Override
public ImageResource getValue(Alert alert) {
if (alert.getNote() != null && alert.getNote().length() > 0) {
return images.note();
} else {
return images.emptyNote();
}
}
};
dataTable.addColumn(noteColumn, "");
}
Instead of creating the PopupPanel as part of the table column, I left the column as a normal ImageResource column, and then added a cellPreviewHandler to capture the mouseover event for the column in question:
final DecoratedPopupPanel simplePopup = new DecoratedPopupPanel(true);
dataTable.addCellPreviewHandler(new CellPreviewEvent.Handler<Alert>() {
#Override
public void onCellPreview(CellPreviewEvent<Alert> alertCellPreviewEvent) {
if ("mouseover".equals(alertCellPreviewEvent.getNativeEvent().getType())
&& alertCellPreviewEvent.getColumn() == 5
&& alertCellPreviewEvent.getValue().getNote() != null) {
// using hard-coded column number isn't the most elegant solution, but it's ok for now.
int left = alertCellPreviewEvent.getNativeEvent().getClientX();
int top = alertCellPreviewEvent.getNativeEvent().getClientY();
simplePopup.setWidget(new HTML(alertCellPreviewEvent.getValue().getNote()));
simplePopup.setPopupPosition(left, top);
simplePopup.show();
} else {
simplePopup.hide();
}
}
});