JavaFX Change list of labels on button click - button

I have a list of Labels in a JavaFX app that I've preset with a holder value as such:
for(int i = 0; i < 4; i++) {
lblUserNames.add(new Label("Username goes here"));
}
and I'm trying to change the label to display the username on the click of a button by using
public void setUsername(int index, String lblUserName) {
this.lblUserNames.set(index, new Label(lblUserName));
}
But it's still showing the holder text instead of updating to show the usernames; and yet when I print out the list of labels, the values have indeed changed.
I had it working before when I had just an array of labels (Label[]) and could use ".setText(lblUserName). I changed it to an ArrayList so that more users can be added and the code wouldn't have to change much, but now I can't use setText() anymore.
I've seen similar questions for changing the text for just a Label but the solution is to use setText() which won't work with an ArrayList of Labels. Is there any way to update and replace the holder text with the new labels for an ArrayList?

When you replace the label in your list, you are not replacing it in the UI. The original label is still shown in the UI. Just call setText(...) on the existing label:
public void setUsername(int index, String lblUserName) {
this.lblUserNames.get(index).setText(lblUserName);
}

Related

Proper way to add nodes using loop

I'm trying to make a small application that displays the contents of an arrayList but I have not been succesful. Currently I have a loop concatenating each object in the list with their toString method. This is not the solution I want for displaying the arrayList however. I want to be able to add a separate label and button for each object in the list so that I can press the button and open a window to change the item's data. Is there a way to add multiple javafx nodes using a loop AND add a parameter/id to a button? I know you can set an id to a button using fxml but I have to make this application without using fxml and have not been able to figure out how to do it otherwise.
Here is a code example of how I add the text right now
String list;
for (Registration registration : registrationList) {
list += registration.toString();
}
label.setText(list);
and what I've tried so far
for (Registration registration : registrationList) {
Label dynamicLabel = new Label(registration.toString());
Button dynamicButton = new Button("" + registration.getId());
layout1.getChildren().addAll(dynamicLabel, dynamicButton);
}
please let me know if something is unclear in my question, thanks in advance.
The problem is that you're thinking about the controls like data, and you need to treat them like regular objects. You're also thinking about the entire thing monolithically, which makes it difficult to see a solution.
Think about a Label + a Button as a distinct unit that works together. Define them together and you can freely have them talk to each other without figuring out ways to identify them and link them together later on.
Something like this will do what you're looking for:
public class ButtonActionSample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
List<String> strings = List.of("String 1", "String 2", "String 3");
VBox vBox = new VBox(5);
vBox.getChildren().addAll(strings.stream().map(string -> createHBox(string)).collect(Collectors.toList()));
primaryStage.setScene(new Scene(vBox));
primaryStage.show();
}
private Node createHBox(String string) {
Label label = new Label(string);
Button button = new Button("Change Text");
button.setOnAction(evt -> new TextInputDialog(label.getText()).showAndWait().ifPresent(label::setText));
return new HBox(5, label, button);
}
}
When you do it like this, you don't need to hang on to references to any of the screen elements at all; just create them, set the action on the Button and stick them on the screen. They just work after that.

How do I get a new value from an editable combo box?

I am trying to add a value to an editable combo box called nameComboBox that I created in the Scene Builder.
I populate the combo box with this code:
private ObservableList<String> getNames()
{
return (FXCollections.observableArrayList("Freddy","Kerstin"));
}
..
nameComboBox.getSelectionModel().select(getNames());
I have a Save button defined form the Scene Builder. The code looks like this:
#FXML
private void handleSaveBtn()
{
System.out.println("The new name is " + nameComboBox.getValue());
}
When the scene is displayed, the combo boxes editable field is displayed empty with the two names hidden in the list underneath the empty field, which is what I want to happen.
If then type "Rusty" in the empty field and click a save button all that happens is that the println statement returns
"The new name is null".
If I wanted to do something with the new value, like validate it or store it in a database, how do I get the value that I entered in the editable field?
Try using this instead of .getValue() :
nameComboBox.getEditor().getText()
This returns the value of the textProperty of the TextField (.getEditor()) of the editable ComboBox.
try this
nameComboBox.setItems(getNames());
nameComboBox.setValue("Freddy");

