I am looking into JFace for Eclipse development. I made a plugin to act as a dummy content provider for a ComboViewer. This provider essentially provides the data model as an ArrayList of hardcoded values. Anyway, I tried to understand the approach.
I set the model on the ComboViewer via the comboViewer.setInput(list) method.
On the press of a button I call another object's method that updates the list I passed as input to the ComboViewer (adds another element) and I call comboViewer.refresh to reflect the change, but nothing happens.
Turns out:
I need to call comboViewer.setInput(list) with the updated list to see the changes in the data (i.e. the previous addition) in my UI combo. I found that comboViewer.refresh reflects any updates only if I get the a hold of comboViewer's passed as input Object and modify that. I.e. if I do:
List<SomeObject> data = ((List<SomeObject>)(comboViewer.getInput()));
data.add(new SomeObject("aaa","cccc"));
comboViewer.refresh();
Only like this the data are refreshed. But I don't understand what is the proper way to use these APIs.
Am I supposed to ever get a hold and modify the object I pass in the setInput method? It feels I should not be doing it. So what is the purpose of refresh?
What is the proper way to do updates of the data that are provided to the Viewers?
The proper way to reflect changes is to call refresh. The list
String[] values = {"1","2","3"};
List<String> list = new ArrayList<String>(Arrays.asList(values));
create components
final ComboViewer comboViewer = new ComboViewer(shell, SWT.DROP_DOWN);
comboViewer.setLabelProvider(new LabelProvider());
comboViewer.setContentProvider(new ArrayContentProvider());
comboViewer.setInput(list);
Button button1 = new Button(shell, SWT.PUSH);
button1.setText("Button 5");
button1.addSelectionListener(new SelectionListener(){
#Override
public void widgetSelected(SelectionEvent e) {
// TODO Auto-generated method stub
System.out.println("Button 5");
list.add("4");
comboViewer.refresh();
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
when you push the button the combo viewer is updated.
Related
I'm new to vaadin and I'm a bit confused with the save and cancel button when setEditorEnabled = true.
Do you need to provide additional codes in order to save the data or it automatically saves all the data to the database when you click on save?
If there are aditional codes, how do I add a listener to the save and cancel buttons?
Thanks!
If you use buffered mode, the edited values are written to the source object when you press the Save button. If you use unbuffered mode, the edition is written instantly, so the Save and Cancel button becomes meaningless.
If you want to write the edited object back to a database, you will need to add that functionality manually. It is practical to use buffered mode in this case and add the database calling method to a method that is called when the save button is pressed.
Besides adding it to a CommitHandler's postCommit method, like Daniel Dubec writes, you can also override the saveEditor() and doCancelEditor() methods of the Grid.
class MyGrid extends Grid {
public MyGrid() {
setEditorEnabled(true);
setEditorBuffered(true);
}
#Override
public void saveEditor() throws CommitException {
super.saveEditor();
// You can persist your data here.
Notification.show("Item " + getEditedItemId() + " was edited.");
}
// Be aware that doCancelEditor() is called whenever super.saveEditor() is called!
#Override
protected void doCancelEditor() {
super.doCancelEditor();
// editedItemId was already set to 'null'.
Notification.show("Cancel button was pressed");
}
}
What super.saveEditor() does is actually calling the commit() method on the editorFieldGroup. But this is only meaningful, if the editable grid is in buffered mode. Read more on Field Buffering here.
So what happens is, when you press the save button, and super.saveEditor() is called, then first the pre-commit event is fired, then the the changes in the editor field values are updated to the data source (that is the commit itself), then the post-commit event is fired. The doCancelEditor() method is called whenever the editor itself is closed, this is why it is called after a save too.
Or use saveListener. I am not sure if this is the best way, but it works for me.
Grid<Bean> grid;
grid.getEditor().addSaveListener(new EditorSaveListener<Bean>() {
#Override
public void onEditorSave(EditorSaveEvent<Bean> event) {
// You can persist your data here
persistBean(event.getBean());
}
});
try to add CommitHandler for FieldGroup
grid.setEditorEnabled(true);
// register save listener
grid.getEditorFieldGroup().addCommitHandler(new CommitHandler() {
#Override
public void preCommit(CommitEvent commitEvent) throws CommitException {
}
#Override
public void postCommit(CommitEvent commitEvent) throws CommitException {
// You can persist your data here
Notification.show("Item " + grid.getEditedItemId() + " was edited.");
}
});
So I am experiencing some odd behaviour using Vaadin 7 and the ComboBox component. Essentially, what is happening is that when it first renders the form, it appears to neither have selected the null selection nor any of the items added.
I have attempted to recreate this behaviour with the following code and this demonstrates the issue.
#Override
protected void init(VaadinRequest request) {
final FieldGroup binder;
FormLayout form = new FormLayout();
form.setMargin(true);
setSizeFull();
setContent(form);
final Label output = new Label();
form.addComponent(output);
ComboBox box = new ComboBox("My Dropdown");
final PropertysetItem fields = new PropertysetItem();
fields.addItemProperty("country", new ObjectProperty<String>(""));
binder = new FieldGroup(fields);
binder.bind(box, "country");
box.addItem("aus");
box.setItemCaption("aus", "Australia");
box.addItem("uk");
box.setItemCaption("uk", "United Kingdom");
box.setRequired(true);
box.setImmediate(true);
box.setRequiredError("Country is required field");
Button submit = new Button("Submit", new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
try {
binder.commit();
output.setValue((String) fields.getItemProperty("country").getValue());
}
catch (CommitException e) {
Notification.show("fail!");
}
}
});
form.addComponent(box);
form.addComponent(submit);
}
By default the ComboBox has allow null selection set to true. So there is a blank entry, which represents a null value selection. However the ComboBox's value when first rendered neither represents the null selection nor one of the items but an empty string.
So when I load the form and click the button the outcome is neither a failure, which it should be because I haven't selected anything yet, nor one of my selections.
This is causing an issue for me in a more advanced UI application but very much the same thing going on here.
Could anybody enlighten me as to what is happening here?
Many thanks,
Joe
So when I load the form and click the button the outcome is neither a
failure, which it should be because I haven't selected anything yet,
nor one of my selections.
Combobox is not empty as you think. It has default property value, that you set as empty string:
fields.addItemProperty("country", new ObjectProperty<String>(""));
Thus form pass validation, because empty string is also a value and empty string != null.
Change this row:
fields.addItemProperty("country", new ObjectProperty<String>(""));
to:
fields.addItemProperty("country", new ObjectProperty<String>(null, String.class));
box.setNullRepresentation("-- Select Country --");
I have this code:
DOM.setEventListener(row.getElement(), new ClickListener(){
#Override
public void onClick(Widget sender) {
// TODO Auto-generated method stub
}});
I think the code is fine and ClickListener extends EventListener, but it gives error saying: The method setEventListener(Element, EventListener) in the type DOM is not applicable for the arguments (Element, new ClickListener(){})
The real answer is that you probably don't. While this is available to attach listeners to events, you may only attach a single listener per element - that listen then gets all dom events that have been configured (see DOM.sinkEvents) - and you are responsible for making sure to detach all listeners before the page unloads, else some browsers will leak memory.
Instead, strongly consider using a Widget (and subclasses) to manage events. RootPanel, the base widget that others should be added to, will manage detaching all other widgets from the page to prevent memory leaks.
Additionally, you are able to listen to the events that happen within there based on the kind of event you are after. For example, even on a widget like a Label that doesnt' normally fire mouseover events, you can still attach handlers and get notification:
Label label = new Label();
label.addDomHandler(new MouseOverHandler() {
#Override
public void onMouseOver(MouseOverEvent event) {
// do something
}
}, MouseOverEvent.getType());
RootPanel.get().add(label);
In most cases, you'll be using existing support methods, like Button to get a click event - there are convinience methods already there for you, thanks to interfaces like HasClickHandlers:
Button button = new Button();
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// do something
}
});
panel.add(button);
More on GWT, Widget, and Memory leaks:
https://developers.google.com/web-toolkit/articles/dom_events_memory_leaks_and_you
http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks
I am writing an RCP application in eclipse that contains a combobox, and upon selecting any of its items, a selection event is being fired and some random code comes in action. The listener looks something like this:
randomComboBox.addSelectionListener(new SelectionListener(){
#Override
public void widgetSelected(SelectionEvent e) {
// random code
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
My question is: is it possible to fire the event from the code? For example if I add:
randomComboBox.select(0);
no event is being fired. In this case, do I have to write my own listener?
The select method of the combo box sends an event of the type SWT.Modify when it changes the selection, so you could use a ModifyListener instead of a SelectionListener.
Actually, the ModifyListener listens to changes in the text field of the combo box, this means it reacts to the text change that is caused by the selection. This also means that it will be fired if that text is changed by other paths (e.g. user entries in the combo text field).
Keeping that behaviour in mind, a ModifyListener might be an option.
Do not use ModifyListener if your ComboBox is "Read Only"
Combo comboBoxColor = new Combo(composite, SWT.BORDER | SWT.READ_ONLY);
You can fire any event explicitly (Programmatically)
For e.g.
control.notifyListeners(eventType , event);
In your case:
comboBoxColor.notifyListeners(SWT.Selection, new Event())
SWT.Selection -> Event type, you can get all event constants from SWT class.
new Event() -> Event object
I'm writing an applet and want to figure out how to make a button and a key event cover the same bit of code. For this question, I'll call this button fireButton. The code for the action event would of course look like this:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == fireButton) {
//all the code that pressing button executes
}
}
Now, I want pressing the 'enter' key to perform the same code that the action event handles, but I do not want to rewrite all the code again in a keyPressed method.
To be specific, I'm writing a battleship program, and the 'Fire' button takes input from two textFields, handles exceptions, and passes the input as parameters to a method that fires at a particular square in the grid. Ideally, pressing the enter key would function the same way as if I had pressed the fire button. Is there a way to make a certain method call an actionPerformed method? If not, what would be an elegant solution to the problem?
Create an Action
Add the Action to the JButton
Use Key Bindings to bind the Enter key to the Action
Read the Swing tutorial. There are sections on:
How to Use Actions
How to Use Key Bindings
If you are just talking about invoking the "Fire" button with the enter key then check out Enter Key and Button for a couple of approaches.
I suggest you put all the code in a separate method that receives all the relevant data from the event (if any) as parameters:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == fireButton) {
Object relevantData0 = new Object(); // e.getSomething();
Object relevantData1 = new Object(); // e.getSomethingElse();
handleFireAction(relevantData1, relevantData2);
}
}
public void actionPerformed(KeyEvent e) {
if (e.getSource() == fireButton) {
Object relevantData0 = new Object(); // e.getSomething();
Object relevantData1 = new Object(); // e.getSomethingElse();
handleFireAction(relevantData1, relevantData2);
}
}
private void handleFireAction(Object relevantData0, Object relevantData1) { // Object relevantDat2, and so on
//all the code that pressing button executes
}
If you don't need any data from the event its even easier ;)
This way you just write your code once for both events. It's a general OO aproach.
Hope this helps.
Borrowing from MVC I would recommend you have a controller class which handles these sorts of requests. Then all you have to do is delegate to the controller in each event handler.
Like so:
public class BattleShipController {
public void handleFireAction() {
// ...
}
}
//-- in your UI class(es)
private BattleShipController _controller = new BattleShipController();
//-- in event calls:
_controller.handleFireAction();
If you post relevant code I can make further suggestions.