There are two listeners:
table.addListener(new ItemClickListener() {
public void itemClick(ItemClickEvent event) {
// fireEvent(...);
}
});
table.addListener(new Table.ValueChangeListener() {
public void valueChange(final ValueChangeEvent event) {
// do something
}
});
I want to fire an event from the first listener to call the second.
In one listener, I want to update the data source for the table by clicking on the row; in the second listener, I want to restore the cursor on the selected row.
How can I do it?
If you change a column value of a row, then second listener is fired. To do so, you can change the column then you can regain its value in the second listener.
You shouldn't be trying to manually trigger events. If you have code in the second listener that needs to be called, you should abstract it out into a third method.
It's difficult to understand exactly what you want, however. I would suggest adding more details to your question.
Related
I have a method which is called at a event of a value change in a JComboBox
public void actionPerformed( ActionEvent e )
{
Object source = e.getSource();
if( source.equals( listComboBox ) )
{
changeList();
}
}
public void changeList()
{ //do some stuff
.....
.....
//warn the user
}
My problem is that this method is called at the initial load method as well.
In the method there is a warning message pop up.
Which is only needed when the user is changing the selected value of the combo box.(Not when i set a value from the code at the loading method.)
Is there a way(flag,different method) to distinguish between these to actions and give the warning message only when its needed?
My problem is that this method is called at the initial load method as well.
So add the listener to the combo box AFTER the load is finished.
You have two options. The first one is to apply a unique listener to each component and handle the event differently ( Which I prefer in most cases cause it keeps code simple for each component and way better to read).
The Second one is to identify which component trigger the event. One way to check that is by taking the sources of the event and check if it matches with the actual object or you can just check if it is 'instanceof' JComboBox and then handle the event as you pleased.
if(sourceObject == myComboBox ){
// handle the event
}
or
if(sourceObject instanceof JComboBox{
// then we are dealing with a combobox
// if it's the only one then you know what to do..
}
my question is. Is possible to add a component like a button (button has a functionality that triggered when it is clicked) inside a list component?
This image explain better what I refer:
http://2.bp.blogspot.com/-HThpKcgDyRA/URI_FdpffMI/AAAAAAAAAUI/SficZAPXaCw/s1600/1.png
Yes but it requires some handcoding and it will only work for touch (since you won't be able to assign focus to it).
We normally recommend just using Component/Container hierarchies for these cases rather than dealing with lists but obviously this isn't always practical.
The key is to always use the list action listener to trigger events, nothing else. So when you are in the action handling code of the list you would want to know if it was triggered by your button...
If you are in the GUI builder this is pretty easy:
Button b = ((GenericListCellRenderer)list.getRenderer()).extractLastClickedComponent();
if(b != null && b == myButton) {
// your event code here for the button, the selected entry is list.getSelectedItem()/Index()
}
The handcoded approach is pretty similar with one major caveat, you don't have the extractLastClickedComponent method. So assuming you have a component within the renderer just add an action listener to it. Within the action listener just set a flag e.g.:
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
buttonWasClicked = true;
}
});
// within the list listener we do the exact same thing:
if(buttonWasClicked) {
// for next time...
buttonWasClicked = false;
// your event code here for the button, the selected entry is list.getSelectedItem()/Index()
}
Yes!!! Try it, this is pretty easy:....
http://www.codenameone.com/how-do-i---create-a-list-of-items-the-easy-way.html
http://www.codenameone.com/how-do-i---create-a-list-of-items-the-hard-way-gui-builder-renderer.html
I have two separate components, one is a class that extends JTable, the other is a class that extends JPanel (contains a form).
Both are displayed on the same view when that application is run, when I click on a row on the table, I expect the textfileds on the form to be updated but nothing happens
I use observer (the form class is the listener) pattern to send the clicked row to the class/ panel containing the form fields to be updated, the values are received but the textfields are not updated.
The code below is in the form class and it updates the form fields, the form class is added as a listener in the table class, the method below is fired when a table row is clicked
public void onTableRowClick(CollectedParcelEvent e)
{
JOptionPane.showMessageDialog(null,"test", "test", 1);
txtCost.setText(Double.toString(e.getSource().getCost()));
txtCustomerName.setText(e.getSource().getCustomer().getName());
txtCost.repaint();
txtCost.revalidate();
}
public void onTableRowClick(CollectedParcelEvent e)
{
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
//JOptionPane.showMessageDialog(null,"test", "test", 1);
txtCost.setText(Double.toString(e.getSource().getCost()));
txtCustomerName.setText(e.getSource().getCustomer().getName());
}
});
}
Events are handled on the single event thread. There the GUI is not responsive for other events, and one should postpone doing such things later with invokeLater.
I don't understand why are you calling revalidate(); as its just tells the layout manager to reset based on the newly added or removed component list.
See this link for more answers about using revalidate(); and also this one
And perhaps, repaint(); should be enough for the required change.
So check your method to see if it really gets fired or not.
I have written a Swing GUI with several controls associated with the same Action subclass. The implementation of the Action subclass follows this psudocode:
public class MyGUI
{
Gizmo gizmo_; // Defined elsewhere
public class Action_StartPlayback extends AbstractAction
{
/* ctor */
public Action_StartPlayback(String text, ImageIcon icon, String desc, Integer mnem)
{
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnem);
}
#Override public boolean isEnabled()
{
return gizmo_ == null;
}
#Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
}
Action_StartPlayback act_;
};
The action is associated with both a button and a menu item, in a way similar to this psudocode:
act_ = new Action_StartPlayback(/*...*/);
// ...
JButton btn = new JButton(act_);
JMenu mnu = new JMenu(act_);
When I click the button or the menu item, the action's actionPerformed is fired correctly, gizmo_ is initialized and is non-null and everything works as expected -- except that the button and menu item are still enabled.
I expected that isEnabled would have been called again "automagically" but this is obviously not happening. isEnabled() is never called again.
This evokes two questions:
Is it OK for me to #Override the isEnabled() method as I have done here?
Assuming the answer to #1 is yes, how do I trigger a refresh of the GUI so that isEnabled() is called again, resulting in the button & menu item being disabled?
Instead of overriding setEnabled you could simply call setEnabled(false) after you intitialize your gizmo in your actionPerformed method:
#Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
setEnabled(false);
}
Here's the setEnabled implementation from AbstractAction:
public void setEnabled(boolean newValue) {
boolean oldValue = this.enabled;
if (oldValue != newValue) {
this.enabled = newValue;
firePropertyChange("enabled",
Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
}
}
The automagical you're looking for is the call to firePropertyChange, which notifies components based on this action that the state has changed, so the component can update its own state accordingly.
I am no pro at this, but I don't see a see an automatic way of doing this, of notifying listeners that the state of enabled has changed. Of course you can call setEnabled(false) at the start of the actionPerformed, and then code Gizmo (or a wrapper on Gizmo) to have property change support and then add a PropertyChangeListener to Gizmo, and in that listener, when the state changes to DONE, call setEnabled(true). A bit kludgy but it would work.
This is not strictly limited to Swing, but a more general Java principle. A lot of classes in the JDK (and in other libraries) have a getter and a setter for a property. Those methods are not meant to be overridden to return a dynamic value as most of the times the superclass accesses the corresponding field directly and does not go through the getters.
If you have dynamic behavior, you should call the corresponding setter each time the value changes. This will notify the super class changes have been made, and typically this will also fire a property change event to notify other interested parties.
You can find a bit more on this convention if you do a search on Java beans.
In your case, a possible solution is to let your UI class fire a PropertyChangeEvent when that gizmo instance changes, and let your actions listen for that event. When they receive such an event, they update their own enabled state.
The enabled-state is stored in both of your objects, in the AbstractAction and in the JButton.
This is important because you only need one instance of Action_StartPlayback for multiple Components like:
In the menu's button.
In a toolbar.
In a Shortcut Strgp in example.
All of them can have the same instance of Action_startPlayback. The Action_startPlayback is the only source of truth. The components are responsible to respect this source of truth so every Component will ask the AbstractAction to notify them if something has been changed. The AbstractAction will remember all the components and will notify them using the Method firePropertyChange().
But how to repaint all pending components? You must force all pending Components to ask the Action_startPlayback for the actuall enabled-state! Look at this:
#Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
// now, force the components to get notified.
setEnabled(true);
}
I'm developing an application where I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
I have done the first part using a DocumentListener and putting the relevant code in its insertUpdate method.
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls. Is it possible to trigger the action from the DocumentListener? Is it a good idea to use Actions at all, or should I just put my code in a normal method?
(in the constructor):
textAreaInput.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
// do something
}
public void removeUpdate(DocumentEvent e) {}
public void changedUpdate(DocumentEvent e) {}
});
and the Action, which is a field:
Action doSomething = new AbstractAction("Do Something!") {
#Override
public void actionPerformed(ActionEvent e) {
// do it
}
};
clarification:
The JTextArea will receive text that is pasted in by the user, which I want to parse automatically. The parsing depends on other values set elsewhere in the GUI; if the user changes these other values, he may want to re-parse the text, hence the need to perform the same action by pressing a button.
I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
This doesn't make sense to me.
Why would clicking a button invoke the same Action as a user typing text into a text area?
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls
That statement is meant for controls that the user clicks, like JMenuItems, JButtons or hitting Enter on a text field. In general they can be used when you use an ActionListner.
A DocumentListener is not an ActionListener so as I stated earlier the use of an Action doesn't seem appropriate.
I think you need to clarify your requirement.
Edit, based on clarification
if the user changes these other values, he may want to re-parse the text
Why does the user have a choice? If you change the font, text, foreground, background of a text area, the component it automatically repainting, you don't have to ask for this to be done. If you look at the code for these methods they always end up invoking the revalidate() and repaint() methods.
The parsing depends on other values set elsewhere in the GUI;
Sounds like you need a custom class. Maybe a ParsedTextArea or ParsedDocument. This class would contain the "properties" that can be set elsewhere in the GUI. It would implmenent the DocumentListener. It would also support your "parseTheText" method. So whenever a property is changed or a DocumentEvent is generated you automatically invoked the "parseTheText" method. This way you don't need a separate button and the component will always be in sync because the parsing is automatic.
You can invoke the actionPerformed() method, whether it's in an Action or not. There's an example here.
I think you need not create the Action object. You can add ActionListener to the Button just like you have added DocumentListener to the Document of the input. If I correctly understand your problem, may be you should do something like this:
textInput.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
doIt();
}
#Override
public void removeUpdate(DocumentEvent e) {}
#Override
public void changedUpdate(DocumentEvent e) {}
});
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
doIt();
}
});
doIt() is a method in which you will do what you wanted to do.