How to use the Vaadin Testbench with Rich Text Area?

I am using Vaadin Testbench (4.1.0-alpha) for designing some integration test for my application (designed in Vaadin 7.6.1).
In a window, I use a rich test area. The idea is to design a test where the value of this rich text element is changed simulating some user behaviour. But now I realize I cannot find any method for change the value of this element, neither get the current value of the element.
I have tested some methods.getHTML() gets the HTML for the component, no the HTML of the designer. getText() gets the list of elements (font colour, background and other options of the element, but not the content).
Then I expect to have specific class methods for retrieving the value. If I explore the class RichTextAreaElement, seems that no method is implemented. All code in this class is:
#ServerClass("com.vaadin.ui.RichTextArea")
public class RichTextAreaElement extends AbstractFieldElement {
}
As you can see, no method is declared.
How can I do a test where a user change the value of this rich text area? It is not implemented?
Hmm yeah, that looks like some work in progress, probably because it's a complex component with all the features it provides. Nonetheless we can workaround the limitations a bit, again making use of chrome developer tools (or similar) and some custom classes to select the components by (actually it's just the gwt-RichTextArea).
Of course this serves just as a starting point and can be further enhanced. Also I'd be very interested to see a more elegant solution if someone finds one...
Structure inspection
Test class
public class RichTextAreaTest extends TestBenchTestCase {
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver", "D:\\Kit\\chromedriver_win32\\chromedriver.exe");
setDriver(new ChromeDriver());
}
#After
public void tearDown() throws Exception {
// TODO uncomment below once everything works as expected
//getDriver().quit();
}
#Test
public void shouldModifyRichTextArea() throws InterruptedException {
// class to identify the editor area by
String editorClass = "gwt-RichTextArea";
// open the browser
getDriver().get("http://localhost:8080/");
// select the first rich text
RichTextAreaElement richTextArea = $(RichTextAreaElement.class).first();
// get the editor section which is where we're writing
WebElement richTextEditorArea = richTextArea.findElement(By.className(editorClass));
// click inside to make it "editable"
richTextEditorArea.click();
// send some keystrokes
richTextEditorArea.sendKeys(" + something else added by selenium");
}
}
Result:
Update for getting the value
If you simply want to get the text, the code below will do the trick:
// switch to the editor iframe
getDriver().switchTo().frame(richTextEditorArea);
// get the <body> section where the text is inserted, and print its text
System.out.println("Text =[" + findElement(By.xpath("/html/body")).getText() + "]");
Output
Text =[Some predefined text + something else added by selenium]
At the end, I was able to obtain the content of the element selecting the first iframe of the page, and searching for the body content. The final code looks like:
String currentWindow = getDriver().getWindowHandle();
getDriver().switchTo().frame(getDriver().findElement(By.tagName("iframe")));
WebElement webelement = this.findElement(By.xpath("/html/body"));
String text = webelement.getText();
getDriver().switchTo().window(currentWindow);
return text;
As I need to switch between the iframe and the window, I am only able to obtain the content of the element, not the element itself. If I return directly the element for future use, an org.openqa.selenium.StaleElementReferenceException: Element belongs to a different frame than the current one - switch to its containing frame to use it exception is obtained.
For changing the text, the solutions is very similar, only use the sendKey functions to first remove existing characters and later add the new text:
String currentWindow = getDriver().getWindowHandle();
getDriver().switchTo().frame(getDriver().findElement(By.tagName("iframe")));
WebElement webelement = this.findElement(By.xpath("/html/body"));
// Remove any previous text.
String previousText = webelement.getText();
for (int i = 0; i < previousText.length(); i++) {
webelement.sendKeys(Keys.DELETE);
}
// Set text.
webelement.sendKeys(text);
getDriver().switchTo().window(currentWindow);

Flex multiple selection drop down list with scrolling

