i have a problem with my searching method.
With this method, I can enter a word in the textfield and display the word in the textarea. However, this only happens once if i let it run. I need to expand it so, that every time I click on "enter," the program should continue with searching in the textarea. How can i do this?
And please give me code examples. i have only 2 days left for my presentation.
Thanks a lot for the helps
textfield.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.ENTER) {
String text = textarea.getText();
Labeled errorText = null;
if (textfield.getText() != null && !textfield.getText().isEmpty()) {
index = textarea.getText().indexOf(textfield.getText());
textarea.getText();
if (index == -1) {
errorText.setText("Search key Not in the text");
} else {
// errorText.setText("Found");
textarea.selectRange(index, index + textfield.getLength());
}
}
}
}
});
There's an overloaded version of the indexOf method allowing you to search starting at a specific index. Keep track of the index of your last find and start searching from this position:
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField("foo");
TextArea textarea = new TextArea();
for (int i = 0; i < 10; i++) {
textarea.appendText("foo\nbarfoobarfoofoo\n");
}
textField.setOnAction(evt -> {
String searchText = textField.getText();
if (searchText.isEmpty()) {
return; // searching for empty text doesn't make sense
}
int index = textarea.getSelection().getEnd();
// in case of the first search, start at the beginning
// TODO: adjust condition/starting index according to needs
if (textarea.getSelection().getLength() == 0) {
index = 0;
}
// find next occurrence
int newStartIndex = textarea.getText().indexOf(searchText, index);
// mark occurrence
if (newStartIndex >= 0) {
textarea.selectRange(newStartIndex, newStartIndex + searchText.length());
}
});
Scene scene = new Scene(new VBox(textField, textarea));
primaryStage.setScene(scene);
primaryStage.show();
}
Edit
If you are not satisfied with searching the element after the selection ( or after the cursor, if there is no range selected), you could save the data of the end of the last match:
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField("foo");
TextArea textarea = new TextArea();
for (int i = 0; i < 10; i++) {
textarea.appendText("foo\nbarfoobarfoofoo\n");
}
class SearchHandler implements EventHandler<ActionEvent> {
int index = 0;
#Override
public void handle(ActionEvent event) {
String searchText = textField.getText();
String fullText = textarea.getText();
if (index + searchText.length() > fullText.length()) {
// no more matches possible
// TODO: notify user
return;
}
// find next occurrence
int newStartIndex = textarea.getText().indexOf(searchText, index);
// mark occurrence
if (newStartIndex >= 0) {
index = newStartIndex + searchText.length();
textarea.selectRange(newStartIndex, index);
} else {
index = fullText.length();
// TODO: notify user
}
}
}
SearchHandler handler = new SearchHandler();
textField.setOnAction(handler);
// reset index to search from start when changing the text of the TextField
textField.textProperty().addListener((o, oldValue, newValue) -> handler.index = 0);
Scene scene = new Scene(new VBox(textField, textarea));
primaryStage.setScene(scene);
primaryStage.show();
}
Related
Hi I need to limit the input of TextField javaFX not only for integer but also for numbers between 1 - 19 only.For example I should be allowed to type : "3" ,"19" ... but not: "33" , 44 ..
for example : What is the recommended way to make a numeric TextField in JavaFX? but this limits the text field just for integers.
You can use regex to allow your specific numbers' range(1-19) and add that validation on TextField's TextFormatter's filter.
Regex => ([1-9]|1[0-9])
[1-9] Either TextField allows you to enter 1 to 9 numbers
1[0-9] Or TextField allows you to enter 10 to 19 numbers
Regex Circut
TextField Validation Demo
public class TextFieldValidationDemo extends Application {
private static final String REGEX_VALID_INTEGER = "([1-9]|1[0-9])";
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
root.setCenter(getRootPane());
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
private BorderPane getRootPane() {
BorderPane root = new BorderPane();
root.setCenter(getTextField());
return root;
}
private TextField getTextField() {
TextField field = new TextField();
field.setTextFormatter(new TextFormatter<>(this::filter));
return field;
}
private TextFormatter.Change filter(TextFormatter.Change change) {
if (!change.getControlNewText().matches(REGEX_VALID_INTEGER)) {
change.setText("");
}
return change;
}
}
I have now revised my code. This code allows you to enter "13" as well as only 13. It also checks if the input is in the range.
Demo App
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
GridPane gridPane = new GridPane();
Scene scene = new Scene(gridPane);
gridPane.add(textField, 0, 0);
final int MIN = 1;
final int MAX = 19;
UnaryOperator<TextFormatter.Change> filter = change -> {
//if something got added
if (change.isAdded()) {
//if change is " add "" in texfield
if (change.getText().equals("\"")) {
if (!change.getControlText().contains("\"")) {
change.setText("\"\"");
return change;
} else {
//if textfield already contains ""
return null;
}
} else {
//If Input is not a number don't change anything
if (change.getText().matches("[^0-9]")) {
return null;
}
//If change don't contains " check if change is in range
if (!change.getControlText().contains("\"")) {
if (Integer.parseInt(change.getControlNewText()) < MIN || Integer.parseInt(change.getControlNewText()) > MAX) {
return null;
}
} else {
//if change contains "" remove "" and check if is in range
String s = change.getControlNewText();
s = s.replaceAll("[\"]", "");
int value = Integer.parseInt(s);
if (value < MIN || value > MAX) {
return null;
}
}
}
}
return change;
};
textField.setTextFormatter(new TextFormatter<>(filter));
primaryStage.setScene(scene);
primaryStage.show();
}
I am populating a comboBox with items taken from a sql database when initializing the thread.
If anyone's interested:
public void initialize(URL arg0, ResourceBundle arg1) {
if(arr != null || arr.length > 0) {
for(int i = 0; i<arr.length; i++) {
cmBox.getItems().add(arr[i]);
}
}
}
I have a part of my code that adds a new value to the sql table, and I want to re-populate the comboBox when that happens.
if I do:
cmBox.getItems().clear();
arr = sqld.selectAll();
if(arr != null || arr.length > 0) {
for(int i = 0; i<arr.length; i++) {
cmBox.getItems().add(arr[i]);
}
}
It works fine, but I can't see the new changes unless I close and re-open the window that displays the comboBox.
No errors or anything, just looking for creative ways of re-loading a comboBox and have it actually show the updated values without manually closing and re-opening the window.
You don't need a refresh button just run comboBox.setItems(...) when you add "a new value to the sql table" this should update the combo box here is an example
public class Main extends Application {
private int[] data;
private int dataCount = 0;
#Override
public void start(Stage primaryStage) throws Exception{
data = randomizeData(dataCount);
ComboBox comboBox = new ComboBox();
comboBox.setItems(FXCollections.observableArrayList(
Arrays.stream(data).boxed().collect(Collectors.toList())));
Button updateDataButton = new Button("Update values in SQL Table");
updateDataButton.setOnAction(event -> {
//Update your SQL data
updateData();
//Refresh List
comboBox.setItems(FXCollections.observableArrayList(
Arrays.stream(data).boxed().collect(Collectors.toList())));
});
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
vBox.getChildren().addAll(comboBox, updateDataButton);
Scene scene = new Scene(vBox);
primaryStage.setScene(scene);
primaryStage.show();
}
private int[] randomizeData(int additional){
int[] data = new int[5+additional];
for (int i = 0; i < data.length; i++) {
data[i] = (int) (Math.random()*10);
}
return data;
}
private void updateData(){
data = randomizeData(++dataCount);
}
public static void main(String[] args) { launch(args); }
}
How do I sort through an array of buttons to see if only one is left enabled? I am creating a Sudoku solver and need to check if there is only one button left unselected in each row, column, or box and if it is to highlight the last remaining option. I can't find a command that will allow me to check each individual cell in the row to see if ONLY one is left. This is what I have so far
public class SudoHelper extends Application
{
public boolean [][][] DisabledCell = new boolean[3][9][9]; // Creates our array
Scene scene;
Pane pane;
Pane main;
BookMark bane;
#Override
public void start (Stage primaryStage)
{
for(int a = 0;a<3;a++)
{
for(int b=0;b<9;b++)
{
for(int c=0; c<9;c++)
{
DisabledCell[a][b][c]=false;
}
}
}
mouseClicks = new MouseEvent[0];
SmartCell[] currentGame = new SmartCell[81];
pane = new Pane();
pane.setPrefSize(684, 702);
int x,y;
x=y=0;
main = new Pane();
for(int i=0; i<81; i++)
{
currentGame[i]= new SmartCell(i);
currentGame[i].setLayoutX(x);
currentGame[i].setLayoutY(y);
pane.getChildren().add(currentGame[i]);
x+=76; // Sets the layout for out array of SmartCells
if(x==684) // and puts our additional buttons on the screen
{ // With our scene and stage
x=0;
y+=78;
}
}
main.setPrefSize(1100, 702);
main.getChildren().add(pane);
bane= new BookMark();
scene = new Scene(main);
main.getChildren().add(bane);
bane.setPrefSize(416, 702);
bane.setLayoutX(685);
bane.setLayoutY(0);
primaryStage.setScene(scene);
primaryStage.setTitle("Sudoku Helper");
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args); // Starts the game
}
class BookMark extends Pane
{
class List
{
String[] MyList=new String[0];
public void Add(String Add)
{
if(this.MyList.length>0)
{
String[] Resize = new String[this.MyList.length+1];
for(int i=0;i<this.MyList.length;i++)
{
Resize[i]=this.MyList[i];
}
Resize[this.MyList.length+1]=Add;
}
else
{
this.MyList = new String[1];
this.MyList[0]=Add;
}
}
public void Clear()
{
this.MyList = new String[0];
}
}
Button lkm = new Button("Load Bookmark"); // Creates our load bookmark button
Button bkm = new Button("Save Bookmark"); // Creates out save bookmark button'
final ToggleGroup group1 = new ToggleGroup();
final ToggleGroup group2 = new ToggleGroup();
RadioButton rl1a = new RadioButton("Rule One All"); // Creates rule one radiobutton
RadioButton rl1s = new RadioButton("Rule One Click"); // Creates Rule one click radiobutton
RadioButton rl2s = new RadioButton("Rule Two Click"); // Creates rule two click radiobutton
RadioButton rl2a = new RadioButton("Rule Two All"); // Create rule two radiobutton
void ruleTwo()
{
}
void ruleOne()
{
int _x,_y;
int B=10;
String[]Getloc = name.split("~");
int loc = Integer.parseInt(Getloc[1]);
_y = loc%9;
if(loc<8) // checking which row we are looking at
{
_x=0;
for(_x=0; loc<8;)
{
if()
{
}
}
}
else if(loc<18)
{
_x=1;
}
else if(loc<27)
{
_x=2;
}
else if(loc<36)
{
_x=3;
}
else if(loc<45)
{
_x=4;
}
else if(loc<54)
{
_x=5;
}
else if(loc<63)
{
_x=6;
}
else if(loc<72)
{
_x=7;
}
else
{
_x=8; // checks blocks were looking at
}
if(_y>=0&&_y<=2) // checks which block we are in
{
if(_x>=0&&_x<=2)
{
B=0;
}
else if(_x>=3&&_x<=5)
{
B=1;
}
else if(_x>=6&&_x<=8)
{
B=2;
}
}
else if(_y>=3&&_y<=5)
{
if(_x>=0&&_x<=2)
{
B=3;
}
else if(_x>=3&&_x<=5)
{
B=4;
}
else if(_x>=6&&_x<=8)
{
B=5;
}
}
else if(_y>=6&&_y<=8)
{
if(_x>=0&&_x<=2)
{
B=6;
}
else if(_x>=3&&_x<=5)
{
B=7;
}
else if(_x>=6&&_x<=8)
{
B=8;
}
}
}
BookMark() // Our buttons specifications (Location font ect)
{
this.bkm = new Button("Save Bookmark");
this.lkm = new Button("Load Bookmark");
this.bkm.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.bkm.setLayoutX(10);
this.bkm.setLayoutY(10);
this.lkm.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.lkm.setLayoutX(150);
this.lkm.setLayoutY(10);
this.rl1a.setLayoutX(10);
this.rl1a.setLayoutY(250);
this.rl2a.setLayoutX(10);
this.rl2a.setLayoutY(500);
this.rl2s.setLayoutX(250);
this.rl1s.setLayoutY(250);
this.rl1s.setLayoutX(250);
this.rl2s.setLayoutY(500);
this.rl1a.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.rl1s.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.rl2a.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.rl2s.setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
this.group1.getToggles().add(this.rl1a);
this.group1.getToggles().add(this.rl1s);
this.group2.getToggles().add(this.rl2a);
this.group2.getToggles().add(this.rl2s);
BookMark.this.getChildren().add(this.lkm);
BookMark.this.getChildren().add(this.bkm);
BookMark.this.getChildren().add(this.rl1a);
BookMark.this.getChildren().add(this.rl1s);
BookMark.this.getChildren().add(this.rl2a);
BookMark.this.getChildren().add(this.rl2s);
// bkm.setOnMouseClicked(e -> Save(e));
}
}
private MouseEvent[] mouseClicks;
class SmartCell extends StackPane
{
GridPane buttonPane;
Pane valPane;
Text textVal;
Button [] btn;
String name;
SmartCell(int nameint)
{
buttonPane = new GridPane();
btn = new Button[10];
for(int i = 1; i <= 9; i++)
{
btn[i] = new Button(i+""); // Turns i into a String
btn[i].setFont(Font.font("Ariel", FontWeight.BOLD, FontPosture.REGULAR, 12));
btn[i].setOnMouseClicked(e -> mouseHandler(e));
buttonPane.add(btn[i], (i-1)%3, (i-1)/3);
}
// When the user clicks one of the 9 buttons, we want to take the number of the button
// they clicked, and set the text on the text pane to that number, hide the 9 buttons,
// and show the text pane.
name = "SmartCell~"+String.valueOf(nameint);
textVal = new Text(25, 55, "");
textVal.setFont(Font.font("Arial", 48));
textVal.setTextAlignment(TextAlignment.CENTER);
valPane = new Pane();
valPane.setStyle("-fx-border-color:black; -fx-border-stroke-width:1");
valPane.getChildren().add(textVal);
getChildren().add(buttonPane); // Add the pane with the 9 buttons to the cell
getChildren().add(valPane); // Add the pane with the one piece of text to the cell
buttonPane.setVisible(true); // We start out showing the 9 buttons
valPane.setVisible(false); // ...NOT showing the pane with the single text
} // end constructor
void disqual(MouseEvent e)
{
MouseEvent[] ResizeMouse = new MouseEvent[SudoHelper.this.mouseClicks.length+1];
ResizeMouse[ResizeMouse.length-1]=e;
SudoHelper.this.mouseClicks = ResizeMouse;
int _x,_y;
int B=10;
String[]Getloc = name.split("~");
int loc = Integer.parseInt(Getloc[1]);
_y = loc%9;
if(loc<8) // checking which row we are looking at
{
_x=0;
}
else if(loc<18)
{
_x=1;
}
else if(loc<27)
{
_x=2;
}
else if(loc<36)
{
_x=3;
}
else if(loc<45)
{
_x=4;
}
else if(loc<54)
{
_x=5;
}
else if(loc<63)
{
_x=6;
}
else if(loc<72)
{
_x=7;
}
else
{
_x=8; // checks blocks were looking at
}
if(_y>=0&&_y<=2) // checks which block we are in
{
if(_x>=0&&_x<=2)
{
B=0;
}
else if(_x>=3&&_x<=5)
{
B=1;
}
else if(_x>=6&&_x<=8)
{
B=2;
}
}
else if(_y>=3&&_y<=5)
{
if(_x>=0&&_x<=2)
{
B=3;
}
else if(_x>=3&&_x<=5)
{
B=4;
}
else if(_x>=6&&_x<=8)
{
B=5;
}
}
else if(_y>=6&&_y<=8)
{
if(_x>=0&&_x<=2)
{
B=6;
}
else if(_x>=3&&_x<=5)
{
B=7;
}
else if(_x>=6&&_x<=8)
{
B=8;
}
};
int CellNum =Integer.parseInt(((Button)e.getSource()).getText());
if(DisabledCell[0][_x][CellNum-1]==true||DisabledCell[1][_y][CellNum-1]==true||DisabledCell[2][B][CellNum-1]==true)
{
disqualify(Integer.parseInt(((Button)e.getSource()).getText()));
return;
}
DisabledCell[0][_x][CellNum-1]=true;
DisabledCell[1][_y][CellNum-1]=true;
DisabledCell[2][B][CellNum-1]=true;
textVal.setText(((Button)e.getSource()).getText());
buttonPane.setVisible(false);
valPane.setVisible(true);
for(int i = 1; i <= 9; i++)disqualify(i); // Since we have locked in, all others are out of play
// in this cell
int c = 0;
int z = 0;
switch(B)
{ // Figures out which block our selected number is in.
case 0: z=0;
break; // ^
case 1: z=27;
break; // ^
case 2: z=54;
break; // ^
case 3: z=3;
break; // ^
case 4: z=30;
break; // ^
case 5: z=57;
break; // ^
case 6: z=6;
break; // ^
case 7: z=33;
break; // ^
case 8: z=60;
break; // ^
}
for(int w = 0; w<9; w++)
{
Object xob =SudoHelper.this.pane.getChildren().get((_x*9)+w);
SmartCell d =SmartCell.class.cast(xob); // Disqualifies x cells
d.disqualify(CellNum);
xob=d;
Object yob =SudoHelper.this.pane.getChildren().get(_y+(9*w));
SmartCell b =SmartCell.class.cast(yob); // Disqualifies Y Cells
b.disqualify(CellNum);
yob=b;
Object zob =SudoHelper.this.pane.getChildren().get(z+c);
SmartCell a =SmartCell.class.cast(zob);
a.disqualify(CellNum); // Disqualifies boxes
zob=a;
c++;
if(c==3)
{
z+=9;
c=0;
}
}
}
void mouseHandler(MouseEvent e)
{
// When any button gets clicked, we take the text from the button, put it on the Text
// shape, hide the pane with the 9 buttons, and show the text pane, making it look like
// the 9 buttons have "gone", and the new value that we have "locked in" has taken their place.
//
if(e.getSource() instanceof Button)
{
// If this was a right click, then just disable this button; If it was a left click then lock
// in the value this button represents.
if(e.getButton() == MouseButton.SECONDARY)
{
disqualify(Integer.parseInt(((Button)e.getSource()).getText()));
// disables button after clicked
return;
}
// System.out.print("A button was clicked"); // for debugging
disqual(e);
} // end if source was a button
} // end mouseHandler
void disqualify(int buttonNo)
{
// When we are called, we disable button #buttonNo in this cell
btn[buttonNo].setDisable(true);
btn[buttonNo].setStyle("-fx-base:black; -fx-text-fill:black; -fx-opacity:1.0"); // Sets color of cells and numbers after disabled.
}
public String toString()
{
// The toString representation of a cell is a string containing a list of
// the values "still in play" --- the remaining candidate values --- for the cell
//
// Start with an empty string. Visit all 9 buttons, and if a given button is
// not disabled (i.e still in play), then add its number (from the text on the
// button) to our string
//
String result = "";
for(int i = 1; i <= 9; i++)
if(!btn[i].isDisabled())
result += i;
return result;
}
}
private boolean[] InitalizeTile() // Initalizes our board of 81 cells
{
boolean[] newbool = new boolean[81];
for(int i=0; i<81; i++)
{
newbool[i] = false;
}
Random R = new Random();
for(int j=0; j<0; j++)
{
while(true)
{
int W = R.nextInt(81);
if(newbool[W]==false)
{
newbool[W]=true;
break;
}
}
}
return newbool;
}
}
All I really need to know is how to look at an array of buttons and see if only one is left enabled.
Arrays.stream(buttons).filter(button -> !button.isDisabled()).count() == 1
Sample application:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import java.util.Arrays;
public class DisabledButtonCount extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Button[] buttons = {
new Button("1"),
new Button("2"),
new Button("3")
};
buttons[1].setDisable(true);
buttons[2].setDisable(true);
System.out.println(
"Only one button enabled? " +
(Arrays.stream(buttons).filter(button -> !button.isDisabled()).count() == 1)
);
Platform.exit();
}
}
Table contains the following rows (one column just for example):
A
B
C
I'm trying to figure out how to drag an item into it, and have it placed between existing rows B and C.
I am able to do drag-and-drop that results in an item added at the end of table but I can't figure out how to place it in between rows, based on where I release the mouse button.
Create a rowFactory producing TableRows that accept the gesture and decide by the mouse position, whether to add the item before or after the row:
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
Button button = new Button("A");
// d&d source providing next char
button.setOnDragDetected(evt -> {
Dragboard db = button.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(button.getText());
db.setContent(content);
});
button.setOnDragDone(evt -> {
if (evt.isAccepted()) {
// next char
button.setText(Character.toString((char) (button.getText().charAt(0) + 1)));
}
});
// accept for empty table too
table.setOnDragOver(evt -> {
if (evt.getDragboard().hasString()) {
evt.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
evt.consume();
});
table.setOnDragDropped(evt -> {
Dragboard db = evt.getDragboard();
if (db.hasString()) {
table.getItems().add(new Item(db.getString()));
evt.setDropCompleted(true);
}
evt.consume();
});
TableColumn<Item, String> col = new TableColumn<>("value");
col.setCellValueFactory(new PropertyValueFactory<>("value"));
table.getColumns().add(col);
// let rows accept drop too
table.setRowFactory(tv -> {
TableRow<Item> row = new TableRow();
row.setOnDragOver(evt -> {
if (evt.getDragboard().hasString()) {
evt.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
evt.consume();
});
row.setOnDragDropped(evt -> {
Dragboard db = evt.getDragboard();
if (db.hasString()) {
Item item = new Item(db.getString());
if (row.isEmpty()) {
// row is empty (at the end -> append item)
table.getItems().add(item);
} else {
// decide based on drop position whether to add the element before or after
int offset = evt.getY() > row.getHeight() / 2 ? 1 : 0;
table.getItems().add(row.getIndex() + offset, item);
evt.setDropCompleted(true);
}
}
evt.consume();
});
return row;
});
Scene scene = new Scene(new VBox(button, table));
primaryStage.setScene(scene);
primaryStage.show();
}
public class Item {
public Item() {
}
public Item(String value) {
this.value.set(value);
}
private final StringProperty value = new SimpleStringProperty();
public String getValue() {
return value.get();
}
public void setValue(String val) {
value.set(val);
}
public StringProperty valueProperty() {
return value;
}
}
I use this JavaFX code to drag BorderPane into FlowPane:
private Node dragPanel(Node bp)
{
bp.setOnDragDetected(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent event)
{
Dragboard db = bp.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboard = new ClipboardContent();
final int nodeIndex = bp.getParent().getChildrenUnmodifiable()
.indexOf(bp);
clipboard.putString(Integer.toString(nodeIndex));
db.setContent(clipboard);
Image img = bp.snapshot(null, null);
db.setDragView(img, 7, 7);
event.consume();
}
});
bp.setOnDragOver(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
boolean accept = true;
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString())
{
try
{
int incomingIndex = Integer.parseInt(dragboard.getString());
int myIndex = bp.getParent().getChildrenUnmodifiable()
.indexOf(bp);
if (incomingIndex == myIndex)
{
accept = false;
}
}
catch (java.lang.NumberFormatException e)
{
// handle null or not number string in clipboard
accept = false;
}
}
else
{
accept = false;
}
if (accept)
{
event.acceptTransferModes(TransferMode.MOVE);
}
}
});
bp.setOnDragDropped(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
boolean success = false;
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString())
{
try
{
int incomingIndex = Integer.parseInt(dragboard.getString());
final Pane parent = (Pane) bp.getParent();
final ObservableList<Node> children = parent.getChildren();
int myIndex = children.indexOf(bp);
final int laterIndex = Math.max(incomingIndex, myIndex);
Node removedLater = children.remove(laterIndex);
final int earlierIndex = Math.min(incomingIndex, myIndex);
Node removedEarlier = children.remove(earlierIndex);
children.add(earlierIndex, removedLater);
children.add(laterIndex, removedEarlier);
success = true;
}
catch (java.lang.NumberFormatException e)
{
//TO DO... handle null or not number string in clipboard
}
}
event.setDropCompleted(success);
}
});
// bp.setMinSize(50, 50);
return bp;
}
I enable this drag event using this code:
BorderPane panel = new BorderPane();
dragPanel(panel),
I also have resize code which is also activated. I need some way to apply the drag code only of I click and drag the panel. I want to disable the drag listener when I drag the panel borders. Is there a way to limit this?
I'm guessing by "borders" you just mean the edges of the border panes. You can just check the coordinates of the mouse event and only initiate dragging if you're away from the borders. To do this, you need to know the width and height of the border pane. The methods to get those are defined in Region, so you need to narrow the type of the parameter from Node to Region. This will still work if you call dragPanel(panel) but you won't be able to pass in a Node that is not a Region instance.
final int borderSize = 5 ;
// ...
private Node dragPane(Region bp) {
bp.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
double x = event.getX();
double y = event.getY();
double width = bp.getWidth();
double height = bp.getHeight();
if (x > borderSize && x < width - borderSize
&& y > borderSize && y < height - borderSize) {
Dragboard db = bp.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboard = new ClipboardContent();
final int nodeIndex = bp.getParent().getChildrenUnmodifiable()
.indexOf(bp);
clipboard.putString(Integer.toString(nodeIndex));
db.setContent(clipboard);
Image img = bp.snapshot(null, null);
db.setDragView(img, 7, 7);
event.consume();
}
}
});
// ...
}