简体   繁体   English

按下按钮不重复操作

[英]Action doesn't repeat on button press JavaFX

First of all, please do not mark this question as duplicate & close it without going through the whole problem. 首先,请不要将此问题标记为重复问题并在未解决整个问题的情况下将其关闭。 I have searched for problems similar to mine, but couldn't find any. 我已经搜索了与我相似的问题,但找不到任何问题。 So I request that you kindly direct me to the post that has a similar problem & then close it. 因此,我请您将我引到一个有类似问题的职位上,然后关闭它。

Now the problem. 现在的问题。

I have created a popup window in a JavaFX application. 我已经在JavaFX应用程序中创建了一个弹出窗口。 I have two buttons on the main window/stage, pressing either of which generates a new window/stage. 我在主窗口/舞台上有两个按钮,按下其中任一按钮都会生成一个新窗口/舞台。 However when I close the newly generated popup window and press those buttons on the original window again, it results in JavaFX application thread exception. 但是,当我关闭新生成的弹出窗口并再次按原始窗口上的那些按钮时,将导致JavaFX应用程序线程异常。

Here is the code for the buttons & the action associated with them & it is in the MAIN WINDOW : 这是按钮的代码以及与它们关联的操作,它位于主窗口中

public class FirstScene
{
  //.....usual code.....//
    //Creating the buttons
    Button leftClick = new Button("",lftIcon);
    Button rightClick = new Button("", rghtIcon);

    //Adding ACTION to the buttons
    add.setOnAction(ae->LoginFunc.loginHandler("add"));
    remove.setOnAction(ae ->LoginFunc.loginHandler("remove"));

Here's the code for LoginFunc that handles the event & it is in the popup window 这是处理事件的LoginFunc的代码,它在弹出窗口中

public class LoginFunc 
{
    private static String userID, password, button;
    private static Stage loginStage = new Stage();
    static Button login = new Button("Login");
    Scene addScene, removeScene;

    public static void loginHandler(String bttn)
    {
        button = bttn;
        loginStage.setTitle("Movie Database Login");

        loginStage.setMaxHeight(400);
        loginStage.setMaxWidth(400);

        GridPane loginLayout = new GridPane();
        loginLayout.getChildren().add(login);

        Scene loginScene = new Scene(loginLayout,400,400);

        login.setOnAction(eh -> ButtonClicked(eh));


        loginStage.setScene(loginScene);
        loginStage.initStyle(StageStyle.UTILITY);
        loginStage.initModality(Modality.APPLICATION_MODAL);        

        loginStage.show();

    }

    private static void ButtonClicked (ActionEvent eh)
    {
        if(button == "add")
        {
            FirstScene.mainStage.setTitle("Add Window");
            loginStage.close();

        }
        if(button == "remove")
        {
            FirstScene.mainStage.setTitle("Remove Window");
            loginStage.close();

        }
    }   
}

THE PROBLEM IS , once I close the newly generated popup window & press any of the buttons again, it results in the following exception: 问题是 ,一旦我关闭了新生成的弹出窗口并再次按下任何一个按钮,就会导致以下异常:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Cannot set style once stage has been set visible
    at javafx.stage.Stage.initStyle(Unknown Source)
    at MovieDataBase.LoginFunc.loginHandler(LoginFunc.java:34)
    at MovieDataBase.FirstScene.lambda$0(FirstScene.java:101)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.event.Event.fireEvent(Unknown Source)
    at javafx.scene.Node.fireEvent(Unknown Source)
    at javafx.scene.control.Button.fire(Unknown Source)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.event.Event.fireEvent(Unknown Source)
    at javafx.scene.Scene$MouseHandler.process(Unknown Source)
    at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
    at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
    at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
    at com.sun.glass.ui.View.notifyMouse(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

I want to be able to repeat the same window every time the button is pressed. 我希望每次按下按钮都可以重复相同的窗口。

I'm sorry if this is a very simple problem & a solution already exists, I'm a beginner in Java & what my search resulted in, I couldn't find a single problem that related to mine. 很抱歉,如果这是一个非常简单的问题,并且已经存在解决方案,我是Java的初学者,我的搜索结果是什么,我找不到与我的问题相关的单个问题。

Thank you for your valuable time & input 感谢您的宝贵时间和投入

Your method call to LoginFunc is static and it uses static members of the class. 您对LoginFunc方法调用是静态的,它使用该类的静态成员。 That means that they are initialized and setup when you run through the method for the first time. 这意味着,当您第一次运行该方法时,它们将被初始化和设置。 The second time you call the method, they are already initialized. 第二次调用该方法时,它们已经被初始化。 There are some methods ( initStyle is one of them) that can only be called once in the lifecycle of the object. 有些方法( initStyle是其中的一种)只能在对象的生命周期中调用一次。

However there is an easy solution to that: Remove the static modifiers from LoginFunc and create an instance in the event handler before you call the method loginHandler , however retain a reference to it, so you can pass it on the remove method. 但是,有一个简单的解决方案:在调用方法loginHandler之前,从LoginFunc删除静态修饰符并在事件处理程序中创建实例,但是保留对其的引用,因此可以将其传递给remove方法。 Or even better separate the logic for adding and removing out of LoginFunc as it is not good decision to trigger behavior upon an input parameter. 甚至更好地将用于添加和删除LoginFunc的逻辑分开,因为这不是触发输入参数行为的明智决定。

You can have a factory method that will provide the event handlers for add and remove and use a boolean to decide which event handler the factory method should return. 您可以有一个工厂方法,该方法将提供用于添加和删除的事件处理程序,并使用布尔值确定工厂方法应返回哪个事件处理程序。

public EventHandler<MouseEvent> createButtonClickEventHandler(boolean add) {
  ...
}

Then you can implement the buttons like this: 然后,您可以实现以下按钮:

EventHandler<MouseEvent> addEventHandler = creatButtonClickEventHandler(true);
add.setOnAction(ae->new LoginFunc().loginHandler(addEventHandler));

EventHandler<MouseEvent> removeEventHandler = creatButtonClickEventHandler(false);
remove.setOnAction(ae->new LoginFunc().loginHandler(removeEventHandler));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM