JAVAFX - share object between controllers - object

Please how to share object User between Controllers? I have a TabPanelController. In initialization send to other controllers Data with object User. Its OK, but I cant acces to this object before stage shown.
Its possible acces to Stage in initialize method in controller, when controller is loaded before Stage? Or how handle onWindowShow in loader (When windows show, object User was filled)?
#FXML
private ActionController panelActionController;
#FXML
private StoreController panelStoreController;
#FXML
private ProfilesController panelProfilesController;
#FXML
private UsersController panelUsersController;
#FXML
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Platform.runLater(new Runnable() {
#Override
public void run() {
menuUserInfo.setText(" " + loggedInUser.getName() + " " +
loggedInUser.getForname() + " (" + loggedInUser.getLogin() + ")");
menuUserInfo.setUserData(loggedInUser);
panelActionController.setLoggedUser(loggedInUser);
panelStoreController.setLoggedUser(loggedInUser);
panelProfilesController.setLoggedUser(loggedInUser);
panelUsersController.setLoggedUser(loggedInUser);
}
});
}
In panelActionController
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
System.out.println(loggedInUser); // NULL..
}
When i press any button in stage, loggedUser is not null. But i need set buttons, textfields by user role (Admin, User) during initialization.

SOLVED:
1. Inject Controllers in Main TabPanel Controller
in fxml must have a root element (e.g. GridPane) with fx:id="panelAction".
Controller must name: fx:id of GridPane + word Controller : panelActionController
#FXML
private ActionController panelActionController;
#FXML
private StoreController panelStoreController;
#FXML
private ProfilesController panelProfilesController;
#FXML
private UsersController panelUsersController;
2. I write getters for all child controllers in main TabPanelController:
public ActionController getActionController() {
return panelActionController;
}
public StoreController getStoreController() {
return panelStoreController;
}
public ProfilesController getProfilesController() {
return panelProfilesController;
}
public UsersController getUsersController() {
return panelUsersController;
}
3. And in main TabPanelStage (here i have Object loggedInUser) get all controllers
TabPanelController tabPanelController = fxmlLoader.getController();
ActionController actionController = tabPanelController.getActionController();
StoreController storeController = tabPanelController.getStoreController();
ProfilesController profilesController = tabPanelController.getProfilesController();
UsersController usersController = tabPanelController.getUsersController();
4. And then:
actionController.setComponentsByRole(loggedInUser.getRole());

Related

use Onclick in extends PagerAdapter

Hi I’m trying to create a horizontal slide where each horizontal page will have a button that will call a Dialog but onClick is not working in extends Pageradapter can anyone tell me what I’m doing wrong?
I gave the name onClickApprove to onClick that I want you to call Dialog. This Dialog is calling an Activity with a Ratingbar to make an assessment.
Thank you.
public class SliderAdapterUsado extends PagerAdapter {
Context context;
LayoutInflater layoutInflater;
BottomSheetDialog dialog;
Button show;
public SliderAdapterUsado(Context context){
this.context = context;
}
public String[] slide_rota ={
"Titulo1",
"Titulo2"
};
public String[] slide_nome={
"Descrção do titulo 1",
"Descrção do titulo 2"
};
#Override
public int getCount(){
return slide_rota.length;
}
#Override
public boolean isViewFromObject(View view, Object object){
return view == (LinearLayout) object;
}
#Override
public Object instantiateItem(ViewGroup container, int position){
layoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.slide_layout_usados, container, false);
TextView slideHeading = view.findViewById(R.id.slide_rota);
TextView slideDescricao = view.findViewById(R.id.slide_nome);
slideHeading.setText(slide_rota[position]);
slideDescricao.setText(slide_nome[position]);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object){
container.removeView((LinearLayout)object);
}
public void onClickAvaliar(View view) {
show = view.findViewById(R.id.show);
dialog = new BottomSheetDialog(dialog.getContext());
show.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createDialog();
dialog.show();
}
});
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
private void createDialog(){
View view = layoutInflater.inflate(R.layout.activity_rating, null, false);
Button FeedBack = view.findViewById(R.id.FeedBack);
FeedBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.setContentView(view);
}
}
Please read the documentation.
Note this in particular (emphasis mine):
To define the click event handler for a button, add the android:onClick attribute to the element in your XML layout. The value for this attribute must be the name of the method you want to call in response to a click event. The Activity hosting the layout must then implement the corresponding method.
The expectation is that the value set on the onClick xml attribute will be a method on the hosting Activity. Yours is in the adapter. That's why it doesn't work.
So either move that method to the hosting activity, or just handle the click event explicitly:
...
TextView slideHeading = view.findViewById(R.id.slide_rota);
TextView slideDescricao = view.findViewById(R.id.slide_nome);
Button slideButton = view.findViewById(R.id.slide_button);
slideButton.setOnClickListener (...)
...

