2017-11-09 4 views
0

Ich habe ein Projekt, dass ein Kreis mit zufälligen x und y-Werten und mit ausgewählten Farben geht, aber wenn der Benutzer die Leertaste gedrückt hat, muss die Farbe des Kreises geändert werden. Mein Kreis bewegt sowohl die x- als auch die y-Koordinate und ich möchte die Farbe des Kreises ändern, wenn ich die Leertaste drücke. Aber es funktioniert nicht, als ich es drückte. Es geht mit seiner ursprünglichen Farbe. Wie kann ich diesen Code richtig machen?Ändern der Farbe mit KeyListener

public class c { 
    private int x,y,r; 
    private Color co; 
    private int Re,G,B; 
    private Random ran; 

    public c() { 
     // TODO Auto-generated constructor stub 
     ran= new Random(); 
     x=100; 
     y=50; 
     r= ran.nextInt(200)+50; 
     Re=ran.nextInt(255); 
     G=ran.nextInt(255); 
     B=ran.nextInt(255); 
     co= new Color(Re,G,B); 
    } 

    public int getRe() { 
     return Re; 
    } 

    public int getG() { 
     return G; 
    } 

    public int getB() { 
     return B; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    public int getR() { 
     return r; 
    } 
    public void setCo(int Re,int G,int B) { 
     co= new Color(Re,G,B); 
    } 
    public Color getCo() { 
     return co; 
    } 

    public Random getRan() { 
     return ran; 
    } 
    public void setX(int x) { 
     this.x=x; 
    } 
    public void setY(int y) { 
    this.y=y; 
    } 

} 



public class Circle extends JFrame implements ActionListener,KeyListener{ 

    private Timer timer; 
    private int x,y,a=5,b=5; 
    private Random rand; 
    c circ = new c(); 
    public Circle() { 
     setLayout(new BorderLayout()); 
     x=circ.getX(); 
     y=circ.getY(); 
     timer=new Timer(50,this); 
     timer.start(); 
     addKeyListener(this); 
     setSize(550,550); 
     setVisible(true); 

    } 

    public void paint(Graphics g) { 
     super.paint(g); 
     g.fillOval(x,y,100,100); 
     g.setColor(circ.getCo()); 
    } 


    public static void main(String[]args) { 
     new Circle(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     moveWithTimer(); 
     repaint();  
    } 

    public void moveWithTimer() { 

     x=x+b; 
     y=y+a; 
    if(x<0) { 
     b=5; 
    } 

    if(x+50>500) { 
     b=-5; 
    } 

    if(y<0){ 
     a=5; 
    } 

    if(y+50>500) { 
     a=-5; 
    } 



    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     // TODO Auto-generated method stub 
     if(e.getKeyCode()==e.VK_SPACE) { 
      circ.setCo(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255)); 


     } 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyTyped(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

} 

Antwort

2

Aber es funktioniert nicht, wenn ich es drückte. Es geht mit seiner ursprünglichen Farbe. Wie kann ich diesen Code richtig machen?

KeyListener ist wankelmütig, besser die Key Bindings API zu verwenden, die das primäre überwindet, den Schwerpunkt im Zusammenhang mit Fragen der KeyListener

Als allgemeine Faustregel gilt: Sie nicht paint von Top-Level-Container wie JFrame außer Kraft setzen sollte, sie sind zusammengesetzte Komponenten und es ist nur ein echtes Durcheinander.

Beginnen Sie stattdessen mit einem JPanel und überschreiben Sie es paintComponent Methode. Es ist generell flexibler. Weitere Informationen finden Sie unter Performing Custom Painting.

Ihr Bewegungscode ist falsch. Sie ordnen die x/y Werte der Kreisklasse einigen anderen Variablen zu. Das Problem hierbei ist, dass das Ändern der Werte dieser Variablen keinen Einfluss auf die Variablen in Ihrer Kreisklasse hat, stattdessen müssen Sie sie zurück zuweisen ...

public void moveWithTimer() { 
    int x = circ.getX(); 
    int y = circ.getY(); 

    x = x + b; 
    y = y + a; 
    if (x < 0) { 
     b = 5; 
    } 

    if (x + 50 > 500) { 
     b = -5; 
    } 

    if (y < 0) { 
     a = 5; 
    } 

    if (y + 50 > 500) { 
     a = -5; 
    } 

    circ.setX(x); 
    circ.setY(y); 

} 

Ihre "Kreis" -Klasse könnte auch ein paar zusätzliche Methoden verwenden. Eins, um die Farbe zu randomisieren (es hat bereits ein Random Objekt, könnte es auch benutzen) und eins, um das Objekt zu malen.

public class Circle { 
    //... 

    public void paint(Graphics2D g2d) { 
     g2d.setColor(co); 
     g2d.fillOval(x, y, r * 2, r * 2); 
    } 

    //... 

    public void randomColor() { 
     setCo(ran.nextInt(255), ran.nextInt(255), ran.nextInt(255)); 
    } 

    //... 

} 

Wenn es mir war, habe ich auch eine move Methode versucht sein, die hinzugefügt werden, aber das ist mir;)

Als runnable Beispiel ...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.util.Random; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Timer timer; 
     private int a = 5, b = 5; 
     private Random rand; 
     private Circle circ = new Circle(); 

