Method keeps window from closing

后端 未结 1 1917
情深已故
情深已故 2020-12-11 11:39

Im making a Simon Says game and when I call the randomColorChange() method in the KeyListener pressed() method, it keeps the winow from closing. The randomColorChange() met

相关标签:
1条回答
  • 2020-12-11 12:35

    You're calling Thread.sleep(...) on the Swing event thread which will sleep or lock the entire GUI. Don't do this. Use a Swing Timer instead.

    • Swing Timer Tutorial.

    Also:

    • You should avoid use of KeyListeners with Swing applications but instead should favor Key Bindings.
    • You should paint in the override of a JPanel's paintComponent(Graphics g) method and not directly in the JFrame or in an override of its paint(Graphics g) method. This will help prevent your colors from flickering as they're doing.
    • Always be sure to call the super paint method in your paint override. For example when overriding the JPanel's paintComponent(Graphics g) method, be sure to call the super.paintComponent(g) method at the start, so your component can do its graphic house keeping first.
    • You will want to set your Graphics2D's RenderingHints to allow for anti-aliasing to smooth out your graphics.

    For Example:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Arc2D;
    import java.util.ArrayList;
    import java.util.EnumMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    import javax.swing.*;
    
    /**
     * link: http://stackoverflow.com/questions/21867283/method-keeps-window-from-
     * closing
     * 
     * @author Pete
     * 
     */
    @SuppressWarnings("serial")
    public class SimonPanelTest extends JPanel {
        private static final String PRESSED = "pressed";
        private static final String RELEASED = "released";
        private static final int TIMER_DELAY = 1000;
        private static final int TIME_SLICES = 8;
        private Random random = new Random();
        private SimonPanel simonPanel = new SimonPanel();
    
        public SimonPanelTest() {
            JPanel buttonPanel = new JPanel();
            buttonPanel.add(new JButton(new ShowRandomPatternAction()));
    
            setLayout(new BorderLayout());
            add(simonPanel, BorderLayout.CENTER);
            add(buttonPanel, BorderLayout.SOUTH);
    
            setKeyBindings(simonPanel, KeyEvent.VK_UP, MyColor.GREEN);
            setKeyBindings(simonPanel, KeyEvent.VK_RIGHT, MyColor.YELLOW);
            setKeyBindings(simonPanel, KeyEvent.VK_DOWN, MyColor.BLUE);
            setKeyBindings(simonPanel, KeyEvent.VK_LEFT, MyColor.RED);
    
            simonPanel.addPropertyChangeListener(SimonPanel.MY_COLOR, pce -> {
                System.out.println(pce.getNewValue());
            });
        }
    
        private void setKeyBindings(SimonPanel panel, int keyCode, MyColor myColor) {
            int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
            InputMap inMap = panel.getInputMap(condition);
            ActionMap actMap = panel.getActionMap();
    
            KeyStroke keyPressed = KeyStroke.getKeyStroke(keyCode, 0, false);
            KeyStroke keyReleased = KeyStroke.getKeyStroke(keyCode, 0, true);
    
            inMap.put(keyPressed, myColor.toString() + PRESSED);
            inMap.put(keyReleased, myColor.toString() + RELEASED);
    
            actMap.put(myColor.toString() + PRESSED, new MyKeyAction(panel, myColor, true));
            actMap.put(myColor.toString() + RELEASED, new MyKeyAction(panel, myColor, false));
        }
    
        private class ShowRandomPatternAction extends AbstractAction {
            private static final int MIN_RANDOM_COLORS = 5;
            private static final int MAX_RANDOM_COLORS = 10;
    
            public ShowRandomPatternAction() {
                super("Show Random Pattern");
                putValue(MNEMONIC_KEY, KeyEvent.VK_S);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                List<MyColor> colorList = new ArrayList<MyColor>();
                for (int i = 0; i < random.nextInt(MAX_RANDOM_COLORS - MIN_RANDOM_COLORS)
                        + MIN_RANDOM_COLORS; i++) {
                    int colorIndex = random.nextInt(MyColor.values().length);
                    MyColor myColor = MyColor.values()[colorIndex];
                    colorList.add(myColor);
                }
    
                ActionListener timerListener = new TimerListener(simonPanel, colorList);
                Timer timer = new Timer(TIMER_DELAY / TIME_SLICES, timerListener);
                timer.start();
            }
        }
    
        private class TimerListener implements ActionListener {
            @SuppressWarnings("hiding")
            private SimonPanel simonPanel;
            private int colorListIndex = 0;
            private int sliceCount = 0;
            private List<MyColor> myColorList;
            private int maxCount;
    
            public TimerListener(SimonPanel simonPanel, List<MyColor> myColorList) {
    
                this.simonPanel = simonPanel;
                this.myColorList = myColorList;
                maxCount = myColorList.size();
            }
    
            @Override
            public void actionPerformed(ActionEvent evt) {
                if (colorListIndex == maxCount) {
                    for (MyColor myColor : MyColor.values()) {
                        simonPanel.setMyColorPressed(myColor, false);
                    }
                    ((Timer) evt.getSource()).stop();
                    return;
                }
    
                if (sliceCount == 0) {
                    MyColor myColor = myColorList.get(colorListIndex);
                    simonPanel.setMyColorPressed(myColor, true);
                    sliceCount++;
                } else if (sliceCount < TIME_SLICES - 1) {
                    sliceCount++;
                    return;
                } else if (sliceCount == TIME_SLICES - 1) {
                    sliceCount = 0;
                    MyColor myColor = myColorList.get(colorListIndex);
                    simonPanel.setMyColorPressed(myColor, false);
                    colorListIndex++;
                    return;
                }
            }
        }
    
        private class MyKeyAction extends AbstractAction {
            private SimonPanel panel;
            private MyColor myColor;
            private boolean pressed;
    
            public MyKeyAction(SimonPanel panel, MyColor myColor, boolean pressed) {
                this.panel = panel;
                this.myColor = myColor;
                this.pressed = pressed;
            }
    
            @Override
            public void actionPerformed(ActionEvent evt) {
                panel.setMyColorPressed(myColor, pressed);
            }
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("Simon Game");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new SimonPanelTest());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }
    

    @SuppressWarnings("serial")
    class SimonPanel extends JPanel {
        public static final String MY_COLOR = "my color";
        private static final int PREF_W = 600;
        private static final int PREF_H = PREF_W;
        private static final int ARC_ANGLE = 90;
        private Map<MyColor, MyArc> colorPressedMap = new EnumMap<MyColor, MyArc>(MyColor.class);
        private List<MyArc> myArcs = new ArrayList<>();
    
        public SimonPanel() {
            int i = 0;
            for (MyColor myColor : MyColor.values()) {
                int startAngle = 45 - i * 90;
                Arc2D arc = new Arc2D.Double(0, 0, PREF_W, PREF_H, startAngle, ARC_ANGLE, Arc2D.PIE);
                MyArc myArc = new MyArc(arc, myColor);
                myArcs.add(myArc);
                colorPressedMap.put(myColor, myArc);
                i++;
            }
            addMouseListener(new MyMouse());
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(PREF_W, PREF_H);
        }
    
        public void setMyColorPressed(MyColor myColor, boolean pressed) {
            colorPressedMap.get(myColor).setSelected(pressed);
            repaint();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            for (MyColor myColor : MyColor.values()) {
                colorPressedMap.get(myColor).fill(g2);
            }
        }
    
        private class MyMouse extends MouseAdapter {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() != MouseEvent.BUTTON1) {
                    return;
                }
                for (MyArc myArc : myArcs) {
                    if (myArc.contains(e.getPoint())) {
                        myArc.setSelected(true);
                        firePropertyChange(MY_COLOR, null, myArc.getMyColor());
                        repaint();
                    }
                }
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.getButton() != MouseEvent.BUTTON1) {
                    return;
                }
                for (MyArc myArc : myArcs) {
                    myArc.setSelected(false);
                }
                repaint();
            }
        }
    }
    

    class MyArc {
        private Arc2D arc;
        private MyColor myColor;
        private boolean selected;
    
        public MyArc(Arc2D arc, MyColor myColor) {
            this.arc = arc;
            this.myColor = myColor;
        }
    
        public boolean contains(Point p) {
            return arc.contains(p);
        }
    
        public boolean isSelected() {
            return selected;
        }
    
        public void setSelected(boolean selected) {
            this.selected = selected;
        }
    
        public Arc2D getArc() {
            return arc;
        }
    
        public MyColor getMyColor() {
            return myColor;
        }
    
        public Color getColor() {
            return selected ? myColor.getBrightColor() : myColor.getDarkColor();
        }
    
        public void fill(Graphics2D g2) {
            Color oldColor = g2.getColor();
            g2.setColor(getColor());
            g2.fill(arc);
            g2.setColor(oldColor);
        }
    
    }
    

    enum MyColor {
        GREEN(Color.green.brighter(), Color.green.darker()), 
        YELLOW(Color.yellow.brighter(), Color.yellow.darker()), 
        BLUE(Color.blue.brighter(), Color.blue.darker()), 
        RED(Color.red.brighter(), Color.red.darker());
    
        private MyColor(Color brightColor, Color darkColor) {
            this.brightColor = brightColor;
            this.darkColor = darkColor;
        }
    
        private Color brightColor;
        private Color darkColor;
    
        public Color getBrightColor() {
            return brightColor;
        }
    
        public Color getDarkColor() {
            return darkColor;
        }
    }
    

    Which displays as:

    enter image description here

    0 讨论(0)
提交回复
热议问题