How to fire event when scrolling up,javafx - javafx-8

I am developing chat application on java and i want to use function used by facebook to retrieve chat history when user scroll up. I tried "on Scroll" action which fire event whenever scroll reach top or down of scroll bar. Now i want to Fire action event only when scroll bar reach top like in facbook chat box.

Assuming that you have a ScrollPane, you can observe vvalueProperty of it:
scrollPane.vvalueProperty().addListener(
(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
if(newValue.doubleValue() == 0){
System.out.println( "AT TOP" );
// load more items
}
});
and you may also scroll to bottom with
scrollPane.setVvalue( scrollPane.getVmax() );
initially.

Here is the example of what you want. I hope this will help you.
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ScrollUtil extends Application
{
private boolean scrollToBottom = false;
private boolean scrollToTop = false;
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(final Stage stage) throws Exception
{
final VBox root = new VBox();
final ScrollPane scrollPane = new ScrollPane();
final VBox vBox = new VBox();
vBox.setAlignment(Pos.BOTTOM_CENTER);
scrollPane.setContent(vBox);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
Button button = new Button("add");
Button button3 = new Button("scroll up");
button3.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent actionEvent)
{
scrollToTop = true;
scrollPane.setVvalue(scrollPane.getVmin());
System.out.println("vmin= "+scrollPane.getVmin() + "; vmax = " + scrollPane.getVmax() + "; vvalue" + scrollPane.getVvalue());
}
});
button.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent actionEvent)
{
vBox.getChildren().add(new Label("hallo"));
scrollToBottom = true;
//System.out.println(scrollPane.getVmin() + "; max = " + scrollPane.getVmax() + "; " + scrollPane.getVvalue());
}
});
scrollPane.setVvalue(scrollPane.getVmax());
scrollPane.vvalueProperty().addListener(new ChangeListener<Number>()
{
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
{
if(scrollToBottom)
{
scrollPane.setVvalue(scrollPane.getVmax());
scrollToBottom = false;
}
if(newValue.doubleValue() ==0)
{
vBox.getChildren().add(new Label("hallo"));
System.out.println("min value ="+scrollPane.getVmin());
//scrollPane.setVvalue(scrollPane.getVmin());
scrollToTop = true;
System.out.println("now get the chat history");
}
}
});
Button button2 = new Button("scroll");
button2.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent actionEvent)
{
scrollPane.setVvalue(Double.MAX_VALUE);
}
});
root.getChildren().addAll(scrollPane, button, button2, button3);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}

Related

JavaFX Custom Table Cell - Strange behavior

I have this code:
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class Example extends Application
{
#Override
public void start(Stage stage) throws Exception
{
TableView<Color> table = new TableView<>();
ObservableList<Color> colors = FXCollections.observableArrayList();
table.setItems(colors);
table.setEditable(true);
TableColumn<Color, Color> column = new TableColumn<>();
column.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue()));
column.setCellFactory(param ->
{
ObservableList<Color> menuColors = FXCollections.observableArrayList();
menuColors.addAll(Color.RED, Color.GREEN, Color.BLUE);
return new ComboBoxTableCell(menuColors);
});
Button button = new Button("Add row");
button.setOnAction(event -> colors.add(Color.BLACK));
VBox box = new VBox(table, button);
table.getColumns().add(column);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
stage.setScene(new Scene(box));
stage.show();
}
public class ComboBoxTableCell extends TableCell<Color, Color>
{
private ComboBox<Color> comboBox;
public ComboBoxTableCell(ObservableList<Color> colors)
{
comboBox = createFancyComboBox(colors);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
#Override
public void updateItem(Color item, boolean empty)
{
if (item == null || empty)
setGraphic(null);
else
setGraphic(comboBox);
}
}
private ComboBox<Color> createFancyComboBox(ObservableList<Color> colors)
{
ComboBox<Color> comboBox = new ComboBox<>(colors);
Callback<ListView<Color>, ListCell<Color>> factory = list -> new ColorSquare();
comboBox.setCellFactory(factory);
comboBox.setButtonCell(factory.call(null));
comboBox.setValue(colors.get(0));
return comboBox;
}
public static class ColorSquare extends ListCell<Color>
{
#Override
public void updateItem(Color item, boolean empty)
{
super.updateItem(item, empty);
Rectangle rect = new Rectangle(18, 18);
if (item != null)
{
rect.setFill(item);
setGraphic(rect);
}
}
}
public static void main(String[] args)
{
launch(args);
}
}
If I try to run it, click on the button, change the color to for Green and click 8 times on the button, the green square will disapper.
How do I fix this and why is it happening? The real code isn't much different from this, this is the only problem I have. Thank you.
I have noticed that at times the rerendering of a table cell doesn't work right after a certain number of attempts. I had one where I was updating a remaining amount when the user entered a value in another cell.
To solve this I would toggle visibility of the column.
column.setVisible(false);
column.setVisible(true);
I would do this immediately after the action that changed the value in the cell.
It's a hack but seems to work.

