Wicket - Add tooltip to every cell in PropertyColumn - java

I really need your help by a wicket-problem.
I want to add a tooltip to all the rows(by mouse hover) in a PropertyColumn. But how can I do it? I've seen solutions with an Abstractcolumn. But I have to use a PropertyColumn because i need the propertyExpression and don't need the sortProperty.

One way is to modify the DataTable like this:
add(new DefaultDataTable("wicektid", null, null, 10) {
#Override
protected Item newCellItem(String id, int index, IModel model) {
Item item = super.newCellItem(id, index, model);
item.add(AttributeModifier.replace("title", "Your Title"));
return item;
}
#Override
protected Item newRowItem(String id, int index, IModel model) {
Item item = super.newRowItem(id, index, model);
item.add(AttributeModifier.replace("title", "Your Title"));
return item;
}
});
Here you have the control if you want the tooltip on whole rows or on individual cells.
If you want to do it in certain columns you can override populateItem in the column like this:
add(new PropertyColumn<>(){
#Override
public void populateItem(Item<ICellPopulator<T>> item, String componentId, IModel<T> rowModel) {
super.populateItem(item, componentId, rowModel);
}
});

I now have found the solution.
First thing, which is important to know is, that in the populateItem-Method, there has to be at least one object in it. For example a label. Because you can't add a string or a tooltip to a cell without something in it. So i had to put a label in it and added the string to that label. After that i've added a PrototipBehavior to the label:
public void populateItem(final Item cellItem, final String componentId, final IModel model) {
Long id = ((MyObject) model.getObject()).getId();
String desc = ((MyObject) model.getObject()).getDescription();
Label l = new Label(componentId, id + "");
l.add(new PrototipBehaviour(desc));
cellItem.add(l);
}

Related

GWT Java - CellTable - ButtonCell - how to make it respond to a click

I have the following ButtonCell. How do I make it respond to a click please (e.g., addClickHandler)? I have tried a number of ways I have found yet none work. None of the Window.alert return a response.
ButtonCell selectButton = new ButtonCell();
Column <HikingMeals,String> update = new Column <HikingMeals,String>(selectButton){
#Override
public String getValue(HikingMeals selectButton)
{
return "Select";
}
public void execute(HikingMeals selectButton) {
// EDIT CODE
Window.alert("Pressed");
}
//#Override
public void update(int index, HikingMeals object, String value) {
// The user clicked on the button for the passed auction.
Window.alert("Pressed2");
}
};
table.addColumn(update, "Select");
You just need to set a FieldUpdater on the update column:
update.setFieldUpdater(new FieldUpdater<HikingMeals, String>() {
#Override
public void update(int index, HikingMeals object, String value) {
Window.alert("Pressed");
}
});

JavaFX ComboBox - How to get different Prompt Text and Selected Item Text?

I've searched a bit, but couldn't find an answer. The Combobox is editable. How can I show different text in the Combobox prompt text and in the list of Objects below? In the list I want the toString method of the Object to be used, but when I select it, I want only one attribute of the selected Object to be shown in the prompt text.
How can I do this? Is it possible to display the value of an object differently in the prompt text field and in the list below?
An example of the usage would be with songs. Let's say I search a song by title, then it shows me the song with the title, composer and instrument below. When I select the song, I only want the title to be shown in the prompt text (because I display the composer and instrument Information somewhere else).
Use a converter that uses the short version for the conversion and a custom cellFactory to create cells displaying the extended version:
static class Item {
private final String full, part;
public Item(String full, String part) {
this.full = full;
this.part = part;
}
public String getFull() {
return full;
}
public String getPart() {
return part;
}
}
#Override
public void start(Stage primaryStage) {
ComboBox<Item> comboBox = new ComboBox<>(FXCollections.observableArrayList(
new Item("AB", "A"),
new Item("CD", "C")
));
comboBox.setEditable(true);
// use short text in textfield
comboBox.setConverter(new StringConverter<Item>(){
#Override
public String toString(Item object) {
return object == null ? null : object.getPart();
}
#Override
public Item fromString(String string) {
return comboBox.getItems().stream().filter(i -> i.getPart().equals(string)).findAny().orElse(null);
}
});
comboBox.setCellFactory(lv -> new ListCell<Item>() {
#Override
protected void updateItem(Item item, boolean empty) {
super.updateItem(item, empty);
// use full text in list cell (list popup)
setText(item == null ? null : item.getFull());
}
});
Scene scene = new Scene(comboBox);
primaryStage.setScene(scene);
primaryStage.show();
}

