JavaFx WebView - how to scroll it to the bottom - javafx

I have made a conversation stage in JavaFx with a WebView that is displaying whole conversation. I want to show it from the bottom where the newest messages are so I used a function "execute script":
public void initialize() throws SQLException
{
buildText();
conversationText.getEngine().loadContent(text1);
conversationText.getEngine().executeScript("window.scrollTo(0, document.body.scrollHeight);");
conversationText.getEngine().setUserStyleSheetLocation(getClass().getResource("/html/style.css").toExternalForm());
}
I wrote this function in an initialize() void but it doesn't work, when I open the conversation it shows me all from the top where the eldest messages are :
But what is interesting it works properly when I use this metod form a void that is connected with a button named "script"
public void script()
{
conversationText.getEngine().executeScript("window.scrollTo(0, document.body.scrollHeight);");
}
when I press this button it scrolls to the bottom :
Is there any way to do this correct in an initialize void ? I have tried many ways like inserting the button method script() into initialize but i noticed that if I use function webengine.loadcontent() it always displays me all from the top.
I want to show the user the newest messages at the bottom from the beginning , not after pushing a button.

Related

How does one call a method on the changing of a Tab in JavaFx?

Ok so here is what i am trying to do: I have a page called 'SettingsPage'. Now, in this page i Have a tabPane with 3 tabs; users, buttons, and sales. Buttons and Users both have tables which need to be populated with data before they are viewed by the user. When I was first making the program I just used a 'initialize' method to populate the user table on the opening of 'SettingsPage'. However, now that I am beginning to try and populate the buttons table, I am encountering a memory error because now there is too much data to be loaded at once together.
So, I though a good solution to this would be to make an Event method that is called whenever a certain tab is opened. I am using SceneBuilder atm, and what seemed to be the equivalent of this was onSelectionChanged, however I can't seem to use this as you would use 'methodEg(ActionEvent event)...'. So my question is, how can ensure that a method will be called on the opening of a certain tab.
For example, when 'buttonTab' is clicked, the 'populateButtonTable' method is called.
The answer to this was this code:
And if anyone asks why I didn't use .isSelected()... I did, it for some reason didn't work, but what I have done below does, so I dunno...
'''
#FXML public void initialize(URL url, ResourceBundle rb){
tabs.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> ov, Tab t, Tab t1)
{
if (tabs.getSelectionModel().getSelectedItem() == ExampleTab)
{
//do whatever
}
}
}
);

Navigation issue in Xamarin Forms with same page type multiple time

Relatively new to Xamarin, hitting an issue with PushAsync and navigation I can't figure out.
I have a main navigation page, and then a "MyContentPage" that is responsible for rendering a dynamic list based on a supplied id. When the user clicks on a list item they go to a next (newed up) "MyContentPage" (same class) with a different id. Basically a recursive page hierarchy based on a local db.
Problem is that navigation seems to quickly get messed up in some way I can't work out. The pages get swapped around, or get lost. Navigating back to root, if I click back down again, it skips to a page that is further down etc.
So basically the one page apart from the main page (which has multiple navigationpages in tabs - though I only use one tab at this point) binds its controls to this function:
public async Task NavigateToContent(int contentId)
{
await ((Application.Current.MainPage) as TabbedPage)?.CurrentPage.Navigation.PushAsync(new MyContentPage(contentId));
}
The above is then used recursively. Ie. Similar controls bind to the same function until there are no further pages to click down to.
The MyContentPage constructor loads the model:
public MyContentPage(int id)
{
InitializeComponent();
_id = id;
BindingContext = viewModel = new ContentPageViewModel(id);
}
What is the issue here?
From what you mentioned in comments, the issue is caused by the navigation code called in the 'service' class. When you call the service method multiple times, it actually changes the current navigation stack in xamarin forms. Move the page navigation code from service class to viewmodel class.
Or try to put the page navigation source code into something like 'NavigationService' (one example is the one in https://learn.microsoft.com/en-us/xamarin/xamarin-forms/enterprise-application-patterns/ ) and inject this service into your view model class.
OK so this all turned out to be an issue with concurrency.
The original button click was like this:
private void Button_Clicked(object sender, EventArgs e)
{
Task.Run(async () => await (BindingContext as ContentPageViewModel).ExecuteNavCommand(sender));
}
But this resulted in a UI operation happening on a different task
The event handler can be declared as async
The correction is
private async void Button_Clicked(object sender, EventArgs e)
{
await viewModel.ExecuteNavCommand(sender);
}

Not able to click on button in iframe window, but getting success while debugging

Not able to click on button element in iframe window, but getting success while debug.
While debugging I am successfully getting passed through action. Both the times(debugging and executing) UI(application) cannot see any actions performed.
Can Any one suggest this please. I have tried using giving waits. Xpath for button can not be wrong as Its successfully getting passed while debugging.
May be it a browser issue or something? I am using firefox browser
waitforelementpresent(locator.login_email);
click(locator.login_email);
type(locator.login_email,email);
click(locator.login_password);
type(locator.login_password,password);
Thread.sleep(5000);
click(locator.login_button); //This button I need to click
Base Class
public static void click(By by) {
WebDriverWait wait = new WebDriverWait(driver, defaultWaitPeriod);
wait.until(ExpectedConditions.elementToBeClickable(by));
driver.findElement(by).click();
}
public static void type(By by, String type) {
WebDriverWait wait = new WebDriverWait(driver, defaultWaitPeriod);
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
driver.findElement(by).clear();
driver.findElement(by).sendKeys(type);
Locators
public By login_email=By.xpath("//input[#placeholder='Email ']");
public By login_password=By.xpath("//input[#placeholder='Password ']");
public By login_button=By.xpath("//form[#class='m-t ng-dirty ng-valid-email ng-valid-parse ng-valid ng-valid-required']//button");
html code

Android TV: Disable collapsing on info_field on ImageCardView

I'm working with Android TV for the first time and I'm learning to use Leanback by modifying the example tv app that is provided.
The issue I'm having is that when I press left on the first item in the lists the navigation drawer opens and focus goes to the headers in the navigation drawer. When this happens, the info_field view in the ImageCardViews collapse behind the image.
What happens: The info field on the ImageCardView hides when I open the navigation drawer.
What I want to Happen: The info field remains visible when I open the navigation drawer.
I'm sure there's a way to do this because I've seen it in some Android TV apps, like Twitch. What's the best way to have the info_field visible when the navigation drawer is open?
I've worked out how to do it. In the CardPresenter, in onCreateViewHolder, when creating the ImageCardView I've overridden the BaseCardView method, setActivated(boolean activated) to always pass 'true' into it's super. And then call setActivated so that it's activated from the beginning. Like this:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
ImageCardView cardView = new ImageCardView(parent.getContext()) {
#Override
public void setActivated(boolean activated) {
super.setActivated(true);
}
#Override
public void setSelected(boolean selected) {
updateCardBackgroundColor(this, selected);
super.setSelected(selected);
}
};
cardView.setActivated(true);
cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
return new ViewHolder(cardView)
}
So that did the trick for me. The ImageCardView never collapses.
I think if you look at this SO post you'll get most of the way there. The info view hides due to what leanback calls "expanding".
Try just calling enableMainFragmentScaling(false); in your BrowseFragment and see if that does what you want. If it doesn't feel like exactly what you want, refer to the post I linked to.
Additionally, if you've tried what I recommend in the linked SO post, you could also call the API on the BaseCardView setInfoVisibility() and pass it CARD_REGION_VISIBLE_ALWAYS. This just requires calling on a reference to your card which shouldn't need an override of the Presenter or Card.

Refreshing tableView in JavaFx after closing dialog

I have two layouts in JavaFX app. The first one contains table view whereas the second one is a simple dialog to input data. The problem is that I want to refresh data after closing the dialog. Now I have a button on the first layout which refreshes data:
data.removeAll(data);
loadDataToTable();
But I don't want to invoke methods shown above with the button but automatically right after closing the dialog. I don't know how to make this, let's say, connection between those controllers.
thanks in advance
The new Dialog, if I am not wrong must be a new Stage ! Let us consider the new Stage to be modifyStage. We can call the onSetCloseRequest of the new Stage and put your code in it.
modifyStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent paramT) {
data.removeAll(data);
loadDataToTable();
}
});

Resources