No errors, but crashing - JOptionPane - JavaFX - javafx

I am trying to get a pop-up message when the cake node is clicked on. It prints to the console, but "JOptionPane.showMessageDialog(null,"Test");" crashes the program when I click on the cake (no errors). Any ideas?
class Cake extends Item {
double dx=3,dy=1.6;
Cake(String imageFile, double x, double y) {
super(imageFile, x, y);
}
#Override
public void move() {
this.setX(this.getX()+dx);
if(this.getX()>749 || this.getX()<-20) {
dx=-dx;
}
this.setY(this.getY()+dy);
if(this.getY()>530 || this.getY()<0) {
dy=-dy;
}
}
#Override
public void collision() {
//System.out.println("Cake");
JOptionPane.showMessageDialog(null,"Test");
}
}

Don't use Swing's JOptionPane in a JavaFX application. Use Dialog, or in this case an Alert instead:
#Override
public void collision() {
//System.out.println("Cake");
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Test");
alert.showAndWait();
}

Related

Why is JavaFX WebEngine getLoadWorker looping?

I'm not very sure how to word this question but I'll try. My application runs commands against a website with a click of a button. The issue is during each loop the getLoadWorker increases by 1. In the load worker i set listeners. Here is how it works.
MenuItem executeToHere = new MenuItem("Execute to here");
executeToHere.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
listViewStepItem item = stepListView.getSelectionModel().getSelectedItem();
int selectedIndex = stepList.getSelectionModel().getSelectedIndex();
WebBrowser browser = new WebBrowser(item.getWebView(), item.getListView());
for(int i=0; i < selectedIndex; i++){
listViewStepItem item2 = stepList.getItems().get(i);
if(item2.comboBoxSelected.contains("http://")){
browser.loadURL();
} else if(item2.comboBoxSelected.contains("enter")){
browser.enterText();
} else if(item2.comboBoxSelected.contains("click")){
browser.click();
}
}
browser.setWorker();
}
});
public class WebBrowser{
public WebBrowser(WebView fxmlWebView, WebEngine webEngine){
this.view = fxmlWebView;
this.engine = webEngine;
}
public void loadUrl(String url){
webEngine.load(url);
}
public void enterText(){
System.out.println("ENTER TEXT");
}
public void click(){
System.out.println("click");
}
public void setWorker(){
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>(){
public void changed(ObservableValue ov, State oldState, State newState){
if(newState == javafx.concurrent.Worker.State.SUCCEEDED){
listener = new EventListener(){
public void handleEvent(org.w3c.dom.events.Event evt) {
eventListeners(evt);
}
};
setListenerByTagNames(listener, "a");
}
}
});
}
private void setListenerByTagNames(EventListener listener, String tagName){
Document doc = webEngine.getDocument();
NodeList elements = doc.getElementsByTagName(tagName);
for(int i=0; i < elements.getLength();i++){
((EventTarget) elements.item(i)).addEventListener("click", listener, false);
}
System.out.println("Listening on :"+tagName);
}
}
the first time i run it the output looks like this
ENTER TEXT
click
Listening on : a
second time
ENTER TEXT
click
Listening on : a
Listening on : a
third time
ENTER TEXT
click
Listening on : a
Listening on : a
Listening on : a
I don't see how the worker is increasing but it causes the page to reload/refresh somehow and therefore all the changes to the page DOM is reset.

how to use again an actionEvent in Other textField in javafx

