Как заставить ключевой слушатель работать с графикой

#java #swing #user-interface #graphics #keylistener

#java #качать #пользовательский интерфейс #графика #Keylistener

Вопрос:

Все в коде работает, за исключением случаев, когда я пытаюсь использовать клавиши для перемещения круга. Я ввел System.out.println(«Работает»), чтобы проверить, работал ли прослушиватель при нажатии любой клавиши, но он вообще не работает. Я сделал то же самое с прослушивателем мыши, и он работал нормально. Я очень новичок в программировании, и я не совсем уверен, что я делаю, поэтому любая помощь была бы отличной.

 import java.awt.*;
import javax.swing.*;
import java.awt.event.*;  // to use listener interfaces
import java.awt.geom.Ellipse2D;

public class WholePanel extends JPanel
{
   private Color foregroundColor, backgroundColor;
   private int currentDiameter, x1, y1;
   private CanvasPanel canvas;
   private JPanel buttonPanel;

   private JRadioButton filledRadio, unfilledRadio;
   private JRadioButton red, green, blue;
   private JRadioButton cyan, yellow, pink;

   private JLabel fill, foreColor, backColor;

   private ButtonGroup circleColor, canvasColor, circleFill;

   public boolean filled = false;

   public WholePanel()
   {
      backgroundColor = Color.CYAN;
      foregroundColor = Color.RED;

      currentDiameter = 100;
      x1 = 200; y1 = 100;

     //INITIATING VARIABLES
      unfilledRadio = new JRadioButton("Unfilled", true);
      filledRadio = new JRadioButton("Filled");
      red = new JRadioButton("Red", true);
      green = new JRadioButton("Green");
      blue = new JRadioButton("Blue");
      cyan = new JRadioButton("Cyan", true);
      yellow = new JRadioButton("Yellow");
      pink = new JRadioButton("Pink");

      fill = new JLabel("Circle Filling");
      foreColor = new JLabel("Foreground Color");
      backColor = new JLabel("Background Color");

     //ORGANIZING THE BUTTONS AND LABELS ON THE BUTTON PANEL
      buttonPanel = new JPanel(new GridLayout(3,4));
          buttonPanel.add(foreColor);
          buttonPanel.add(red);
          buttonPanel.add(green);
          buttonPanel.add(blue);
          buttonPanel.add(backColor);
          buttonPanel.add(cyan);
          buttonPanel.add(yellow);
          buttonPanel.add(pink);
          buttonPanel.add(fill);
          buttonPanel.add(unfilledRadio);
          buttonPanel.add(filledRadio);

     //BUTTON GROUPS ALLOW FOR ONE RADIO BUTTON SELECTION AT A TIME
      circleColor = new ButtonGroup();
          circleColor.add(red);
          circleColor.add(green);
          circleColor.add(blue);
      canvasColor = new ButtonGroup();
          canvasColor.add(cyan);
          canvasColor.add(yellow);
          canvasColor.add(pink);
      circleFill = new ButtonGroup();
          circleFill.add(unfilledRadio);
          circleFill.add(filledRadio);

     //MAKES LISTENER FOR ALL RADIO BUTTONS
      FillListener listener1 = new FillListener();
          unfilledRadio.addActionListener(listener1);
          filledRadio.addActionListener(listener1);
      ColorListener listener2 = new ColorListener();
          red.addActionListener(listener2);
          green.addActionListener(listener2);
          blue.addActionListener(listener2);
          cyan.addActionListener(listener2);
          yellow.addActionListener(listener2);
          pink.addActionListener(listener2);

      canvas = new CanvasPanel();

      JSplitPane sPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, buttonPanel, canvas);