hide options in comboBox java swing

I'm wanting to create the option for users in a game to select their own piece to play with from a list of piece's that I have made. To do this I have two comboBox's that contain the same items in them but i dont want users to be able to select the same piece.
I have thought about removing the item from comboBox 1 if selected in comboBox2 (and adding it back later) but i am using the index of the selected item later when i assign the image to the 'player' class and so this would get messy there and also the indexing of each list would be different since they dont contain the item that the other has selected (hope that makes sense).
How can i make the item in comboBox 2 hidden or unselectable if it is selected in comboBox 1?
Many thanks
Create POJO which represents the basic properties of the Piece...
public class Piece {
private Image image;
private String name;
public Piece(String name, Image image) {
this.image = image;
this.name = name;
}
public Image getImage() {
return image;
}
public String getName() {
return name;
}
}
Add these to your JComboBox
Piece[] pieces = new Piece[]{
// Create what ever pieces you need...
}
DefaultComboBoxModel modelPlayer1 = new DefaultComboBoxModel(pieces);
DefaultComboBoxModel modelPlayer2 = new DefaultComboBoxModel(pieces);
JComboBox cbPlayer1 = new JComboBox(modelPlayer1);
JComboBox cbPlayer2 = new JComboBox(modelPlayer2);
You will find that you will probably need a ListCellRenderer of some kind in order to display the name of the Piece in the JComboBox, for example...
public class PieceListCellRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof Piece) {
value = ((Piece)value).getName();
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
Then apply the renderer to the comboboxes
cbPlayer1.setRenderer(new PieceListCellRenderer());
cbPlayer2.setRenderer(new PieceListCellRenderer());
Now, you don't need to care about the indecies, and because you've built the two models from the same array of Pieces you should have no issue simply removing them by reference...
Piece p = (Piece)cbPlayer1.getSelectedItem();
((DefaultComboBoxModel)cbPlayer2.getModel()).removeElement(p);
See How to Use Combo Boxes for more details

Is there any way to add objects to a JComboBox and assign a String to be shown?

I want to add objects to a JComboBox but show a String on the JComboBox for each object.
For example, in the following html code
<select>
<option value="1">Item 1</option>
<option value="2">Item 2</option>
<option value="3">Item 3</option>
<option value="4">Item 4</option>
</select>
in the first item, the String that is shown is "Item 1", but the value of the item is "1".
Is there a form to do something like that with a JComboBox?
Start by taking a look at How to Use Combo Boxes, in particular Providing a Custom Renderer
Basically, you want to define your object which will be contained within the combo box...
public class MyObject {
private String name;
private int value;
public MyObject(String name, int value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
}
Then create a custom ListCellRenderer that knows how to renderer it...
public class MyObjectListCellRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (value instanceof MyObject) {
value = ((MyObject)value).getName();
}
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
return this;
}
}
Then populate you combo box and apply the cell renderer...
JComboBox box = new JComboBox();
box.addItem(new MyObject(..., ...));
//...
box.setRenderer(new MyObjectListCellRenderer());
You could, equally, override the toString method of your object, but I tend to like to avoid this for display purposes, as I like the toString method to provide diagnostic information about the object, but that's me
If your combo box model contains objects, their toString() method will be used by default to display them in the combo box. If the toString() method displays what you want, you don't have anything to do.
Otherwise, you just need to set a cell renderer to customize the way each object is displayed (and that doesn't limit you to text: you can also change the font, color, icon, etc.).
This is all described in the Swing tutorial.
For example, in the following html code
For something simple like this, where you have an "ID", "Value" type of data, I do like the approach of a custom Object who's purpose in life is to provide a custom toString() method. See Combo Box With Hidden Data for such an reusable object.
Many people in the forums do recommend a custom renderer. Unfortunately using a custom renderer breaks the default functionality of the comobo box. See Combo Box With Custom Renderer for more information as a solution.
Yes, that can be done using the object type as the parameter for the JComboBox generic, like this:
public class TestFrame extends JFrame {
// This will be the JComboBox's item class
private static class Test {
private Integer value;
private String label;
public Test(Integer value, String label) {
this.setValue(value);
this.setLabel(label);
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
// The "toString" method will be used by the JComboBox to generate the label for the item
#Override
public String toString() {
return getLabel();
}
}
public static void main(String[] args) {
TestFrame frmMain = new TestFrame();
frmMain.setSize(300, 50);
frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Here you declare a JComboBox that
// uses the type "Test" for item elements
JComboBox<Test> cmbCombo = new JComboBox<TestFrame.Test>();
for (int i = 0; i < 10; i++) {
// Add some elements for the combo
cmbCombo.addItem(new Test(i, String.format("This is the item %d", i + 1)));
}
// Listen to changes in the selection
cmbCombo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JComboBox<Test> cmbCombo = (JComboBox<Test>) e.getSource();
// The selected element is a "Test" instance, just cast it to the correct type
Test test = (Test) cmbCombo.getSelectedItem();
// Manipulate the selected object at will
System.out.printf("The selected value is '%d'\n", test.getValue());
}
});
frmMain.add(cmbCombo);
frmMain.setVisible(true);
}
}

