简体   繁体   English

循环内的侦听器不允许更改外人布尔标志

[英]Listener inside a loop won't allow to change an outsider boolean flag

Following my previous post here , I wrote a listener : 继我以前的帖子在这里 ,我写了一个监听器:

@Override
public void keyTyped(KeyEvent keyEvent) 
{
    PolygonFiller polyFiller = new PolygonFiller();
    char key = keyEvent.getKeyChar();

    final boolean runForever = true;

    switch(key)
    {
        /**
         *  Fill the polygons 
         */
        case FILL_POLYGON:      
        {
            if (greenLightForFilling == true)
            {

                while (runForever)
                {
                    fillPolygon(polyFiller);
                    KeyListener listener = new KeyListener()
                    {
                        public void keyPressed(KeyEvent keyEvent) 
                        {
                            char keyOther = keyEvent.getKeyChar();
                            if (keyOther == 'F' || keyOther == 'f')
                                // can't use break;
                                runForever = false;
                        }

                        @Override
                        public void keyReleased(KeyEvent arg0) {}

                        @Override
                        public void keyTyped(KeyEvent arg0) {}
                    };
                }
            }
            break;

        }  // end FILL_POLYGON


        case FILL_POLYGON_LOWERCASE:
        {
            if (greenLightForFilling == true)
            {
                fillPolygon(polyFiller);
            }
            break;              

        }

        /**
         *  save all polygons in a .scn file
         */
        case SAVE_POLYGONS :         
        {
            if (greenLightForFilling == true)
            {
                saveWorkspace();
            } 
            break;  
        }   // end SAVE_POLYGONS



        case SAVE_POLYGONS_LOWERCASE:
        {
            if (greenLightForFilling == true)
            {
                saveWorkspace();
            } 
            break;  
        }

        /**
         *  Delete everything & load all polygons from .scn file
         */
        case LOAD_POLYGONS:      
        {
            loadWorkspace();
            break;
        }   

        case LOAD_POLYGONS_LOWERCASE:
        {
            loadWorkspace();
            break;
        }

        default: break;  
    } // end switch


} 

The goal : 目标

  1. break from the loop , when I get a second f or F (I already got one f / F when I entered to loop) . 当我得到第二个fF时中断循环(进入循环时我已经得到一个f / F )。

  2. Do I need to attach the second listener to something ? 我是否需要将第二个侦听器附加到某物上?

But I can't change the runForever to false , since it's written outside . 但是我无法将runForever更改为false,因为它是在外部编写的。

Even if I change it to final , I can't change its value to false either . 即使我将其更改为final ,也不能将其值更改为false

Any way around this ? 可以解决吗?

Note : I already have a key-listener for entering the switch-case!! 注意 :我已经有一个用于输入开关盒的按键监听器!!

EDIT: 编辑:

// Hot-keys hit by the user - used for keyboard listening
private static final char FILL_POLYGON = 'F';
private static final char SAVE_POLYGONS = 'S';
private static final char LOAD_POLYGONS = 'L';
private static final char FILL_POLYGON_LOWERCASE = 'f';
private static final char SAVE_POLYGONS_LOWERCASE = 's';
private static final char LOAD_POLYGONS_LOWERCASE = 'l';


    @Override
    public void keyTyped(KeyEvent keyEvent) 
    {
        PolygonFiller polyFiller = new PolygonFiller();
        char key = keyEvent.getKeyChar();

        final Settable runForever = new Settable();

        switch(key)
        {
            /**
             *  Fill the polygons 
             */
            case FILL_POLYGON:      
            {
                if (greenLightForFilling == true)
                {

                        KeyListener listener = new KeyListener()
                        {
                            public void keyPressed(KeyEvent keyEvent) 
                            {
                                char keyOther = keyEvent.getKeyChar();
                                if (keyOther == 'F' || keyOther == 'f')
                                    runForever.set(false);
                            }

                            @Override
                            public void keyReleased(KeyEvent arg0) {}

                            @Override
                            public void keyTyped(KeyEvent arg0) {}
                        };

                        this.addKeyListener(listener);


                        while (runForever.get())
                        {
                            fillPolygon(polyFiller);
                        }
                }
                break;

            }  // end FILL_POLYGON

...
}

Final variables cannot be changed, but if they represent a mutable object, you can change the content of that object. 最终变量不能更改,但是如果它们表示可变对象,则可以更改该对象的内容。

For example, if you make a Settable class, and use its instance instead of boolean , you could do this: 例如,如果创建一个Settable类,并使用其实例而不是boolean ,则可以这样做:

class Settable {
    private boolean flag;
    public boolean get() {return flag;}
    public boolean set(boolean val) { flag = val; }
}

Now, use a final instance of Settable in your code; 现在,在代码中使用Settablefinal实例; use set(...) instead of the assignment, and get() instead of a direct access: 使用set(...)代替赋值,并使用get()代替直接访问:

final Settable runForever = new Settable();
runForever.set(true);
...
while (runForever.get()) {
    ...
    if (keyOther == 'F' || keyOther == 'f') runForever.set(false);
    ...
}
  • please did you read comment by @kleopatra in your previous post, not good idea to ignore that 请在上一篇文章中阅读@kleopatra的评论吗,不要忽略它

  • not never, not wrong direction, use KeyBindings and with Swing Action instead of KeyListener 永远不会,也不是错误的方向,请使用KeyBindings和Swing Action而不是KeyListener

  • accepted answer by @dasblinkenlight solved nothing in Swing, Swing and Java2D, use KeyBindings and with Swing Action, @dasblinkenlight接受的答案未解决Swing,Swing和Java2D中的任何问题,使用KeyBindings和Swing Action,

for example 例如

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class FullScreen {

    private static final long serialVersionUID = 1L;
    private JButton button = new JButton("Close Meeee");
    private JPanel myPanel = new JPanel();
    private JFrame frame = new JFrame();

    public FullScreen() {
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        myPanel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }
        };
        myPanel.setFocusable(true);
        myPanel.add(button);
        frame.add(myPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //frame.setUndecorated(true);
        frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("ENTER"), "clickENTER");
        frame.getRootPane().getActionMap().put("clickENTER", updateBol());
        frame.pack();
        frame.setVisible(true);
        updateCol().setEnabled(false);
        updateDol().setEnabled(false);
    }

    private Action updateBol() {
        return new AbstractAction("updateBol") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("updateCol is " + updateBol().isEnabled());
                System.out.println("updateBol is " + updateCol().isEnabled());
                System.out.println("updateDol is " + updateDol().isEnabled());
                updateCol().actionPerformed(e);
                updateDol().actionPerformed(e);
            }
        };
    }

    private Action updateCol() {
        return new AbstractAction("updateCol") {
            private static final long serialVersionUID = 1L;
            private Boolean _enabled = false;

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("updateCol is " + updateCol().isEnabled());
                if (updateCol().isEnabled()) {
                } else {
                }
            }

            public void setEnabled(Boolean bol) {
                _enabled = bol;
            }

            @Override
            public boolean isEnabled() {
                return _enabled;
            }
        };
    }

    private Action updateDol() {
        return new AbstractAction("updateDol") {
            private static final long serialVersionUID = 1L;
            private Boolean _enabled = false;

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("updateDol is " + updateDol().isEnabled());
                if (updateCol().isEnabled()) {
                } else {
                }
            }

            public void setEnabled(Boolean bol) {
                _enabled = bol;
            }

            @Override
            public boolean isEnabled() {
                return _enabled;
            }
        };
    }

    public static void main(String[] args) {
        Runnable doRun = new Runnable() {
            @Override
            public void run() {
                FullScreen fullScreen = new FullScreen();
            }
        };
        SwingUtilities.invokeLater(doRun);
    }
}

You can make final array of boolean of size 1 to store your flag. 您可以将大小为1的布尔值的最终数组存储为标志。 Even if array is final, it's elements are not, so you can modify array's elements from anonymous classes. 即使array是final,它的元素也不是,所以您可以从匿名类中修改array的元素。

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

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