      setLayout(new BorderLayout());
      add(sPane, BorderLayout.CENTER);
    }

   //Its description should be completed
   private class ColorListener implements ActionListener
    {
     public void actionPerformed(ActionEvent event)
      {
        //CHANGES COLOR BASED ON WHICH BUTTON IS SELECTED
         if(event.getSource() == cyan)
         {
             backgroundColor = Color.CYAN;
         }
         else if(event.getSource() == yellow)
         {
             backgroundColor = Color.YELLOW;
         }
         else if(event.getSource() == pink)
         {
             backgroundColor = Color.PINK;
         }
         if(event.getSource() == red)
         {
             foregroundColor = Color.RED;
         }
         else if(event.getSource() == green)
         {
             foregroundColor = Color.GREEN;
         }
         else if(event.getSource() == blue)
         {
             foregroundColor = Color.BLUE;
         }

        //SETS THE COLORS
         setBackground(backgroundColor);
         setForeground(foregroundColor);
      }
    } // end of ColorListener


   //Its description should be completed
   private class FillListener implements ActionListener
    {
     public void actionPerformed(ActionEvent event)
      {
        //CHECKS IF USER WANTS CIRCLE FILLED OR UNFILLED
         if(event.getSource() == unfilledRadio)
         {
             filled = false;
         }
         if(event.getSource() == filledRadio)
         {
             filled = true;
         }
      }
    }

   //CanvasPanel is the panel where a circle is drawn
   private class CanvasPanel extends JPanel
   {
    //Constructor to initialize the canvas panel
    public CanvasPanel( )
      {
        // make this canvas panel listen to keys
        addKeyListener(new DirectionListener());
        // make this canvas panel listen to mouse
        addMouseListener(new PointListener());

        setBackground(backgroundColor);
        setForeground(foregroundColor);

        //This method needs to be called for this panel to listen to keys
        //When panel listens to other things, and go back to listen
        //to keys, this method needs to be called again.
        requestFocus();
      }

     //this method draws all characters pressed by a user so far
     public void paintComponent(Graphics page)
      {
          super.paintComponent(page);
         //SETS THE COLORS BASED ON USERS CHOICE
          setBackground(backgroundColor);
          setForeground(foregroundColor);
         //DRAWS THE CIRCLE
          Graphics2D page2d = (Graphics2D)page;
         //DRAWS IT FILLED OR UNFILLED BASED ON USER CHOICE
          if(filled == true)
          {
              page.setColor(foregroundColor);
              Ellipse2D.Double circle = new  Ellipse2D.Double(x1,y1,currentDiameter,currentDiameter);
                page2d.fill(circle);
              canvas.repaint();
          }
          else if(filled == false)
          {
              page.setColor(foregroundColor);
              Ellipse2D.Double circle = new Ellipse2D.Double(x1,y1,currentDiameter,currentDiameter);
            page2d.draw(circle);
              canvas.repaint();
          }  
      }

     /** This method is overridden to enable keyboard focus */
     public boolean isFocusable()
      {
        return true;
      }

     // listener class to listen to keyboard keys
     private class DirectionListener implements KeyListener 
       {
         public void keyReleased(KeyEvent e) {}
         public void keyTyped(KeyEvent e) {}

         // in case that a key is pressed, the following will be executed.
         public void keyPressed(KeyEvent e)
          {
            //FOCUSES THE LISTENER ON THE KEYBOARD
             canvas.requestFocus();

            //CHANGES THE SIZE/POSITION OF CIRCLE IF KEYS ARE PRESSED
             if(e.getKeyChar() == KeyEvent.VK_UP)
             {
                 y1 = y1 5;
                 canvas.repaint();
             }
             else if(e.getKeyChar() == KeyEvent.VK_DOWN)
             {
                 y1 = y1-5;
                 canvas.repaint();
             }
             else if(e.getKeyChar() == KeyEvent.VK_RIGHT)
             {
                 x1 = x1 5;
                 canvas.repaint();
             }
             else if(e.getKeyChar() == KeyEvent.VK_LEFT)
             {
                 x1 = x1-5;
                 canvas.repaint();
             }
             else if(e.getKeyChar() == 's')
             {
                 if(currentDiameter >= 16)
                    currentDiameter = currentDiameter - 6;
                 canvas.repaint();
             }
             else if(e.getKeyChar() == 'b')
             {
                 currentDiameter = currentDiameter   6;
                 canvas.repaint();
             }
           }
       } // end of DirectionListener


     // listener class that listens to the mouse
     // This class is already completed. No adjustment is needed.
     public class PointListener implements MouseListener
       {
         //in case that a user presses using a mouse,
         //it gains the focus of the keyboard keys
         public void mousePressed (MouseEvent event)
          {
            canvas.requestFocus();
          }

         public void mouseClicked (MouseEvent event) {}
         public void mouseReleased (MouseEvent event) {}
         public void mouseEntered (MouseEvent event) {}
         public void mouseExited (MouseEvent event) {}


       } // end of PointListener

    } // end of Canvas Panel Class

} // end of Whole Panel Class
 

Ответ №1:

Ключевые события отправляются только компоненту с фокусом. По умолчанию панель не фокусируется.

Вам нужно добавить:

 setFocusable(true);
 

в конструкторе вашего класса.

Вы можете запросить фокус только на видимом компоненте, что означает, что оператор requestFocust() в конструкторе ничего не сделает. Кроме того, метод, который нужно использовать requestFocusInWindow() (снова после того, как фрейм виден).

Наконец, вы должны использовать привязки клавиш для прослушивания ключевых событий в компоненте (поэтому вам не нужно беспокоиться о том, что компонент имеет фокус). Дополнительную информацию и примеры см. в разделе Движение с помощью клавиатуры.