How to add AdMob Interstitial banner to LibGDX game with several activities and classes?

I have a game on LibGDX. According to this
http://www.norakomi.com/tutorial_admob_part2_banner_ads1.php
instruction I created necessery methods in AndroidLauncher.java file. And in the core file, generated by AndroidLauncher.java, I have created the controller and also interface java file
( http://www.norakomi.com/tutorial_admob_part2_banner_ads2.php ).
The problem is that my game has several classes which extend one another and the corresponding condition, which I want to use for displaying adMob, is not that one to which method "initialize" gives "this" from AndroidLauncher.java file. But to download and to give request for adMob is possible only from AndroidLauncher.java, because another classes are in its own game view.
How to solve this?
This is the basic code from AndroidLauncher.java
public class AndroidLauncher extends AndroidApplication implements AdsController {
private static final String BANNER_AD_UNIT_ID = "ca-app-pub-3940256099942544/6300978111";
private static final String INTERSTITIAL_AD_UNIT_ID = "ca-app-pub-3940256099942544/1033173712";
AdView bannerAd;
InterstitialAd interstitialAd;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
// Create a gameView and a bannerAd AdView
View gameView = initializeForView(new Stork2016(this), config);
setupBanner();
setupInterstitial();
// Define the layout
RelativeLayout layout = new RelativeLayout(this);
layout.addView(gameView, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layout.addView(bannerAd, params);
setContentView(layout);
config.useCompass = false;
config.useAccelerometer = false;
public void setupBanner() {
bannerAd = new AdView(this);
//bannerAd.setVisibility(View.VISIBLE);
//bannerAd.setBackgroundColor(0xff000000); // black
bannerAd.setAdUnitId(BANNER_AD_UNIT_ID);
bannerAd.setAdSize(AdSize.SMART_BANNER);
}
public void setupInterstitial() {
interstitialAd = new InterstitialAd(this);
interstitialAd.setAdUnitId(INTERSTITIAL_AD_UNIT_ID);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
interstitialAd.loadAd(ad);
#Override
public void showInterstitialAd(final Runnable then) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (then != null) {
interstitialAd.setAdListener(new AdListener() {
#Override
public void onAdClosed() {
Gdx.app.postRunnable(then);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
interstitialAd.loadAd(ad);
}
});
}
interstitialAd.show();
}
});
}
#Override
public boolean isWifiConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return (ni != null && ni.isConnected());
}
#Override
public void showBannerAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
bannerAd.setVisibility(View.VISIBLE);
AdRequest.Builder builder = new AdRequest.Builder();
AdRequest ad = builder.build();
bannerAd.loadAd(ad);
}
});
}
#Override
public void hideBannerAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
bannerAd.setVisibility(View.INVISIBLE);
}
});
}
}
And then we have file Stork2016.java in which we create AdsController to be able to use methods for adds in AndroidLauncher.java.
private AdsController adsController;
public Stork2016(AdsController adsController){
this.adsController = adsController;
}
#Override
public void create () {
adsController.showBannerAd();
batch = new SpriteBatch();
gsm = new GameStateManager();
music = Gdx.audio.newMusic(Gdx.files.internal("music.mp3"));
music.setLooping(true);
music.setVolume(0.5f);
music.play();
Gdx.gl.glClearColor(1, 0, 0, 1);
gsm.push(new MenuState(gsm));
}
And also we have interface java file AdsController.java
public interface AdsController {
public void showBannerAd();
public void hideBannerAd();
public void showInterstitialAd (Runnable then);
public boolean isWifiConnected();
}
So, as we can see in Stork2016 we have "gsm.push(new MenuState(gsm));" and in MenuState.java I have "gsm.set(new PlayState(gsm));". In PlayState.java there is the part of code:
#Override
public void update(float dt) {
handleInput();
updateGround();
....
if (tube.collides(bird.getBounds()))
gsm.set(new GameOver(gsm));
...
}
}
camera.update();
}
The condition "if" frome the above code I want to use to show interstitial adMob. But it is impossibe, because the contoller which takes methods from AndroidLauncher.java can be created only in Stork2016.java. And also in AndroidLauncher.java there is
View gameView = initializeForView(new Stork2016(this), config);
wich transfers "this" to Stork2016, where is the controller.
In my AndroidLauncher activity I start the game and initialize the Insterstitial ad. Then I initialize my interface which I call from inside the game, to trigger show/hide of the interstitial ad.
For example I have method showInterstitialAd() in my interface listener, then my implementation on Android would be:
#Override
public void showCoverAd() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (interstitialAd.isLoaded()) {
interstitialAd.show();
}
}
});
}
And on iOS-MOE:
#Override
public void showCoverAd() {
if (gadInterstitial.isReady()) {
gadInterstitial.presentFromRootViewController(uiViewController);
}
}
So you need the make sure that the interface listener knows about the interstitial ad, for example AndroidLauncher implements MyGameEventListener
In my case interface AdsController.java is implemented in AndroidLauncher.java:
public class AndroidLauncher extends AndroidApplication implements AdsController { ...
And then by this part of code:
View gameView = initializeForView(new Stork2016(this), config);
we send "this" to new class Strork2016.java.
And in the class Stork2016.java I create constructor:
private AdsController adsController;
public Stork2016(AdsController adsController){
this.adsController = adsController;
}
which lets us use methods from interface AdsController.java.
But only in this class Stork2016. If I want to use it in another class:
gsm.push(new MenuState(gsm));
this is impossible and this is the problem.
OK guys, I have solved the problem.
I had to create two consturctors in both classes: the main core class which is initialyzed from AndroidLauncher and in the class GameStateManager. Because the class, where I want admob intersitital to be called, is created by method gsm.push which is described in class GameStateManager. Actually, in GameStateManager there have already been constuructor, so I hade only to add necessary code to this constructor.

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException

I'm writing a program on the desktop that takes an array of COM port and displays it on the chart dynamically. the program runs without failures for a while, but then fails with the following exception:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:521)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:505)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$399(QuantumToolkit.java:334)
at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$40/432581434.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$144(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/1963387170.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
the application continues to run. continue to saved data to a text file, but the window is not active any button except the close button.
if anyone has any ideas please help.
here is some code
public class FXMLController implements Initializable {
public static XYChart.Series<Number, Number> hourDataSeries;
#FXML
public Label label;
#FXML
public Label statusbar;
#FXML
public LineChart lineChart;
#FXML
public NumberAxis xAxis;
#FXML
NumberAxis yAxis;
#FXML
MenuItem close;
#FXML
MenuItem Options;
#FXML
MenuItem about;
#FXML
Button connect;
#FXML
public Label hexString;
#FXML
private void close(ActionEvent event) throws SerialPortException {
//COMConnect.serialPort.closePort();
System.exit(0);
}
#FXML
private void connect(ActionEvent event) {
OpenScene openScene = new OpenScene("/SceneCOM.fxml", "Options");
}
#FXML
private void showStatistics(ActionEvent event) {
OpenScene openScene = new OpenScene("/SceneStatistics.fxml", "Statistics");
}
#FXML
private void aboutit(ActionEvent event) {
OpenScene openScene = new OpenScene("/SceneAbout.fxml", "About");
}
#FXML
private void getconnect(ActionEvent event) {
if (COMConnect.b == true) {
COMConnect.b = false;
try {
COMConnect.serialPort.closePort();
} catch (SerialPortException ex) {
Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
}
connect.setText("Connect");
} else {
COMConnect.b = true;
COMConnect.comConnect();
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
hourDataSeries = new XYChart.Series<Number, Number>();
label.textProperty().bind(COMConnect.EventListener.valueProperty);
COMConnect.connectProperty.setValue("Connect");
connect.textProperty().bindBidirectional(COMConnect.connectProperty);
statusbar.textProperty().bind(Typewriter.status);
hexString.textProperty().bind(TypewriterHexString.hexStr);
xAxis.setLabel("Time");
xAxis.setTickUnit(1);
xAxis.setTickLabelFormatter(new NSC());
yAxis.setLabel("density," + superscript(" kg/m3"));
xAxis.setForceZeroInRange(false);
lineChart.setLegendVisible(false);
lineChart.setCursor(Cursor.CROSSHAIR);
lineChart.getData().add(hourDataSeries);
}
}
and add data to LineChart from other class
javafx.application.Platform.runLater(new Runnable() {
#Override
public void run() {
valueProperty.setValue(formatt(second) + superscript(" kg/m3"));
if (y > 10) {
hourDataSeries.getData().remove(0);
}
data = new XYChart.Data<Number, Number>(y, second);
data.setNode(new HoveredThresholdNode(0, second, ""));
hourDataSeries.getData().add(data);
System.out.println(hourDataSeries.getData().toString());
y++;
}
});
}
Thus, the solution was very simple:
lineChart.setAnimated(false);
the application works correctly for about 25 hours.
Thanks everyone!

JavaFX access ui-elements from Controller(Singleton)

I have a javafx design in the file javafx.fxml where the root element has the following attribute
fx:controller="de.roth.jsona.javafx.ViewManagerFX"
This controller class has a singleton machanism and is binded with some ui-elements.
public class ViewManagerFX {
private static ViewManagerFX instance = new ViewManagerFX();
#FXML
private Slider volumeSlider;
#FXML
private Label volumeLabel;
public IntegerProperty volumeValue = new SimpleIntegerProperty();
#FXML
private TabPane musicTabs;
public List<StringProperty> tabNames = new ArrayList<StringProperty>();
public static ViewManagerFX getInstance() {
return (instance);
}
public void initialize() {
// Volume
volumeSlider.valueProperty().bindBidirectional(volumeValue);
volumeLabel.textProperty().bindBidirectional(volumeValue, new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition pos) {
toAppendTo.append(obj);
toAppendTo.append("%");
return toAppendTo;
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null; // no need to be implemented
}
});
volumeValue.set(Config.getInstance().VOLUME);
}
public void addMusicFolderTab(final String t, final ArrayList<MusicListItem> items) {
Platform.runLater(new Runnable() {
#Override
public void run() {
Tab m = new Tab("Test Tab");
musicTabs.getTabs().add(0, m);
}
});
}
}
The method addMusicFolderTab is called from a thread that is used to scan files and directories.
In the initialize method I can access the ui-elements but in the method addMusicFolderTab, that is called from the filescanner-thread, the variable musicTabs is null. Here is the exception:
java.lang.NullPointerException
at de.roth.jsona.javafx.ViewManagerFX$3.run(ViewManagerFX.java:110)
I have no clue, why I can't access the TabPane from outside the initialize method.
Aside from the many questionable patterns used here, the problem is that your ViewManagerFX singleton (besides not being a singleton) never has its instance set.
When using FXML, the Controller is created and loaded dynamically by Reflection from the FXMLoader.
What happens is that by calling ViewManagerFX.getInstance(), you access the a different controller than the one created by the FXMLoader. The instance you access is the one created here:
private static ViewManagerFX instance = new ViewManagerFX();
The quickest way to solve the issue is to set the instance in the initialize() since it's called by the FXMLoader on the instance created by the FXMLoader.
public void initialize() {
instance = this;
// Volume
...
}

NPE while calling selectionModel().select() in TabPane

Here is my code:
public class TabApp implements Initializable {
#FXML
Button newButton;
#FXML
TabPane tabPane = new TabPane();
public Tab newTab;
private SingleSelectionModel<Tab> selectionModel;
public int zQueryTabCount = 2;
#FXML
public void handleNewButton(ActionEvent event) {
System.out.println("new button is pressed");
newTab = new Tab();
selectionModel.select(newTab);
newTab.setId("Query " + zQueryTabCount);
newTab.setText("Query " + zQueryTabCount);
tabPane.getTabs().add(tabPane.getTabs().size(), newTab);
tabPane.getTabs().get(0).setClosable(false);
newTab.setClosable(true);
if (zQueryTabCount < 2) {
tabPane.getTabs().get(0).setClosable(false);
}
zQueryTabCount++;
}
}
I am getting the NullPointerException at the line selectionModel.select(newTab);
How can I resolve it?
Your selectionModel variable is not initialized nor attached to TabPane.
Use next call instead:
[...]
tabPane.getTabs().add(tabPane.getTabs().size(), newTab);
// should be called after tab has been added to TabPane
tabPane.getSelectionModel().select(newTab);

Resources