I have a small web application project using GWT, where a button handles an event: populating a panel with widgets. Currently, clicking the button a second time will duplicate the panel, i want it so it clears the panel, and re adds the widgets.
So far I have:
final Button b = new Button("get schools near me");
final HorizontalPanel panel = new HorizontalPanel();
panel.getElement().setId("distanceTable");
RootPanel.get("core").add(b);
RootPanel.get("core").add(panel);
b.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
Timer t = new Timer(){
#Override
public void run() {
//how do you clear the panel here first? before you
// do a bunch of things along the lines of:
panel.add(widget);
panel.add(widget2);
}
};
t.schedule(1400); // wait 1.4 seconds for callback
}
});
I get that anything you pass to the run function has to be as a final declaration, so how do I get around this?
You can use the clear method:
panel.clear();
Change final HorizontalPanel panel = new HorizontalPanel(); to a class level attribute. Then it can be easily passed on to the inner anonymous classes. And you can use the clear method inside Timer method as suggested by #philfr49
e.g
private HorizontalPanel panel = new HorizontalPanel();
.....
// Elsewhere
.....
final Button b = new Button("get schools near me");
panel.getElement().setId("distanceTable");
RootPanel.get("core").add(b);
RootPanel.get("core").add(panel);
b.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
Timer t = new Timer(){
#Override
public void run() {
panel.clear();
panel.add(widget);
panel.add(widget2);
}
};
t.schedule(1400); // wait 1.4 seconds for callback
}
});
Continued from the comments to the question -- using a timer to wait for a callback result is not recommended.
I assume you are working with a strict Model-View-Controller separation, and that the code you printed is the View part with the callback happening in a separate Controller class.
Now, if it is not a lot of things being added to the panel, I would use following construct:
/*
* contains all the display parts of the appliation
*/
class View{
private HorizontalPanel panel = new HorizontalPanel(); // panel as a field
/*
* Getter for panel
*/
public HorizontalPanel getPanel(){
return this.panel;
}
/**
* Method to create the display part for 'Schools Near Me'
*
* #param schoolsNearMeHandler Clickhandler that decides what happens
* when the 'near me' button is clicked
* Contains code to request from server
* and display server result
*/
public void createSchoolsNearMeSection(ClickHandler schoolsNearMeHandler){
final Button b = new Button("get schools near me");
panel.getElement().setId("distanceTable");
RootPanel.get("core").add(b);
RootPanel.get("core").add(panel);
b.addClickHandler(schoolsNearMeHandler);
}
}
/*
* Creates and operates the View and makes sure the correct things get displayed
*/
class Controller{
private View view;
public Controller(){
// since the Controller drives the Model-View-Controller part,
// the view is being created here
view = new View();
// TODO more code to set up the view to perfection
// Create the 'schools near me' section
view.createSchoolsNearMeSection(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
loadSchoolsNearMe(); // send request to server
}
}
}
/**
* Loads schools near me from the server
*/
private void loadSchoolsNearMe(){
// generic callback -- use whatever callback interface is required for your way of requesting data from server
Callback callback = new Callback(){
public void onSuccess(ServerResult result){
// retrieve the panel where you want to display your data
HorizontalPanel panel = view.getPanel();
panel.clear();
// TODO execute whatever code necessary to create
// widget and widget2 from the ServerResult
// display the newly generated widgets
panel.add(widget);
panel.add(widget2);
}
public void onError(...){
// handle errors
}
}
// Create request
Request request = new Request(...);
// Execute request
RequestBuilder.execute(request, callback);
}
}
Of course, if there is a lot of complicated code and view-building to be done with the server result, you could once again put the display-part into the View object, keep the logic in the Controller, and just call the corresponding View functions to display whatever necessary.
Related
I'm trying to create a simple Web Application with Google Web Toolkit. I have a button that I want to update another widget whenever it is clicked. The event handler for the onClick() event is defined in a separate file. I have tried passing a reference to the object as an argument to the method that is handling the event:
Button submitButton = new Button(
"Submit",
new ClickHandler() {
public void onClick(ClickEvent event){
getContentService.getContent(url.getText(),
new GetContentCallBack(theGwt));
}
}
);
And here is what it looks like inside of the GetContentCallBack.onSuccess method (note that I've set the gwtRef inside of the constructor):
public void onSuccess(TargetContent result) {
// TODO Auto-generated method stub
this.gwtRef.setProxyHTML(new HTML("<Working!>", true));
Window.alert("I've updated the html");
}
I get the alert box, but the HTML widget does not update. What am I doing wrong, and how am I supposed to do this?
I am having the following problem which is exclusive to the oracle forms framework and custom implementation classes provided in java. I modified a VButton to display a custom menue as soon as i am pressing the right mouse button.
The following was accomplished by inheriting from the VButton and providing a custom behavior.
The popup will be displayed by a JPopupMenu. This JPopupMenu will be filled dynamicly by a HashMap<String, JMenuItem> which represents each option in this JPopupMenu and it´s representing key. To accomplish this i wrote an abstract class which contains everything that needs to be done to create a custom right click menu, with two abstract methods. These methods will be overriden by subclasses of this class and will create two representing lists of Keys for the Map and theyr representing JMenuItem.
This is how the abstract class is designed.
public abstract class AbstractRightClickButton extends VButton{
// The PopupMenu for this item;
private JPopupMenu popup = new JPopupMenu();
// The HashMap that stores the Menuitems and it´s keys
private HashMap<String, JMenuItem> menuItems = new HashMap<String, JMenuItem>();
// Stores the current selected key.
private String choice= "";
public AbstractRightClickButton() {
this.menuItems = generateHashmap();
initMouseListener();
initPopUp();
}
// Abstract method to create an ArrayList of all JMenuItem
public abstract ArrayList<JMenuItem> generateJMenuItemSide();
// Abstract method to create an ArrayList for each key in the HashMap
public abstract ArrayList<String> generateStringSide();
private void initPopUp() {
ArrayList<String> list = generateStringSide();
for (String counter : list) {
popup.add(menuItems.get(counter));
}
}
private void initMouseListener() {
this.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e)) {
// If the width of the popup is 0 then it wasn´t displayed yet. Just show it once and make it invisible again to get the width and height of the popup.
if (popup.getWidth() == 0) {
popup.show(AbstractRightClickButton.this, AbstractRightClickButton.this.getWidth(), 0);
popup.setVisible(false);
}
popup.show(AbstractRightClickButton.this, AbstractRightClickButton.this.getWidth()-popup.getWidth(), 0);
}
}
public void mouseExited(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
});
protected HashMap<String, JMenuItem> generateHashmap() {
HashMap<String, JMenuItem> map = new HashMap<String, JMenuItem>();
ArrayList<String> key = generateStringSide();
ArrayList<JMenuItem> value = generateJMenuItemSide();
for (int i = 0;i < key.size();++i) {
map.put(key.get(i), value.get(i));
}
return map;
};
// This method is a helper method that can be called by subclasses of AbstractRightClickButton
// It creates a JMenutButton based on the parameter
protected JMenuItem generateJMenuItem(final String key, final boolean click) {
JMenuItem item = new JMenuItem(new AbstractAction(key) {
#Override
public void actionPerformed(ActionEvent e) {
choice = key;
if (click) {
ActionEvent act = new ActionEvent((Object)AbstractRightClickButton.this, ActionEvent.ACTION_PERFORMED, ""); // Button Event erstellen
AbstractRightClickButton.this.processEvent(act); // Event Processen um den Buttondruck Formsseitig auch auszulösen
}
}
});
return item;
}
}
A concrete class would look like this
public class ConcreteRightClickButton extends AbstractRightClickButton{
#Override
public ArrayList<String> generateStringSide() {
ArrayList<String> basis = new ArrayList<String>(0);
basis.add("OPTION1");
basis.add("OPTION2");
return basis;
}
#Override
public ArrayList<JMenuItem> generateJMenuItemSide() {
ArrayList<JMenuItem> basis = new ArrayList<JMenuItem>(0);
basis.add(generateJMenuItem("OPTION1", true));
basis.add(generateJMenuItem("OPTION2", true));
return basis;
}
}
The problem i am facing depends on the type of button, espacially how this button is defined in the forms builder. If the button property iconic is defined as No, then the call of AbstractRightClickButton.this.processEvent(act) correctly processes this event and can be handelt by the When-Button-Pressed Event in Oracle Forms. But if the button property iconic is defined as Yes then the processing of the event somehow doesn´t work. While Debugging everything looks fine, there is no exception and it reaches the AbstractRightClickButton.this.processEvent(act) without any problem. But the representing When-Button-Pressed Trigger in Oracle Forms doesn´t react. Am i processing the Event incorrectly or is there something else that stops oracle forms from recieving this event?
I am using Oracle forms 11g to create a mask containing this specific button.
1 year 8 months later, maybe this isn't an "answer" but its an alternative way to do the same thing.
Create a class that extends VBean, and create a JButton.
Add the jar to the classpath, and call it within a Bean Area.
It's called java pluggable components.
This page is useful:
JPC
EDIT:
import java.awt.Color;
import javax.swing.JButton;
import oracle.forms.ui.VBean;
public class TryButton extends VBean {
JButton button = new JButton();
public TryButton() {
this.setSize(500, 500);
this.setVisible(true);
this.add(button);
button.setSize(500, 500);
button.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/imagen2.png")));
}
}
Then, add the jar to: oracle_home/forms/java
and add it to classpath
In oracle forms in a new canvas create a Bean Area
Go to Item Properties and add the class package and name to: implementation class.
I'm studying the GWT framework and I'm trying to create a custom widget: this widget is a button that contain inside a menu of operations.
if you click in the area of the triangle I want a menu with some options (that are possible operations) and if I click in the other parts of the buttons I want that the operation is the first from the list.
I have put a ListBox widget inside a Button widget and I want 2 different clickListener. The problem is that the listener of the listBox inside the button don't work.
Do you know why?
Following the code
public class MyClass extends Composite {
private ListBox options;
private Button saveButton;
private HorizontalPanel savePanel;
private int indexHandler;
public MyClass(String label, List<String> operationList, final List<Command> commandList) {
savePanel = new HorizontalPanel();
initWidget(savePanel);
options = new ListBox();
saveButton = new Button(label);
for(String operation : operationList){
options.addItem(operation);
}
options.sinkEvents(Event.ONCLICK);
options.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
System.out.println("Test1");
indexHandler = options.getSelectedIndex();
commandList.get(indexHandler).execute();
options.setItemSelected(0, true);
}
});
saveButton.getElement().appendChild(options.getElement());
saveButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
System.out.println("Test2");
commandList.get(0).execute();
options.setItemSelected(0, true);
}
});
savePanel.add(saveButton);
}
}
Don't use ClickHandler on the ListBox. Use ChangeHandler instead.
Also, I don't think you need to mess with Elements here. Simply add your Button widget and your ListBox widget to a container (i.e. some panel). You can add button on top of ListBox, if you want.
I'm trying to figure out how to make it so that my navigation menu, when clicked, will open appropriate panels within my GWT page.
Here's a part of my code:
#Override
public void onModuleLoad()
{
MainNavBar nb = new MainNavbar();
NavItem i = new NavItem("1", "TestNavItem");
nb.add(i);
i = new NavItem("2", "TestNavItem2");
nb.add(i);
}
So when I run the project, I see that I have a menu on the test site:
So my question is, how can I have an event handler such that when either one of those are clicked, the panel to the right will be changed to something else?
Thanks!
create an actionListener class,
public class listen implements actionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource() == ObjectName){
// Your code goes here....
}
}
}
then create an object of this class e.g
listen listener = new listen();
YourObjectName.addActionListener(listener);
Don't forget to make the imports, hope this helps...
In my Swing app, users can click a button to open a dialog panel and enter some values, then they can click "Ok" on that panel to close it and return to the main program, but how can I pass the values they enter to the main program without saving them to a file first ?
There are a couple things you could do:
You could create an Observer/Observable relationship between your app and the dialog, and make the dialog publish an event when the dialog closes with the values in the event.
You could maintain a handle to your dialog in your app, and when you call setVisible(false) on dialog, you can query the dialog for its data.
The UI should usually be layered upon the underlying application. (IMO, the UI should itself be split into layers, but that another rant.) Pass in a relevant part of your application to the creation of your UI. When you are ready for values to go from the UI to the application (which could be an OK button on a multi-page dialog, down to every keystroke), push the data to the application component.
Rather than using just the poor Java Observable/Observer API, I'd rather advise you take a look at an "Event Bus", which should be particularly suited for your situation.
Two implementations of Event Buses:
EventBus very general event bus,
can be used in any situation
GUTS Event Bus specific to Guice dependency injection library
One of these should help you with your current problem.
Just define an interface with a single method (like: "returnToCaller(returntype rt)") in your dialog class.
The Constructor of the dialog takes an instance of this interface as input, and uses it to return results on exit/ok.
The mainmodule (window or whatever) simply instantiates the dialog and thus makes annonymous use of the interface, defininng the return method, sort of like a delegate (c#).
The call then being:
MyDialog md = new MyDialog(new MyDialog.ReturnToCaller() {
public void returnToCaller(ReturnValues rv) {
// Handle the values here
}
});
md.setModal(true);
md.setVisible(true);
I would suggest MVC(Model-view-controller) design. So dialog will be you view and possibly controller. But have to have a domain class which will be your model. For example, if the dialog is created to edit personal data, then you can have class called Person which will hold the data. The dialog should be designed in the way so you can set and get a Person from it.
The class implementing your dialog panel must have a link to your main program, and your main program must provide a method with parameters that will be the values to transmit.
Then your dialog panel class listen to the Ok button, and on the button click, it retrieve the values and use them with the aforementionned method.
class Main {
//...
private Dialog myDialog ;
public Main(){
//...
myDialog = new Dialog(this);
//...
}
//...
public void onDialogOk(String valueA, int valueB)
{
//...
}
}
class Dialog implement ActionListener{
//...
private Main myMain ;
public setMain(Main main){
myMain = main;
}
public Dialog(Main main){
//...
setMain(main) ;
//...
JButton ok = new JButton("ok") ;
ok.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
// retrieve form values
String valueA = ... ;
int valueB = Integer.parse(...);
myMain.onDialogOK(valueA, valueB) ; //DONE
}
}
May be you would like to try this solution:
class MyDialog {
private static String[] returnValues = new String[10]
private static MyDialog dialog;
private MyDialog() {
initDialog()
}
private void closeDialog()
{
dispose();
}
private initDialog()
{
//....
btnOk = new JButton("OK");
jTextField1 = new JTextField();
...
jTextField10 = new JTextField();
...
ActionListener btnOK_click = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
returnValues[0] = jTextField1.getText();
...
returnValues[9] = jTextField10.getText();
closeDialog();
}
}
btnOk.addActionListener(btnOk_click);
}
public static String[] showMyDialog() {
dialog = new MyDialog();
dialog.setVisible(true);
return returnValues;
}
}