     public TestPane() { 
      timer = new Timer(50, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        moveWithTimer(); 
        repaint(); 
       } 
      }); 
      timer.start(); 

      InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap am = getActionMap(); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaced"); 
      am.put("spaced", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        circ.randomColor(); 
        repaint(); 
       } 
      }); 
     } 

     public void moveWithTimer() { 
      int x = circ.getX(); 
      int y = circ.getY(); 

      x = x + b; 
      y = y + a; 
      if (x < 0) { 
       b = 5; 
      } 

      if (x + 50 > 500) { 
       b = -5; 
      } 

      if (y < 0) { 
       a = 5; 
      } 

      if (y + 50 > 500) { 
       a = -5; 
      } 

      circ.setX(x); 
      circ.setY(y); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(500, 500); 
     } 

     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      circ.paint(g2d); 
      g2d.dispose(); 
     } 

    } 

    public class Circle { 

     private int x, y, r; 
     private Color co; 
     private int Re, G, B; 
     private Random ran; 

     public Circle() { 
      // TODO Auto-generated constructor stub 
      ran = new Random(); 
      x = 100; 
      y = 50; 
      r = ran.nextInt(50) + 50; 
      Re = ran.nextInt(255); 
      G = ran.nextInt(255); 
      B = ran.nextInt(255); 
      co = new Color(Re, G, B); 
     } 

     public void paint(Graphics2D g2d) { 
      g2d.setColor(co); 
      g2d.fillOval(x, y, r * 2, r * 2); 
     } 

     public int getRe() { 
      return Re; 
     } 

     public int getG() { 
      return G; 
     } 

     public int getB() { 
      return B; 
     } 

     public int getX() { 
      return x; 
     } 

     public int getY() { 
      return y; 
     } 

     public int getR() { 
      return r; 
     } 

     public void randomColor() { 
      setCo(ran.nextInt(255), ran.nextInt(255), ran.nextInt(255)); 
     } 

     public void setCo(int Re, int G, int B) { 
      co = new Color(Re, G, B); 
     } 

     public Color getCo() { 
      return co; 
     } 

     public Random getRan() { 
      return ran; 
     } 

     public void setX(int x) { 
      this.x = x; 
     } 

     public void setY(int y) { 
      this.y = y; 
     } 

    } 

} 
2

Ich schlage vor, Sie die Farbe der Grafiken innerhalb Farbe (g) Objekt gesetzt sollte vor den Kreis zu malen.

public void paint(Graphics g) { 
    super.paint(g); 
    g.setColor(circ.getCo()); 
    g.fillOval(x,y,100,100); 
} 

Im Allgemeinen sollten Sie die paint() - Methode des JFrame nicht überschreiben. Erstellen Sie stattdessen ein JPanel, fügen Sie es Ihrem Frame hinzu und überschreiben Sie die paintComponent() -Methode des Panels.