FXML, JavaFX 8, TableView: Make a delete button in each row and delete the row accordingly

I am working on a TableView (FXML) where I want to have all the rows accompanied with a delete button at the last column.
Here's a video that shows what I mean: YouTube Delete Button in TableView
Here's what I have in my main controller class:
public Button del() {
Button del = new Button();
del.setText("X");
del.setPrefWidth(30);
del.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
int i = index.get();
if(i > -1) {
goals.remove(i);
list.getSelectionModel().clearSelection();
}
}
});
return del;
}
private SimpleIntegerProperty index = new SimpleIntegerProperty();
#Override
public void initialize(URL location, ResourceBundle resources){
//DateFormat df = new SimpleDateFormat("dd MMM yyyy");
sdate.setValue(LocalDate.now());
edate.setValue(LocalDate.now());
seq.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("id"));
gol.setCellValueFactory(new PropertyValueFactory<Goals, String>("goal"));
sdt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("sdte"));
edt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("edte"));
prog.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("pb"));
del.setCellValueFactory(new PropertyValueFactory<Goals, Button>("x"));
list.setItems(goals);
list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
#Override
public void changed(ObservableValue<?> observable,
Object oldValue, Object newValue) {
index.set(goals.indexOf(newValue));
System.out.println("Index is: "+goals.indexOf(newValue));
}
});
}
Each time I launch the application, I will try to click the delete button from random rows but it always delete the first row. I guess the addListener method I use for list is not properly implemented and indexOf(newValue) is always 0 at every initialisation.
However, it will work if I click a row first and then click the delete button. But this is not what I want. I want users to be able to delete any row if they press the delete button without selecting the row.
Appreciate your help guys!
You need a custom cell factory defined for the column containing the delete button.
TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setCellValueFactory(
param -> new ReadOnlyObjectWrapper<>(param.getValue())
);
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
private final Button deleteButton = new Button("Unfriend");
#Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (person == null) {
setGraphic(null);
return;
}
setGraphic(deleteButton);
deleteButton.setOnAction(
event -> getTableView().getItems().remove(person)
);
}
});
Here is a sample app. It doesn't use FXML, but you could adapt it to work with FXML very easily. Just click on an "Unfriend" button in the "Anti-social" column to delete a friend. Do it a lot and you will soon run out of friends.
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class GestureEvents extends Application {
private TableView<Person> table = new TableView<>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final Label label = new Label("Friends");
label.setFont(new Font("Arial", 20));
final Label actionTaken = new Label();
TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setMinWidth(40);
unfriendCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
private final Button deleteButton = new Button("Unfriend");
#Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (person == null) {
setGraphic(null);
return;
}
setGraphic(deleteButton);
deleteButton.setOnAction(event -> data.remove(person));
}
});
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<>("lastName"));
table.setItems(data);
table.getColumns().addAll(unfriendCol, firstNameCol, lastNameCol);
table.setPrefHeight(250);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 10, 10, 10));
vbox.getChildren().addAll(label, table, actionTaken);
VBox.setVgrow(table, Priority.ALWAYS);
stage.setScene(new Scene(vbox));
stage.show();
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person(String fName, String lName) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
}

Dynamically adding data in Hashmap to TableView in JavaFX

