My problem is that I want my popups to either close or not be stay-on-top.
Currently, when I click on a window which is different from my app, the app disappears behind it, but the popups stay on top, in front of the window belonging to a different application.
I want the popups to either behave differently, or as a hack I would like to hide the popup.
I tried to do this with Listeners as I found these in other q&a on stackoverflow, but these Listeners never get called when I minimize or lose focus with the window.
I commented out the code which does not work in below code.
/*
* (non-Javadoc)
*
* #see javafx.application.Application#start(javafx.stage.Stage)
*/
#Override
public void start(Stage primaryStage)
{
log.debug("JavaFx start method");
//log.trace("is used", fileViewController.toString());
try
{
splash.start(primaryStage, () -> startMain());
primaryStage.toFront();
//HACK attempt
//primaryStage.setAlwaysOnTop(false);
//FIXME: this doesn't work (is not called)
/*
primaryStage.iconifiedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
System.err.println("minimized:" + t1.booleanValue());
popupBuilder.hide();
popupPicker.hide();
popupAbout.hide();
popupExecute.hide();
popupAdministration.hide();
popupLicensegenerator.hide();
popupProjects.hide();
}
});
*/
/*
* This doesn't work, either
primaryStage.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) {
System.err.println("focus:" + newValue);
if (!newValue){
popupBuilder.hide();
popupPicker.hide();
popupAbout.hide();
popupExecute.hide();
popupAdministration.hide();
popupLicensegenerator.hide();
popupProjects.hide();
}else{
//nothing
}
}
});
*/
}
catch (Exception e)
{
log.error("Error during start initialization of main application!");
e.printStackTrace();
System.exit(1);
}
}
Related
I am developing an javaFX application where the user has several textfields to fill and edit. I want that if you enter a new textfield by jumping from another by pressing TAB the content of the textfield is not selected and also the cursor is on the right. The textfields have an event listener that detects when they receive the focus and I have been testing various methods of the API to position the cursor and deselect content when entering the textfield, for the moment, all without success.
Where is my error?
id_ip2B_tf.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
// 1 - don't work
id_ip2B_tf.deselect();
id_ip2B_tf.positionCaret(id_ip2B_tf.getLength());
// 2 - don't work
id_ip2B_tf.end();
}
}
Can you try wrapping the logic of setting the caret in Platform.runLater. Something like..
id_ip2B_tf.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
Platform.runLater(()->{
id_ip2B_tf.deselect();
id_ip2B_tf.positionCaret(id_ip2B_tf.getLength());
});
}
}
});
I am using an MVC model where I initialize all the action listeners for the view in the controller. For example:
The view:
public void addStartDateListener(ChangeListener<Boolean>e){
startDate.focusedProperty().addListener(e);
}
public void addFinishDateListener(ChangeListener<Boolean>e){
finishDate.focusedProperty().addListener(e);
}
The controller:
this.theView.addStartDateListener(new startDateFocusListener());
this.theView.addFinishDateListener(new finishDateFocusListener());
class finishDateFocusListener implements ChangeListener<Boolean> {
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
{
if (newPropertyValue)
{
System.out.println("Finish date");
}
else
{
System.out.println("Finish date");
}
}
}
//focus listener to update the date whenever the focus is lost
class startDateFocusListener implements ChangeListener<Boolean> {
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
{
if (newPropertyValue)
{
System.out.println("start date");
}
else
{
System.out.println("start date");
}
}
As the stage(which is the view) appears I need for the application to wait till it gets closed and not allow the user to perform any other action on other stages. If however I use "showAndWait()" with "initModality(Modality.APPLICATION_MODAL);" The action listeners do not get added to the view, but if I use only "initModality(Modality.APPLICATION_MODAL);" it does not allow the user to perform any actions on other stages except the one and all the action listener are fully functional, but I still need to wait till the stage gets closed and only then continue further as the rest is depending on the output of the stage that is being created. So my question is how can I do it?
I have so far tried to use Task with "setOnSucced" and etc. However no luck. I am fairly new to the MVC concept as well.
I have implemented a NavigationDrawer with a few items in it. Every item represents a different Fragment and one of them has tabs. My problem is that every time I open this Fragment the tabs reloaded! and added to the previous tabs. Why is this happening and how can I solve it?
This is the Fragment with the tabs:
public class fragment_profilo_tabs extends Fragment implements ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
String[] tabs = { "Profilo aziendale", "Credenziali" };
/* (non-Javadoc)
* #see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*/
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
// Initilization
View view = View.inflate(getActivity(), R.layout.profilo_tabs, null);
viewPager = (ViewPager) view.findViewById(R.id.pager);
actionBar = getActivity().getActionBar();
mAdapter = new TabsPagerAdapter(getFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
return view;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
And this is my ViewPagerAdapter:
public class TabsPagerAdapter extends FragmentPagerAdapter {
/* (non-Javadoc)
* #see android.support.v4.view.PagerAdapter#getItemPosition(java.lang.Object)
*/
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return POSITION_NONE;
}
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new fragment_profilo_modificaProfilo();
case 1:
// Games fragment activity
return new fragment_profilo_credenzialiAccesso();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Ok there are multiple issues. First and foremost lets talk about your ViewPagerAdapter:
The first thing that caught my eye is this:
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return POSITION_NONE;
}
This is very bad for performance. I know that some posts on Stack Overflow suggest using this to "fix" a few things, but that is not the way to go. Remove this, you don't need it.
But the main issue is in your Fragment. First and foremost this:
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab()
.setText(tab_name)
.setTabListener(this));
}
You are adding tabs to the ActionBar. And the ActionBar is not part of you Fragment. Each time you display this Fragment you add the same tabs to the ActionBar but you never remove them again or anything.
My advice: Don't do this. Open a new Activity for the tabs Fragment. This should clearly not be in the same Activity. I cannot imagine any situation where suddenly adding tabs to the current Activity would satisfy the Android Platform Guidelines or provide good usability.
The general rule is that everything that has to do with the Activity itself - like things concerning the ActionBar or tabs in the ActionBar - should be handled in the Activity. Code which adds tabs to the ActionBar has no place inside a Fragment. So either add the tabs permanently in onCreate() of your Activity. Or create a new Activity with those tabs especially for the fragment_profilo_tabs.
As an aside: class names should never be Snake Case. Start class names with an uppercase letter and use Camel Case. Everything else will just confuse other programmers looking at your code
I'm trying to show a context menu only when there is something selected in the list view.
So I called hide in its on showing event. However, this is not working. The context menu still shows up. Is this a bug, or not its intended use? Because JavaFX api seems to suggest hide() is suppose to do this.
Anyway this is the code.
ContextMenu menu = new ContextMenu();
menu.setOnShowing(new EventHandler<WindowEvent>() {
#Override
public void handle(final WindowEvent event) {
menu.hide();
}
});
It will probably work if you do
public void handle(final WindowEvent event) {
Platform.runLater(new Runnable() {
#Override
public void run() {
menu.hide();
}
});
}
but that really seems like a horrible hack.
Why not just set the context menu only if something is selected?
final ListView<T> listView = ... ;
final ContextMenu menu = new ContextMenu();
listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<T>() {
#Override
public void changed(ObservableValue<? extends T> obs, T oldValue, T newValue) {
if (newValue == null) {
listView.setContextMenu(null);
} else {
listView.setContextMenu(menu);
}
}
});
(obviously replace T with whatever type your ListView is displaying).
private ContextMenu menu; private MenuItem deleteItem;
table.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
#Override
public void handle(ContextMenuEvent event) {
if (table.getSelectionModel().getSelectedIndex() != -1) {
deleteItem.setVisible(true);
deleteItem.setText("delete: " + table.getSelectionModel().getSelectedItem().getName());
contextMenu.show(table, event.getScreenX(), event.getScreenY());
} else {
deleteItem.setVisible(false);
}
event.consume();
}
});
primaryStage.getScene().addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) { menu.hide(); }});
I'm having trouble with the JavaFX Preloader. During the start phase the application will have to connect to a DB and read many so I thought it would be nice to display a splash screen during this time. The problem is the ProgressBar automaticly goes to 100% and I don't understand why.
Application class. Thread sleep will be replaced by real code later (DB connection etc)
public void init() throws InterruptedException
{
notifyPreloader(new Preloader.ProgressNotification(0.0));
Thread.sleep(5000);
notifyPreloader(new Preloader.ProgressNotification(0.1));
Thread.sleep(5000);
notifyPreloader(new Preloader.ProgressNotification(0.2));
}
Preloader
public class PreloaderDemo extends Preloader {
ProgressBar bar;
Stage stage;
private Scene createPreloaderScene() {
bar = new ProgressBar();
bar.getProgress();
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
#Override
public void handleStateChangeNotification(StateChangeNotification scn) {
if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
stage.hide();
}
}
#Override
public void handleProgressNotification(ProgressNotification pn) {
bar.setProgress(pn.getProgress());
System.out.println("Progress " + bar.getProgress());
}
For some reason I get the following output:
Progress 0.0
Progress 1.0
I had same problem and I found solution after two hours of searching and 5 minutes of carefully reading of JavaDoc.:)
Notifications send by notifyPreloader() method can be handled only by Preloader.handleApplicationNotification() method and it doesn't matter which type of notification are you sending.
So change you code like this:
public class PreloaderDemo extends Preloader {
.... everything like it was and add this ...
#Override
public void handleApplicationNotification(PreloaderNotification arg0) {
if (arg0 instanceof ProgressNotification) {
ProgressNotification pn= (ProgressNotification) arg0;
bar.setProgress(pn.getProgress());
System.out.println("Progress " + bar.getProgress());
}
}
}