I have a log in form that i was creating and i want the TextField ActionEvent to be used also in the Button but I don't know what to do. In Swing I've seen it that it can recycle an ActionEvent and use it in other like TextField but i don't know how to do it in JavaFX.
Here is a code for my TextField with an ActionEvent
and I want to apply this also to my Button so I dont have to create another method with just the same function but different Component. Thanks
passField.setOnKeyPressed(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent e)
{
if(e.getCode().equals(KeyCode.ENTER))
{
if(admin.equals(userField.getText()) && password.equals(passField.getText()))
{
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else
{
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
}
});
You will have to find a shared Event that both the Button and the TextField support.
In your example you are attaching a handler for a KeyEvent watching for the ENTER key, which is equivalent to an ActionEvent. luckily the Button supports it too.
Create a shared EventHandler:
final EventHandler<ActionEvent> myHandler = e -> {
if(admin.equals(userField.getText()) && password.equals(passField.getText())) {
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else {
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
Which you can now attach twice (or even more often):
button.setOnAction(myHandler);
passField.setOnAction(myHandler);
EDIT
Without lambda expression:
final EventHandler<ActionEvent> myHandler = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e)
{
if(admin.equals(userField.getText()) && password.equals(passField.getText())) {
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else {
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
});

Why i get a NullPointerException when I try to get a fragment from fragmentManager in Android Test?

Hello I'm a newbie in Android testing. I was trying to check if a button is visible in my app during the UI test. I write something:
#RunWith(AndroidJUnit4.class)
public class MainActivityTest {
#Rule
public ActivityTestRule<MainActivity> mRule = new ActivityTestRule<>(MainActivity.class);
#Before
public void setUp() {
}
#Test
public void clickOnProductTest() {
if (isRegisterClosed()) {
openRegister();
}
onView(withText("Food")).perform(click());
onView(withText("Mineral water")).perform(click());
}
private boolean isRegisterClosed() {
MainActivity activity = mRule.getActivity();
FragmentManager fragmentManager = activity.getFragmentManager();
Fragment f = fragmentManager.findFragmentById(R.id.current_order_fragment);
View v = f.getView();
Button b = (Button) v.findViewById(R.id.orderOpenRegister);
return b.getVisibility() == View.VISIBLE;
}
private void openRegister() {
onView(withId(R.id.orderOpenRegister)).perform(click());
}
On line
View v = f.getView(); //in method isRegisterClosed()
I get NullPointerException. It looks like a fragment didn't load. But i don't know why. But when I try to click on button in that Fragment, it works:
onView(withId(R.id.orderOpenRegister)).perform(click());
I want to do something like:
if (buttonIsVisible) {
do smth;
}
else {
do smth else;
}
This button is in current_order_fragment and its ID is orderOpenRegister.
Edit
I find out, that I should add the following line:
fragmentManager.executePendingTransactions();
so my method looks like:
private boolean isRegisterClosed() {
FragmentManager fragmentManager = activity.getFragmentManager();
fragmentManager.executePendingTransactions();
Fragment f = fragmentManager
.findFragmentById(R.id.current_order_fragment);
View v = f.getView();
Button b = (Button) v.findViewById(R.id.orderOpenRegister);
return b.getVisibility() == View.VISIBLE;
}
but if I do that, i need to run this test in UI thread. Does anyone know how to run test on UI thread?
You can run the test in UI thread as below
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.runOnMainSync(new Runnable() {
#Override
public void run() { //your test
}
});

FragmentDialog loose reference to activity

I am using the support library to create dialogs using fragments.
And i Have the following code to show and dismiss the dialogs:
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d("Create", "Create");
setContentView(R.layout.activity_report);
init();
addListeners();
addhandlerListener();
super.onCreate(savedInstanceState);
}
private void showDialog(final Class<?> classs) {
if (classs.equals(AddressValidateProgress.class)) {
addressValidateProgress = AddressValidateProgress.newInstance();
addressValidateProgress.show(getSupportFragmentManager(), null);
Log.d("counter", "+1");
}
if (classs.equals(GPSSearchProgress.class)) {
showDialog(gpsSearchloadId);
}
}
private void dismissDialog(final Class<?> classs) {
if (classs.equals(AddressValidateProgress.class)) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(addressValidateProgress).commitAllowingStateLoss();
addressValidateProgress = null;
Log.d("super", addressValidateProgressId + ":dismissed");
}
if (classs.equals(AddressChooseDialog.class)) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(addressChooseDialog).commitAllowingStateLoss();
addressChooseDialog = null;
}
if (classs.equals(GPSSearchProgress.class)) {
dismissDialog(gpsSearchloadId);
Log.d("super", gpsSearchloadId + ":dismissed");
}
}
If i start the application in portrait mode i can use the dialogs normally, i can even rotate the screen and the dialogs are reconstructed.
The problem is that if i start the application rotate the screen and click the button that open the dialogs i get an exception:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Solution found.
It was caused by a static Handler declared

AspectJ capture button clicked

I want to know whether how to capture the button clicked with AspectJ and get its parameter (eg. button name). I think for having more generalized capturing with AspectJ, it shoudl be used MouseListener so it can capture other UI elements in general!
Example:
In a GUI example I have defined 2 buttons that take some actions
public JButton btn1 = new JButton("Test1");
public JButton btn2 = new JButton("Test2");
btn1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
btn2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
How to capture these buttons with AspectJ, and get their parameters (eg. name)?
It is possible. I have provided two examples. The first that prints out for every JButton that has an ActionListener. The other example only prints out if a specific buttons is clicked.
Prints the text for every JButton clicked with an ActionListener:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent)")
public void buttonPointcut(ActionEvent actionEvent) {}
#Before("buttonPointcut(actionEvent)")
public void beforeButtonPointcut(ActionEvent actionEvent) {
if (actionEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Button name: " + clickedButton.getText());
}
}
Prints the text for a specific JButton:
public static JButton j1;
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean button1Pointcut(ActionEvent actionEvent) {
return (actionEvent.getSource() == j1);
}
#Before("button1Pointcut(actionEvent)")
public void beforeButton1Pointcut(ActionEvent actionEvent) {
// logic before the actionPerformed() method is executed for the j1 button..
}
UPDATED:
You can do this in many different ways. For example add your buttons to the aspect directly. But I prefere to use a enum object between (ButtonManager in this case), so the code does not know about the aspect. And since the ButtonManager is an enum object, it is easy for the aspect to retrieve values from it.
I just tested it with a Swing button class from Oracle and it works. In the Swing class:
b1 = new JButton("Disable middle button", leftButtonIcon);
ButtonManager.addJButton(b1);
AspectJ is extremely powerful when it comes to manipulating classes, but it can not weave advises into specific objects since objects is not created at the time of weaving. So you can only work with objects at runtime and that is why I have added the addJButton(..) method above. That enables the aspect to check the advised button against a list of registered buttons.
The ButtonManager class:
public enum ButtonManager {
;
private static Collection<JButton> buttonList = new LinkedList<JButton>();
public static void addJButton(JButton jButton) {
buttonList.add(jButton);
}
public static Collection<JButton> getButtonList() {
return buttonList;
}
}
Modified pointcut and advice to only print the name of the buttons registered in the ButtonManager:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean buttonListPointcut(ActionEvent actionEvent) {
Collection<JButton> buttonList = ButtonManager.getButtonList();
JButton registeredButton = null;
for (JButton jButton : buttonList) {
if (actionEvent.getSource() == jButton) {
registeredButton = jButton;
}
}
return registeredButton != null;
}
#Before("buttonListPointcut(actionEvent)")
public void beforeButtonListPointcut(ActionEvent actionEvent) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Registered button name: " + clickedButton.getText());
}
UPDATED 2
Okay, I believe I understand what you want. You want to listen to mouse events. That is possible. The downside is that you have to register all your GUI components that you want to listen for clicks with a mouse listener. It is not enough to register the JPanel of the JFrame with a MouseListener. So if you only have registered an ActionListener for your buttons, you also have to add a mouse listener.
I have created a quick solution that works for me. It only shows that it works. I have not tried to make the solution generic with many different GUI objects. But that should be quite easy to refactor in when you have got the basics to work.
In the Swing class:
private class MouseListener extends MouseInputAdapter {
public void mouseClicked(MouseEvent e) {}
}
In the init method of the Swing class:
MouseListener myListener = new MouseListener();
btn1.addMouseListener(myListener);
btn2.addMouseListener(myListener);
In the Aspect class:
#Pointcut("execution(* *.mouseClicked(*)) && args(mouseEvent)")
public void mouseEventPointcut(MouseEvent mouseEvent) {}
#Before("mouseEventPointcut(mouseEvent)")
public void beforeMouseEventPointcut(MouseEvent mouseEvent) {
if (mouseEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) mouseEvent.getSource();
System.out.println("aspectJ --> mouseClicked: " + clickedButton.getText());
}
}
This results in the following output in the console:
aspectJ --> mouseClicked: Test1
I hope it helps!

Resources