I have a map mapping symbols to prices.I want to display a table with one column containing keys and the other column containing corresponding values in JavaFX
public class myMap {
Map<Symbol, Price> map;
}
I want to display a table like the following
Symbol | Price
I guess it can be done by using TableView with CallBack.
Since I've already done something similar to this I'll add my code.
import java.util.Map;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;
public class MapTable extends Application {
#Override
public void start(Stage primaryStage) {
final ObservableMap<String, Number> obsMap = FXCollections.observableHashMap();
for (int i = 0; i < 3; i++) obsMap.put("key "+i, i*10d);
final TableView<ObservableMap.Entry<String, Number>> tv = new TableView(FXCollections.observableArrayList(obsMap.entrySet()));
tv.setEditable(true);
obsMap.addListener((MapChangeListener.Change<? extends String, ? extends Number> change) -> {
tv.setItems(FXCollections.observableArrayList(obsMap.entrySet()));
});
TableColumn<ObservableMap.Entry<String, Number>,String> keyCol = new TableColumn<>("key");
TableColumn<ObservableMap.Entry<String, Number>,Number> priceCol = new TableColumn<>("price");
tv.getColumns().addAll(keyCol,priceCol);
keyCol.setCellValueFactory((p) -> {
return new SimpleStringProperty(p.getValue().getKey());
});
keyCol.setCellFactory(TextFieldTableCell.forTableColumn());
keyCol.setOnEditCommit((TableColumn.CellEditEvent<Map.Entry<String,Number>, String> t) -> {
final String oldKey = t.getOldValue();
final Number oldPrice = obsMap.get(oldKey);
obsMap.remove(oldKey);
obsMap.put(t.getNewValue(),oldPrice);
});
priceCol.setCellValueFactory((p) -> {
return new ReadOnlyObjectWrapper<>(p.getValue().getValue());
});
priceCol.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
priceCol.setOnEditCommit((TableColumn.CellEditEvent<Map.Entry<String,Number>, Number> t) -> {
obsMap.put(t.getTableView().getItems().get(t.getTablePosition().getRow()).getKey(),//key
t.getNewValue());//val);
});
Button btn1 = new Button();
btn1.setText("Add data");
btn1.setOnAction((ActionEvent event) -> {
obsMap.put("hi",100);
});
Button btn2 = new Button();
btn2.setText("verify data");
btn2.setOnAction((ActionEvent event) -> {
for (Map.Entry<String,Number> me : obsMap.entrySet())
System.out.println("key "+me.getKey()+" val "+me.getValue());
});
VBox root = new VBox(tv,btn1,btn2);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Map Table test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Hope this can help.
public class Demo {
public static void main(String[] args) {
// Use Java Collections to create the List.
Map<String,String> map = new HashMap<String,String>();
// Now add observability by wrapping it with ObservableList.
ObservableMap<String,String> observableMap = FXCollections.observableMap(map);
observableMap.addListener(new MapChangeListener() {
#Override
public void onChanged(MapChangeListener.Change change) {
System.out.println("Detected a change! ");
}
});
// Changes to the observableMap WILL be reported.
observableMap.put("key 1","value 1");
System.out.println("Size: "+observableMap.size());
// Changes to the underlying map will NOT be reported.
map.put("key 2","value 2");
System.out.println("Size: "+observableMap.size());
}
}
http://docs.oracle.com/javafx/2/collections/jfxpub-collections.htm

Drag and Drop vbox element with show snapshot in javafx

I want drag an element in vbox as a parent and show node moving during drag and drop of element, how can do this with The slightest change.
Just register mouse listeners with the elements of the VBox. You want to call startFullDrag() on the node on a dragDetected event, and rotate the child nodes of the VBox on a dragReleased event. You can use the dragEntered and dragExited events if you want to give visual hints to the user about the drag.
See the API docs for more.
Simple example (code is way cleaner in JavaFX 8, btw):
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
final VBox root = new VBox(5);
final ScrollPane scroller = new ScrollPane();
scroller.setContent(root);
final Scene scene = new Scene(scroller,400,200);
for (int i=1; i<=20; i++) {
final Label label = new Label("Item "+i);
addWithDragging(root, label);
}
// in case user drops node in blank space in root:
root.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
#Override
public void handle(MouseDragEvent event) {
int indexOfDraggingNode = root.getChildren().indexOf(event.getGestureSource());
rotateNodes(root, indexOfDraggingNode, root.getChildren().size()-1);
}
});
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
private void addWithDragging(final VBox root, final Label label) {
label.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
label.startFullDrag();
}
});
// next two handlers just an idea how to show the drop target visually:
label.setOnMouseDragEntered(new EventHandler<MouseDragEvent>() {
#Override
public void handle(MouseDragEvent event) {
label.setStyle("-fx-background-color: #ffffa0;");
}
});
label.setOnMouseDragExited(new EventHandler<MouseDragEvent>() {
#Override
public void handle(MouseDragEvent event) {
label.setStyle("");
}
});
label.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
#Override
public void handle(MouseDragEvent event) {
label.setStyle("");
int indexOfDraggingNode = root.getChildren().indexOf(event.getGestureSource());
int indexOfDropTarget = root.getChildren().indexOf(label);
rotateNodes(root, indexOfDraggingNode, indexOfDropTarget);
event.consume();
}
});
root.getChildren().add(label);
}
private void rotateNodes(final VBox root, final int indexOfDraggingNode,
final int indexOfDropTarget) {
if (indexOfDraggingNode >= 0 && indexOfDropTarget >= 0) {
final Node node = root.getChildren().remove(indexOfDraggingNode);
root.getChildren().add(indexOfDropTarget, node);
}
}
public static void main(String[] args) {
launch(args);
}
}
This is an addendum to #James_D's excellent answer
This shows how to add an image preview to the draggable node as #James_D suggests in his comment:
private void addPreview(final VBox root, final Label label) {
ImageView imageView = new ImageView(label.snapshot(null, null));
imageView.setManaged(false);
imageView.setMouseTransparent(true);
root.getChildren().add(imageView);
root.setUserData(imageView);
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
imageView.relocate(event.getX(), event.getY());
}
});
}
private void removePreview(final VBox root) {
root.setOnMouseDragged(null);
root.getChildren().remove(root.getUserData());
root.setUserData(null);
}
Call addPreview() in label.setOnDragDetected(). Call removePreview() in label.setOnMouseDragReleased() and root.setOnMouseDragReleased().
There is a much better solution that is far cleaner now.
// Root is the node you want to drag, not the scene root.
root.setOnDragDetected(mouseEvent -> {
final ImageView preview = new ImageView(root.snapshot(null, null));
final Dragboard db = root.startDragAndDrop(TransferMode.ANY);
db.setContent( // Set your content to something here.
);
db.setDragView(preview.getImage());
mouseEvent.consume();
});