Dependent columns in a JTable

Hie!
I have a JTable. Columns of this JTable are rendered by JComboBox.
I would like to be able to change items of column 2 on the basis of values selected in column 1.
For example if the user selects Microsoft in column 1, then in column 2 he/she can select ado, wpf, etc.
Is it possible ?
If it is possible, than which events should be listened to do it ?
The Combo Box Table Editor provides one possible solution for this.
Maybe you can base you on this code;
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int row = table.getSelectedRow();
int column = table.getSelectedColumn();
}
}
);
This is an intresting page: click
Just make your own TableCellEditor that preps the JComboBox's model on the call to getTableCellEditorComponent. Something like this:
class MyEditor extends DefaultCellEditor{
public MyEditor() {
super(new JComboBox());
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JComboBox combo = (JComboBox)editorComponent;
Object column1Value = table.getValueAt(row, column-1);
Object[] options = ... create options based on other value
combo.setModel(new DefaultComboBoxModel(options));
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
What are you using as values in your TableModel?
One solution would be to define a class, say CategoryValue, that represents a list of possible items and a selected item, and use that; then listen for TableModelEvents and when a value in column 0 changes, set the corresponding value in column 1. A simple example is below.
First, the TableModelListener:
model.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
if (e.getColumn() == 0) {
int firstRow = e.getFirstRow();
int lastRow = e.getLastRow();
for (int row = firstRow; row <= lastRow; row++) { // note <=, not <
CategoryValue parentValue = ((CategoryValue) model.getValueAt(row, 0));
String parentSelection = parentValue.getSelection();
List<String> childCategories = getChildCategories(parentSelection);
CategoryValue newChildValue = new CategoryValue(childCategories);
model.setValueAt(newChildValue , row, 1);
}
}
}
});
(Implementing getChildCategories(String) depends on where your data is coming from, but it could be as simple as a Map<String, List<String>>.)
Next, the value class:
public class CategoryValue {
private final String selection;
private final List<String> categories;
public CategoryValue(List<String> categories) {
this(categories, categories.get(0));
}
public CategoryValue(List<String> categories, String selection) {
assert categories.contains(selection);
this.categories = categories;
this.selection = selection;
}
public String getSelection() {
return selection;
}
public List<String> getCategories() {
return categories;
}
#Override
public String toString() {
return selection;
}
}
Finally, a custom cell editor for the value class:
public class CategoryCellEditor extends DefaultCellEditor {
public CategoryCellEditor() {
super(new JComboBox());
}
static List<CategoryValue> allValues(List<String> categories) {
List<CategoryValue> allValues = new ArrayList<CategoryValue>();
for (String value: categories) {
allValues.add(new CategoryValue(categories, value));
}
return Collections.unmodifiableList(allValues);
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
CategoryValue categoryValue = (CategoryValue) value;
List<String> categories = categoryValue.getCategories();
List<CategoryValue> allValues = CategoryValue.allValues(categories);
ComboBoxModel cbModel = new DefaultComboBoxModel(allValues.toArray());
((JComboBox)editorComponent).setModel(cbModel);
return super.getTableCellEditorComponent(table, categoryValue,
isSelected, row, column);
}
}
All done with one event listener, and a nice bonus is that that event listener doesn't care how the table is edited/updated, or where the edits/updates come from.
Edited to add: Alternatively, represent each row of the table with some business object that captures all the choices made for a particular row, and have the CellEditor get the available choices from the business object (using the row argument to getTableCellEditorComponent() to get the business object). The event mechanism would remain the same. This has the advantage that it's probably easier to read the selected values from the business object than to scrape the table.

Categories