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
Related
See below for code sample, the method handleMouseDoubleClick method will take seconds to run and open another layout screen containing buttons and links. End users may click many times on one listed item in the table control and create flood of mouse events, how can I handle the last mouse event only?
Table tableControl = (Table) control;
tableControl.addMouseListener(new MouseAdapter()
{
public void mouseDown(MouseEvent e)
{
handleMouseDown(e);
}
public void mouseUp(MouseEvent e)
{
handleMouseUp(e);
}
public void mouseDoubleClick(MouseEvent e)
{
handleMouseDoubleClick(e);
}
}
Create a flag field. Set it to true when handler was called. Initialize it with false.
You just need to check whether your screen is already initialized or not before creating another one.
Set the cursor to hourglass and/or disable the table, resetting these after the new "layout screen" is closed...
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 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.
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.
I have an editable JComboBox where I want to take some action whenever the text is changed, either by typing or selection. In this case, the text is a pattern and I want to verify that the pattern is valid and show the matches that result in some test data.
Having done the obvious, attach an ActionHandler, I have found that, for typing, the event seems to fire unreliably, at best (selection is fine). And when it does fire as a result of typing, the text retrieved (using getEditor().getItem(), since getSelectedItem() only gets the text when it was selected from the list) seems to be the text as it was when the last event was fired - that is, it's always missing the character was typed immediately before the action event was fired.
I was expecting the action event to fire after some short delay (500ms to 1 second), but it seems immediately fired upon keying (if it is fired at all).
The only workable alternative I can think of is to simply start a 1 second timer on focus-gained, killing it on focus-lost and doing the work as the timer action if the content is different from last time.
Any thoughts or suggestions?
The code snippets are not particularly interesting:
find.addActionListener(this);
...
public void actionPerformed(ActionEvent evt) {
System.out.println("Find: "+find.getEditor().getItem());
}
The action listener is typically only fired when you hit enter, or move focus away from the editor of the combobox. The correct way to intercept individual changes to the editor is to register a document listener:
final JTextComponent tc = (JTextComponent) combo.getEditor().getEditorComponent();
tc.getDocument().addDocumentListener(this);
The DocumentListener interface has methods that are called whenever the Document backing the editor is modified (insertUpdate, removeUpdate, changeUpdate).
You can also use an anonymous class for finer-grained control of where events are coming from:
final JTextComponent tcA = (JTextComponent) comboA.getEditor().getEditorComponent();
tcA.getDocument().addDocumentListener(new DocumentListener() {
... code that uses comboA ...
});
final JTextComponent tcB = (JTextComponent) comboB.getEditor().getEditorComponent();
tcB.getDocument().addDocumentListener(new DocumentListener() {
... code that uses comboB ...
});
You can use somthing like this:
JComboBox cbListText = new JComboBox();
cbListText.addItem("1");
cbListText.addItem("2");
cbListText.setEditable(true);
final JTextField tfListText = (JTextField) cbListText.getEditor().getEditorComponent();
tfListText.addCaretListener(new CaretListener() {
private String lastText;
#Override
public void caretUpdate(CaretEvent e) {
String text = tfListText.getText();
if (!text.equals(lastText)) {
lastText = text;
// HERE YOU CAN WRITE YOUR CODE
}
}
});
this sounds like the best solution
jComboBox.getEditor().getEditorComponent().addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) { //add your hadling code here:
} });