How to register ClickHandler to a vector grahpic in gwt-graphics and get-plattform

I’m trying to use gwt-graphics in a gwt-plattform project.
When I try to register a ClickHandler of a circle I got an exception:
I can add a ClickHandler to the circle in the view, but how can a add in the presenter?
view:
import org.vaadin.gwtgraphics.client.DrawingArea;
import org.vaadin.gwtgraphics.client.shape.Circle;
import com.gwtplatform.mvp.client.ViewImpl;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.PushButton;
public class MainPageView extends ViewImpl implements MainPagePresenter.MyView {
private static String html = "<h1>Web Application Starter Project</h1>\n"
+ "<table align=\"center\">\n"
+ " <tr>\n"
+ " <td colspan=\"2\" style=\"font-weight:bold;\">Please enter your name:</td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <td id=\"nameFieldContainer\"></td>\n"
+ " <td id=\"sendButtonContainer\"></td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <td colspan=\"2\" style=\"color:red;\" id=\"errorLabelContainer\"></td>\n"
+ " </tr>\n" + "</table>\n";
private final HTMLPanel panel = new HTMLPanel(html);
private final Label errorLabel;
private final TextBox nameField;
private final Button sendButton;
private AbsolutePanel absolutePanel = new AbsolutePanel();
Image image_1;
Image image;
DrawingArea d;
Circle circle;
#Inject
public MainPageView() {
sendButton = new Button("Send");
nameField = new TextBox();
nameField.setText("GWT User");
errorLabel = new Label();
// We can add style names to widgets
sendButton.addStyleName("sendButton");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
panel.add(nameField, "nameFieldContainer");
panel.add(sendButton, "sendButtonContainer");
d = new DrawingArea(500, 500);
panel.add(absolutePanel);
absolutePanel.setHeight("500px");
// circle.addClickHandler(new ClickHandler() {
//
// #Override
// public void onClick(ClickEvent event) {
// Window.alert("image2");
//
// }
// });
image = new Image("ball1.png");
absolutePanel.add(image, 59, 10);
image.setSize("100px", "100px");
image_1 = new Image("Hexagon.svg");
absolutePanel.add(image_1, 115, 10);
image_1.setSize("100px", "100px");
absolutePanel.add(d, 100, 100);
//
Circle circle = new Circle(100, 100, 150);
circle.setStrokeColor("red");
d.add(circle);
panel.add(errorLabel, "errorLabelContainer");
}
#Override
public Widget asWidget() {
return panel;
}
#Override
public HasValue<String> getNameValue() {
return nameField;
}
#Override
public HasClickHandlers getSendClickHandlers() {
return sendButton;
}
#Override
public void resetAndFocus() {
// Focus the cursor on the name field when the app loads
nameField.setFocus(true);
nameField.selectAll();
}
#Override
public void setError(String errorText) {
errorLabel.setText(errorText);
}
// #Override
// public HasClickHandlers getImage1() {
// return image;
// }
//
// #Override
// public HasClickHandlers getImage2() {
// return image_1;
//
// }
#Override
public HasClickHandlers getCircle() {
return circle;
}
}
Presenter:
package mybla.client.core;
import org.vaadin.gwtgraphics.client.shape.Circle;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.View;
import com.gwtplatform.mvp.client.annotations.ProxyStandard;
import com.gwtplatform.mvp.client.annotations.NameToken;
import mybla.client.place.NameTokens;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.google.inject.Inject;
import com.google.gwt.event.shared.EventBus;
import com.gwtplatform.mvp.client.proxy.RevealRootContentEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasValue;
import com.gwtplatform.mvp.client.proxy.PlaceManager;
import com.gwtplatform.mvp.client.proxy.PlaceRequest;
import mybla.shared.FieldVerifier;
public class MainPagePresenter extends
Presenter<MainPagePresenter.MyView, MainPagePresenter.MyProxy> {
public interface MyView extends View {
HasValue<String> getNameValue();
HasClickHandlers getSendClickHandlers();
void resetAndFocus();
void setError(String errorText);
HasClickHandlers getCircle();
// HasClickHandlers getImage2();
//
// HasClickHandlers getImage1();
}
#ProxyStandard
#NameToken(NameTokens.main)
public interface MyProxy extends ProxyPlace<MainPagePresenter> {
}
private final PlaceManager placeManager;
#Inject
public MainPagePresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, final PlaceManager placeManager) {
super(eventBus, view, proxy);
this.placeManager = placeManager;
}
#Override
protected void revealInParent() {
RevealRootContentEvent.fire(this, this);
}
#Override
protected void onBind() {
super.onBind();
registerHandler(getView().getSendClickHandlers().addClickHandler(
new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
sendNameToServer();
}
}));
// registerHandler(getView().getImage1().addClickHandler(new ClickHandler() {
//
// #Override
// public void onClick(ClickEvent event) {
// Window.alert("image1");
//
// }
// }));
registerHandler(getView().getCircle().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("image2");
}
}));
}
#Override
protected void onReset() {
super.onReset();
getView().resetAndFocus();
}
/**
* Send the name from the nameField to the server and wait for a response.
*/
private void sendNameToServer() {
// First, we validate the input.
getView().setError("");
String textToServer = getView().getNameValue().getValue();
if (!FieldVerifier.isValidName(textToServer)) {
getView().setError("Please enter at least four characters");
return;
}
// Then, we transmit it to the ResponsePresenter, which will do the server call
placeManager.revealPlace(new PlaceRequest(NameTokens.response).with(
ResponsePresenter.textToServerParam, textToServer));
}
}
In your presenter:
getView().getCircle().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event)
{
Window.alert("image2");
}
});
This will use the getter method set in the presenter.view, to access the circle in the View itself.
Looks like the circle you instantiate in your View's constructor is a local variable, not the class-scope variable your getCircle() method returns. Additionally, the commented out code for adding the onclick handler is before the code that instantiates the local variable.
You have:
...
// circle.addClickHandler(new ClickHandler() {
//
// #Override
// public void onClick(ClickEvent event) {
// Window.alert("image2");
// }
// });
...
Circle circle = new Circle(100, 100, 150);
circle.setStrokeColor("red");
d.add(circle);
Change it to:
...
circle = new Circle(100, 100, 150); // This now references the class-scope variable, rather than creating a new local variable.
circle.setStrokeColor("red");
d.add(circle);
circle.addClickHandler(new ClickHandler() { // This will no longer throw a null-pointer exception.
#Override
public void onClick(ClickEvent event) {
Window.alert("image2");
}
});