I'm working in flex and I made a custom drop down where there are check boxes to allow the user to select multiple options. I used this template.
However this does not have scrolling because if you allow scrolling for some reason the checkboxes start to mess up. For instance if you have options 1 to 8 and only 1 to 5 are shown. You select option 1 and then scroll down to select option 7. When you scroll up the checkboxes start to switch around like option 3 all of a sudden is showing selected. Keep scrolling up and down and the checkbox selection just changes on it's own. I think this is a rendering issue and the actual selection data isn't changed at all (it knows only option 1 and option 7 were selected). Any ideas on how to fix this?
public function onOpen(event:DropDownEvent):void
{//load the checkboxes and set the mouse tracker
activateAllCheckBoxes();
this.scroller.verticalScrollBar.addEventListener(Event.CHANGE, list_verticalScrollBar_change);
callLater(observeMouse);
}
private function list_verticalScrollBar_change(evt:Event):void
{
//currentlySelectedCheckBoxes = selectedCheckboxes;
UpdateCheckBoxesWhenScrolling();
selectedIndex = -1;
}
protected function UpdateCheckBoxesWhenScrolling():void
{
for (var c:int = 0; c < dataGroup.numElements; c++) {
var obj:DropDownCheckBox = dataGroup.getElementAt(c) as DropDownCheckBox;
if(obj!=null)
{
var judgDebtorFromCheckBox:JudgDebtor = (obj.data) as JudgDebtor;
if(FindInCurrentList(judgDebtorFromCheckBox.JudgmentDebtorId)>0)
{
obj.checkbox.selected = true;
}
else
{
obj.checkbox.selected = false;
}
}
}
}
private function FindInCurrentList(ID:int):int
{
for(var i:int=0;i<currentlySelectedCheckBoxes.length;i++)
{
var JD:JudgDebtor = currentlySelectedCheckBoxes.getItemAt(i) as JudgDebtor;
if(JD.JudgmentDebtorId == ID)
return 1;
}
return -1;
}
So above code I register a scroll event listener on the drop down. It will update the drop down entries which has a check box and it uses an array collection called: currentlySelectedCheckBoxes. I debug the UpdateCheckBoxesWhenScrolling function and it's working fine, in other words it will check off the ones selected but for some reason it still is showing the wrong results for instance 11 entries in the list and only the second one is selected I scroll down and I can't see the the second entry but all of a sudden the last entry is showing that it's checked off.
This happens because the drop down list reuses the renderers when you scroll. For example if you have checked 1st item and scroll, the renderer for that is reused to display the item that becomes visible when you scroll. So the last item shows as checked. To avoid messing up the selection, you will have to do the following in the renderer that you are using
override public function set data(value:Object):void
{
super.data = value;
//inspect the property which indicates whether to select the checkbox or not
//and set the value of selected property accordingly
}
Hope this helps

Cursor moves to the start location on selection in spark combobox?

I have a . I provide arraylist as its data provider. my question is why moves to the ing location in when I select any item using enter key. Also when I press space from keyboard, again moves to ing location. How can I fix this? Thanks
protected function onInputKeyDown(e:KeyboardEvent):void
{
if(e.keyCode == 13)
{
AddPath(cb.textInput.text);
cb.dataProvider = recentList;
}
}
here recentList is a Bindable ArrayList. Every Time when I enter anything in ComboBox and press Enter, The cursor moves to the beginning in the Text Area of ComboBox. AddPath function simply adds the new data to the recentList.
When you set cb.dataProvider = recentList; you are essentially assigning a new pointer which overrides the previous list and resets the cursor.
You should be able to create a variable containing the selected item and manually set the ComboBox to that item on click/enter after you carry out the cb.dataProvider = recentList;
protected function onInputKeyDown(e:KeyboardEvent):void
{
if(e.keyCode == 13)
{
var selectedItem:String = cb.selectedItem
AddPath(cb.textInput.text);
cb.dataProvider = recentList;
cb.selectedItem(selectedItem);
}
}
Apologies if the code isn't perfect, but the theory should be right.

Resources