The objective is to use drag and drop on a treeView to move the nodes on itself.I have seen several examples where the events are handled in a redefined TreeCell, but only the detected event is triggered.
This is my code:
public class TreeCellImpl extends TreeCell<TreeItemContent> {
public TreeCellImpl() {
setOnDragEntered(e -> {
System.out.println(" Entered ");
e.consume();
});
setOnDragDetected(e -> {
System.out.println(" Detected ");
startDragAndDrop(TransferMode.MOVE);
e.consume();
});
setOnDragDone(e -> {
System.out.println(" Done ");
e.consume();
});
setOnDragDropped(e -> {
System.out.println(" Dropped ");
e.setDropCompleted(true);
e.consume();
});
setOnDragExited(e -> {
System.out.println(" Exited ");
e.consume();
});
setOnDragOver(e -> {
System.out.println(" Over ");
e.consume();
});
}
}
Where i wrong ?
It seems the event handlers are not triggered until you put some content to Dragboard:
setOnDragDetected(e -> {
System.out.println(" Detected ");
Dragboard db = startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString( "Hello!" );
db.setContent(content);
e.consume();
});
You may also choose to use the other type of drag-n-drop mechanism described in MouseEvent. I.e. MouseDragEvent.
Related
In ComboBoxViewerCellEditor I want to write something and as a result I will get the matching dropdown value.
Can you suggest how to get this? Please find the code below:
public TCOperationColumnEditable(TableViewer viewer) {
super(viewer);
try
{
this.viewer = viewer;
//this.editor = new TextCellEditor(this.viewer.getTable());
OperationGSON[] allOperations = OperationAPIHandler.getInstance().getAllOperations();
ArrayList<String> opnName = new ArrayList<String>();
for(OperationGSON opn : allOperations)
{
opnName.add(opn.opnName);
}
this.editor = new ComboBoxViewerCellEditor(this.viewer.getTable(), SWT.FULL_SELECTION );
this.editor.setLabelProvider(new LabelProvider());
this.editor.setContentProvider(new ArrayContentProvide());
this.editor.setInput(opnName);
String[] stockArr = new String[opnName.size()];
stockArr = opnName.toArray(stockArr);
new AutoCompleteField(this.viewer.getControl(), new CComboContentAdapter(), stockArr);
}
catch(Exception e)
{
System.out.println("[" + getClass().getName() + " : TCOperationColumnEditable()] - Exception : " + e.getMessage());
e.printStackTrace();
}
}
enter image description here
Subclass TextCellEditor.
For a content proposal, use field assist API of JFace
(org.eclipse.jface.fieldassist). Content assist is enabled
when the cell editor is activated for the first time:
if (contentProposalAdapter == null) {
....
// enable content assist on the cell editor's text widget
contentProposalAdapter = new ContentProposalAdapter(text, new TextContentAdapter(), proposalProvider, activationKeyStroke, null);
} else {
contentProposalAdapter.setEnabled(true);
}
super.activate();
....
Make sure to also override method
TextCellEditor#dependsOnExternalFocusListener() to return false always.
Otherwise, you'll face some serious problems concerning focus.
I try to get the values of the ZK Tree from this example. But i not get the all childrens value...what i tried:
List<Treechildren> treeChildren = new ArrayList<>();
List<Label> labelList = new ArrayList<>();
List<Label> childs = new ArrayList<>();
tree.getChildren().forEach(component -> {
if(component instanceof Treechildren){
treeChildren.add((Treechildren) component);
}
});
List<Treeitem> treeItems = new ArrayList<>();
treeChildren.forEach(treechildren ->{
treeItems.addAll(treechildren.getChildren());
});
List<Treechildren> children = new ArrayList<>();
treeItems.forEach(treeitem -> {
System.err.println("treeitem: " + treeitem);
if (treeitem.getChildren().size() > 1) {
treeitem.getChildren().forEach(child -> {
if(child instanceof Treechildren){
children.add((Treechildren) child);
} else {
List<Treecell> tcList = new ArrayList<>();
child.getChildren().forEach(component -> {
if(component instanceof Treecell) {
tcList.add((Treecell) component);
}
});
List<Hlayout> hlList = new ArrayList<>();
tcList.forEach(treecell ->{
System.err.println("treecell" + treecell);
hlList.addAll(treecell.getChildren());
});
hlList.forEach(hlayout -> {
childs.addAll(hlayout.getChildren());
});
}
});
}else {
List<Treerow> tr = new ArrayList<>();
treeitem.getChildren().forEach(component -> {
if (component instanceof Treerow) {
tr.add((Treerow) component);
} else {
}
});
List<Treecell> TC = new ArrayList<>();
tr.forEach(treerow -> {
TC.addAll(treerow.getChildren());
});
List<Hlayout> HL = new ArrayList<>();
TC.forEach(treecell -> {
HL.addAll(treecell.getChildren());
});
HL.forEach(hlayout -> labelList.addAll(hlayout.getChildren()));
}
});
labelList.forEach(label -> System.err.println("label: " + label.getValue()));
childs.forEach(label -> System.err.println("childs: " + label.getValue()));
}
But i not get the whole tree labels....the aim is to save the tree to database when i push the submit button.
Since you did not post your tree, I can only guess how it looks. But I tried to at least understand your code and found a potential bug: In line 21 handle the case where tree nodes have sub nodes. You add the Treechildren to children, but never do anything with it. So you loop will stop at the first level.
First of all, I would recommend using the special methods for trees and their components:
Tree: getTreechildren()
Treeitem: getTree(), getTreerow() and getTreechildren()
Treerow: getTree() and getLinkedTreechildren()
These help you to get rid of all the casting and instanceof checks. Furthermore, you can specify the type of children when calling getChildren():
List<Treecell> cells = row.<Treecell> getChildren()
Now you don't have to cast, but to be careful that all children are of the same type.
Finally, I refactored your code to understand it:
// Find all items in the tree, level by level
List<Treeitem> items = new ArrayList<>(tree.getTreechildren().getChildren());
List<Treeitem> itemsTemp = new ArrayList<>(tree.getTreechildren().getChildren());
while (!itemsTemp.isEmpty())
{
Treeitem nextChild = itemsTemp.remove(0);
if (nextChild.getTreechildren() != null)
{
items.addAll(nextChild.getTreechildren().getChildren());
itemsTemp.addAll(nextChild.getTreechildren().getChildren());
}
}
// convert item -> row -> cells -> hlayouts -> children
List<Component> children = items.stream()
.map(Treeitem::getTreerow)
.filter(Objects::nonNull)
.flatMap(row -> row.<Treecell> getChildren().stream())
.flatMap(cell -> cell.<Hlayout> getChildren().stream())
.flatMap(hlayout -> hlayout.getChildren().stream())
.collect(Collectors.toList());
// // without streams
// List<Component> children = new ArrayList<>();
// for (Treeitem item : items)
// {
// if (item.getTreerow() != null)
// {
// for (Treecell cell : item.getTreerow().<Treecell> getChildren())
// {
// for (Hlayout hlayout : cell.<Hlayout> getChildren())
// {
// children.addAll(hlayout.getChildren());
// }
// }
// }
// }
You can see that in the while loop, I looked at the tree's children on the first level, then at their children, that at those children's children, and so on. Then I used the methods mentioned above to find the components of each tree node.
Again, I do not know how your tree looks, so I do not know whether this works for you. Maybe you could post a small example.
In my application, the first I do is request the user to login using the controlsFX LoginDialog. If the login is successful, I display the application, however if it fails the login window will close.
I would rather the login window stay open to allow the user to attempt to login again.
public void start(Stage stage) throws Exception {
LoginDialog ld = new LoginDialog(new Pair<String, String>("", ""), new Callback<Pair<String,String>, Void>() {
#Override
public Void call(Pair<String, String> info) {
boolean success = login(info.getKey(), info.getValue());
if(success){
openDriverWindow(stage);
}else {
//Display error message
}
return null;
}
});
ld.show();
}
If the login is unsuccessful, the dialog closes - which requires the user to reopen the application.
You can use Dialog from JDK8u40 which will be released at march 2015 or use dialogs from ConrolsFX (openjfx-dialogs-1.0.2). There is a code to implement Dialog which will not be closed until authentication is not passed.
// Create the custom dialog.
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle("Login Dialog");
dialog.setHeaderText("Look, a Custom Login Dialog");
dialog.setGraphic(new ImageView(this.getClass().getResource("login.png").toString()));
// Set the button types.
ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
// Create the username and password labels and fields.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
TextField username = new TextField();
username.setPromptText("Username");
PasswordField password = new PasswordField();
password.setPromptText("Password");
grid.add(new Label("Username:"), 0, 0);
grid.add(username, 1, 0);
grid.add(new Label("Password:"), 0, 1);
grid.add(password, 1, 1);
// Enable/Disable login button depending on whether a username was entered.
Button loginButton = (Button)dialog.getDialogPane().lookupButton(loginButtonType);
loginButton.setDisable(true);
**// Prevent closing dialog if not authenticated**
loginButton.addEventFilter(ActionEvent.ACTION, (event) -> {
if (!authenticated()) {
event.consume();
}
});
// Do some validation (using the Java 8 lambda syntax).
username.textProperty().addListener((observable, oldValue, newValue) -> {
loginButton.setDisable(newValue.trim().isEmpty());
});
dialog.getDialogPane().setContent(grid);
// Request focus on the username field by default.
Platform.runLater(() -> username.requestFocus());
// Convert the result to a username-password-pair when the login button is clicked.
dialog.setResultConverter(dialogButton -> {
if (dialogButton == loginButtonType) {
return new Pair<>(username.getText(), password.getText());
}
return null;
});
Optional<Pair<String, String>> result = dialog.showAndWait();
result.ifPresent(usernamePassword -> {
System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
});
this example was given from this article where you can find many useful examples
Try this:
public class Main extends Application{
private boolean login(String key, String value){
Pair loginData = new Pair<String, String>("test", "test");
if (loginData.getKey().equals(key) && loginData.getValue().equals(value)) {
return true;
}
else {
//Вывести Alert.
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
Alert alert = new Alert(Alert.AlertType.ERROR, "Вы ввели неправильное имя или пароль");
alert.setTitle("Error");
alert.showAndWait();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return false;
}
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Terminal Kuban-electro");
getLogin(primaryStage);
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent t) {
System.exit(0);
}
});
}
private void getLogin(Stage primaryStage){
LoginDialog ld = new LoginDialog(new Pair<String, String>("", ""), new Callback<Pair<String, String>, Void>() {
#Override
public Void call(Pair<String, String> info) {
boolean success = login(info.getKey(), info.getValue());
if (success) {
Scene scene = null;
try {
scene = new Scene(FXMLLoader.load(getClass().getClassLoader().getResource("fxml/main.fxml")));
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
}
} else {
getLogin(primaryStage);
}
return null;
}
});
ld.setHeaderText("Введите имя пользователя и пароль");
ld.setTitle("Авторизация");
ld.show();
}
public static void main(String[] args) throws MalformedURLException {
//Инициализация формы в потоке
Thread myThready = new Thread(() -> {
launch(args);
});
myThready.start();
}
}
I have a javafx TableView populated with a class called Song. I have a sidebar in my border pane populated with Buttons that represent a class called Playlist. my (currently basic) UI looks like this:
I want to make it so that if I drag a song and drop it in to one of the buttons on the left, it adds that song to the playlist. Also I have looked and searched around the internet for an answer and haven't found anything useful. That being said, please don't link me to something. I have already tried implementing the code from the following link: http://docs.oracle.com/javase/8/javafx/events-tutorial/drag-drop.htm#CHDJFJDH
If you have any suggestions please help me! thanks!
UPDATE:
Here's my code, my naming conventions are pretty easily understandable:
musicTable.setOnMouseClicked(new EventHandler<MouseEvent>() { //click
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() == 2) { // double click
Song selected = (Song)musicTable.getSelectionModel().getSelectedItem();
dragged = selected;
if (selected != null) {
System.out.println("select : " + selected);
}
}
}
});
musicTable.setOnDragDetected(new EventHandler<MouseEvent>() { //drag
#Override
public void handle(MouseEvent event) {
// drag was detected, start drag-and-drop gesture
Song selected = (Song)musicTable.getSelectionModel().getSelectedItem();
dragged = selected;
if (selected != null) {
Dragboard db = musicTable.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(selected.pointer.toString());
db.setContent(content);
event.consume();
}
}
});
musicTable.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
// data is dragged over the target
Dragboard db = event.getDragboard();
if (event.getDragboard().hasString()) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
}
});
musicTable.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (event.getDragboard().hasString()) {
String text = db.getString();
//tableContent.add(text);
//musicTable.setItems(tableContent);
success = true;
}
event.setDropCompleted(success);
event.consume();
}
});
playlistTable.setRowFactory(cb -> {
TableRow<Playlist> row = new TableRow<>();
row.setOnMouseClicked(ev -> {
musicTable.setItems(row.getItem().playlist);
row.setOnDragDropped( new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
boolean success = false;
row.getItem().add(dragged);
System.out.println("ACCEPED TRANSFER");
success = true;
event.setDropCompleted(success);
event.consume();
}
});
});
return row;
});
dragged is a song that keeps track of which song is being dragged, if you have any other way of doing that please tell me, musicTable is what I'm dragging from, playlist table is where I'm dragging to.
Ok, this is the smallest example I could create:
#Override
public void start(Stage primaryStage) throws IOException {
ObservableList<String> tableData = FXCollections
.observableList(IntStream.range(0, 1000)
.mapToObj(Integer::toString)
.collect(Collectors.toList()));
TableView<String> stringTable = new TableView<>(tableData);
TableColumn<String, String> column1 = new TableColumn<>();
column1.setCellValueFactory(cb -> new ReadOnlyStringWrapper(cb
.getValue()));
stringTable.getColumns().add(column1);
stringTable.setRowFactory(cb -> {
TableRow<String> row = new TableRow<>();
row.setOnDragDetected(ev -> {
Dragboard db = row.startDragAndDrop(TransferMode.COPY);
ClipboardContent content = new ClipboardContent();
content.putString(row.getItem());
db.setContent(content);
ev.consume();
});
return row;
});
VBox leftSide = new VBox();
leftSide.setPrefWidth(300);
leftSide.setOnDragOver(ev -> {
if (ev.getGestureSource() != leftSide && ev.getDragboard().hasString()) {
ev.acceptTransferModes(TransferMode.COPY);
}
ev.consume();
});
leftSide.setOnDragDropped(ev -> {
Dragboard db = ev.getDragboard();
boolean success = false;
if (db.hasString()) {
Label label = new Label(db.getString());
leftSide.getChildren().add(label);
success = true;
}
ev.setDropCompleted(success);
ev.consume();
});
BorderPane root = new BorderPane(stringTable);
root.setLeft(leftSide);
Scene scene = new Scene(root, 700, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
This is a BorderPane where the center is a TableView and the left side is a VBox.
Now I added your requested Drag and Drop handlers so you can drag rows (thus this is done in the row factory) to the left side, where they are added as new Labels to the VBox as new children.
Edit: Second example with ListView as drop target:
#Override
public void start(Stage primaryStage) {
ObservableList<String> tableData = FXCollections
.observableList(IntStream.range(0, 1000)
.mapToObj(Integer::toString)
.collect(Collectors.toList()));
TableView<String> stringTable = new TableView<>(tableData);
TableColumn<String, String> column1 = new TableColumn<>();
column1.setCellValueFactory(cb -> new ReadOnlyStringWrapper(cb
.getValue()));
stringTable.getColumns().add(column1);
stringTable.setRowFactory(cb -> {
TableRow<String> row = new TableRow<>();
row.setOnDragDetected(ev -> {
Dragboard db = row.startDragAndDrop(TransferMode.COPY);
ClipboardContent content = new ClipboardContent();
content.putString(row.getItem());
db.setContent(content);
ev.consume();
});
return row;
});
ObservableList<String> leftSideItems = FXCollections
.observableList(IntStream.range(0, 1000)
.mapToObj(Integer::toString)
.collect(Collectors.toList()));
ListView<String> leftSideDropTarget = new ListView<String>(
leftSideItems);
leftSideDropTarget.setPrefWidth(200);
leftSideDropTarget.setCellFactory(cb -> {
ListCell<String> cell = new TextFieldListCell<>();
cell.setOnDragOver(ev -> {
if (ev.getGestureSource() != cell
&& ev.getDragboard().hasString()) {
ev.acceptTransferModes(TransferMode.COPY);
}
ev.consume();
});
cell.setOnDragDropped(ev -> {
Dragboard db = ev.getDragboard();
boolean success = false;
if (db.hasString()) {
cell.setText("Got Item: " + db.getString());
success = true;
}
ev.setDropCompleted(success);
ev.consume();
});
return cell;
});
BorderPane root = new BorderPane(stringTable);
root.setLeft(leftSideDropTarget);
Scene scene = new Scene(root, 700, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
I am creating a webpage having CellTable.I need to feed this table with data from hbase table.
I have written a method to retrieve data from hbase table and tested it.
But when I call that method as GWT asynchronous RPC method then rpc call succeeds but it returns nothing.In my case it returns empty list.The alert box show list's size as 0.
Following is the related code.
Please help.
greetingService.getDeviceIDData(new AsyncCallback<List<DeviceDriverBean>>(){
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
System.out.println("RPC Call failed");
Window.alert("Data : RPC call failed");
}
public void onSuccess(List<DeviceDriverBean> result) {
//on success do something
Window.alert("Data : RPC call successful");
//deviceDataList.addAll(result);
Window.alert("Result size: " +result.size());
// Add a text column to show the driver name.
TextColumn<DeviceDriverBean> nameColumn = new TextColumn<DeviceDriverBean>() {
#Override
public String getValue(DeviceDriverBean object) {
Window.alert(object.getName());
return object.getName();
}
};
table.addColumn(nameColumn, "Name");
// Add a text column to show the device id
TextColumn<DeviceDriverBean> deviceidColumn = new TextColumn<DeviceDriverBean>() {
#Override
public String getValue(DeviceDriverBean object) {
return object.getDeviceId();
}
};
table.addColumn(deviceidColumn, "Device ID");
table.setRowCount(result.size(), true);
// more code here to add columns in celltable
// Push the data into the widget.
table.setRowData(0, result);
SimplePager pager = new SimplePager();
pager.setDisplay(table);
VerticalPanel vp = new VerticalPanel();
vp.add(table);
vp.add(pager);
// Add it to the root panel.
RootPanel.get("datagridContainer").add(vp);
}
});
Code to retrieve data from hbase (server side code)
public List<DeviceDriverBean> getDeviceIDData()
throws IllegalArgumentException {
List<DeviceDriverBean> deviceidList = new ArrayList<DeviceDriverBean>();
// Escape data from the client to avoid cross-site script
// vulnerabilities.
/*
* input = escapeHtml(input); userAgent = escapeHtml(userAgent);
*
* return "Hello, " + input + "!<br><br>I am running " + serverInfo +
* ".<br><br>It looks like you are using:<br>" + userAgent;
*/
try {
Configuration config = HbaseConnectionSingleton.getInstance()
.HbaseConnect();
HTable testTable = new HTable(config, "driver_details");
byte[] family = Bytes.toBytes("details");
Scan scan = new Scan();
int cnt = 0;
ResultScanner rs = testTable.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
DeviceDriverBean deviceDriverBean = new DeviceDriverBean();
byte[] rowid = r.getRow(); // Category, Date, Sentiment
NavigableMap<byte[], byte[]> map = r.getFamilyMap(family);
Iterator<Entry<byte[], byte[]>> itrt = map.entrySet()
.iterator();
deviceDriverBean.setDeviceId(Bytes.toString(rowid));
while (itrt.hasNext()) {
Entry<byte[], byte[]> entry = itrt.next();
//cnt++;
//System.out.println("Count : " + cnt);
byte[] qual = entry.getKey();
byte[] val = entry.getValue();
if (Bytes.toString(qual).equalsIgnoreCase("account_number")) {
deviceDriverBean.setAccountNo(Bytes.toString(val));
} else if (Bytes.toString(qual).equalsIgnoreCase("make")) {
deviceDriverBean.setMake(Bytes.toString(val));
} else if (Bytes.toString(qual).equalsIgnoreCase("model")) {
deviceDriverBean.setModel(Bytes.toString(val));
} else if (Bytes.toString(qual).equalsIgnoreCase("driver_name")) {
deviceDriverBean.setName(Bytes.toString(val));
} else if (Bytes.toString(qual).equalsIgnoreCase("premium")) {
deviceDriverBean.setPremium(Bytes.toString(val));
} else if (Bytes.toString(qual).equalsIgnoreCase("year")) {
deviceDriverBean.setYear(Bytes.toString(val));
} else {
System.out.println("No match found");
}
/*
* System.out.println(Bytes.toString(rowid) + " " +
* Bytes.toString(qual) + " " + Bytes.toString(val));
*/
}
deviceidList.add(deviceDriverBean);
}
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e) {
// System.out.println("Message: "+e.getMessage());
e.printStackTrace();
}
return deviceidList;
}
Could this be lazy fetching on the server side by hbase. This means if you return the list hbase won't get a trigger to actually read the list and you will simple get an empty list. I don't know a correct solution, in the past I've seen a similar problem on GAE. This could by solved by simply asking the size of the list just before returning it to the client.
I don't have the exact answer, but I have an advise. In similar situation I put my own trace to check every step in my program.
On the server side before return put : System.out.println("size of table="+deviceidList.size());
You can put this trace in the loop for deviceidList;