2013-08-02 103 views
2

在Liang的第15章Intro to Java Programming(第7版)中,他介紹了一個程序來創建一個(2D)球一個JPanel並通過點擊放大/縮小按鈕將其放大。我已經修改了程序,以便它還可以1)當用戶點擊/選項+點擊時放大/縮小球,2)允許您通過按下按鈕選擇球的顏色,3)允許您移動球用鼠標拖動它可以圈選。有沒有更好的方法來設置JPanel圖形的初始位置?)

最後一次修改是我給了我一段時間的麻煩,因爲我想在開始時將球居中,但是隨後允許用戶用鼠標移動球。我想出的解決方案是讓paintComponent方法只在第一次繪製時將球的x座標和y座標設置爲getWidth()和getHeight()。爲此,我在BallCanvas類中添加了一個paintCount變量,並創建了一個if語句,以便它僅在第一次執行時執行。當我試圖找出最初如何做到這一點時,我看到了其他解決方案,例如:Why can't I access my panel's getWidth() and getHeight() functions?,但我發現我的解決方案更簡單。

所以問題是:我認爲是否認爲不好的編碼風格?專業程序員會嘲笑這個解決方案嗎?還是可以嗎?

更重要的是,有沒有更好的(而且也比較簡單)的方法來做到這一點,不涉及設立櫃臺?

下面是代碼中的相關位:

BallCanvas的開始:

public static class BallCanvas extends JPanel { 

    private int radius = 20; 
    private Color color = Color.BLACK; 
    private int ballX; 
    private int ballY; 
    private int paintCount = 0; 

    ... 

此舉方法(這是爲了響應一個的mouseDragged事件):

public void move(MouseEvent e){ 

     ballX = e.getX() - radius; 
     ballY = e.getY() - radius; 
     repaint(); 

} 

的的paintComponent方法:

protected void paintComponent(Graphics g){ 

     super.paintComponent(g); 
     g.setColor(color); 
     if(paintCount < 1){ 
      ballX = getWidth()/2 - radius; 
      ballY = getHeight()/2 - radius; 
     } 
     g.fillOval(ballX, ballY, 2*radius, 2*radius); 
     paintCount++; 

} 

全部程序:

// Reference: Liang's Intro to Java Programming 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class ControlBall extends JFrame{ 

    private JButton jbtRed = new JButton("Red"); 
    private JButton jbtGreen = new JButton("Green"); 
    private JButton jbtBlue = new JButton("Blue"); 
    private JButton jbtBlack = new JButton("Black"); 
    private BallCanvas canvas = new BallCanvas(); 
    private JMenuBar menuBar = new JMenuBar(); 
    private JMenu menu = new JMenu("Edit"); 
    private JMenuItem miEnlarge = new JMenuItem("Enlarge"); 
    private JMenuItem miShrink = new JMenuItem("Shrink"); 

    public ControlBall(){ 

     menuBar.add(menu); 
     menu.add(miEnlarge); 
     menu.add(miShrink); 

     JPanel panel = new JPanel(); 
     panel.add(jbtRed); 
     panel.add(jbtGreen); 
     panel.add(jbtBlue); 
     panel.add(jbtBlack); 

     this.add(canvas, BorderLayout.CENTER); 
     this.add(panel, BorderLayout.SOUTH); 
     this.add(menuBar, BorderLayout.NORTH); 

     jbtRed.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.setColor(Color.RED); 
      } 
     }); 

     jbtGreen.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.setColor(Color.GREEN); 
      } 
     }); 

     jbtBlue.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.setColor(Color.BLUE); 
      } 
     }); 

     jbtBlack.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.setColor(Color.BLACK); 
      } 
     }); 

     miEnlarge.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.enlarge(); 
      } 
     }); 

     miShrink.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e){ 
       canvas.shrink(); 
      } 
     }); 

     canvas.addMouseListener(new MouseListener() { 
      public void mouseClicked(MouseEvent e){ 
       canvas.changeSize(e); 
      } 
      public void mousePressed(MouseEvent e){} 
      public void mouseReleased(MouseEvent e){} 
      public void mouseEntered(MouseEvent e){} 
      public void mouseExited(MouseEvent e){} 
     }); 

     canvas.addMouseMotionListener(new MouseMotionAdapter() { 

      public void mouseDragged(MouseEvent e) { 

       canvas.move(e); 

      } 
     }); 

    } 

    public static void main(String[] args){ 

     JFrame frame = new ControlBall(); 
     frame.setTitle("ControlBall"); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400, 200); 
     frame.setVisible(true); 

    } 

    public static class BallCanvas extends JPanel { 

     private int radius = 20; 
     private Color color = Color.BLACK; 
     private int ballX; 
     private int ballY; 
     private int paintCount = 0; 

     public BallCanvas(){ 

      System.out.println(getWidth() + " " + getHeight()); 

     } 

     public BallCanvas(int initialRadius){ 

      radius = initialRadius; 

     } 

     public void setColor(Color color){ 

      this.color = color; 
      repaint(); 

     } 

     public void changeSize(MouseEvent e){ 

      int numClicks = e.getClickCount(); 

      if(e.isAltDown()){ 
       if(radius >= 6){ 
        this.radius -= 5*numClicks; 
       } else{ 
        // do nothing 
       } 
      } else{ 

       this.radius += 5*numClicks; 
      } 

      repaint(); 

     } 

     public void enlarge(){ 

      this.radius += 5; 
      repaint(); 

     } 

     public void shrink(){ 

      if(radius >= 10){ 
       this.radius -= 5; 
      } 
      repaint(); 
     } 

     public void move(MouseEvent e){ 

      ballX = e.getX() - radius; 
      ballY = e.getY() - radius; 
      repaint(); 

     } 

     protected void paintComponent(Graphics g){ 

      super.paintComponent(g); 
      g.setColor(color); 
      if(paintCount < 1){ 
       ballX = getWidth()/2 - radius; 
       ballY = getHeight()/2 - radius; 
      } 
      g.fillOval(ballX, ballY, 2*radius, 2*radius); 
      paintCount++; 

     } 

    } 

} 
+2

我不認爲這是不好的編程風格。但是,再次,我不是一個專業人士。這個問題可能會引出基於意見的,而不是基於事實的答案,所以我正在投票結束。 – Jeffrey

+0

也許如果我將焦點改爲「是否有更好的方法可以做到這一點?」這會是一個更合適的問題嗎? –

+0

+1 [sscce](http://sscce.org/) – trashgod

回答

4

幾件事情值得關注:

  • 覆蓋getPreferredSize()建立在面板的初始幾何形狀。

  • 使用該幾何來確定球的初始位置。

  • 調用pack()然後設置位置&的知名度。

  • 使用Action封裝通過菜單和控制共享代碼。

  • 使用適配器一致。

  • 使用initial threads正確。

  • 看到這個Q&A,其中審查從幾個方面相關的例子。

image

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class ControlBall extends JFrame { 

    private JButton jbtRed = new JButton("Red"); 
    private JButton jbtGreen = new JButton("Green"); 
    private JButton jbtBlue = new JButton("Blue"); 
    private JButton jbtBlack = new JButton("Black"); 
    private BallCanvas canvas = new BallCanvas(); 
    private JMenuBar menuBar = new JMenuBar(); 
    private JMenu menu = new JMenu("Edit"); 
    private JMenuItem miEnlarge = new JMenuItem("Enlarge"); 
    private JMenuItem miShrink = new JMenuItem("Shrink"); 

    public ControlBall() { 

     menuBar.add(menu); 
     menu.add(miEnlarge); 
     menu.add(miShrink); 

     JPanel panel = new JPanel(); 
     panel.add(jbtRed); 
     panel.add(jbtGreen); 
     panel.add(jbtBlue); 
     panel.add(jbtBlack); 

     this.add(canvas, BorderLayout.CENTER); 
     this.add(panel, BorderLayout.SOUTH); 
     this.add(menuBar, BorderLayout.NORTH); 

     jbtRed.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.setColor(Color.RED); 
      } 
     }); 

     jbtGreen.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.setColor(Color.GREEN); 
      } 
     }); 

     jbtBlue.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.setColor(Color.BLUE); 
      } 
     }); 

     jbtBlack.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.setColor(Color.BLACK); 
      } 
     }); 

     miEnlarge.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.enlarge(); 
      } 
     }); 

     miShrink.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       canvas.shrink(); 
      } 
     }); 

     canvas.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       canvas.changeSize(e); 
      } 

      @Override 
      public void mouseDragged(MouseEvent e) { 
       canvas.move(e); 
      } 
     }); 
    } 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new ControlBall(); 
       frame.setTitle("ControlBall"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 

    } 

    public static class BallCanvas extends JPanel { 

     private static final int SIZE = 400; 
     private int radius = 20; 
     private Color color = Color.BLACK; 
     private int ballX = SIZE/2 - radius; 
     private int ballY = SIZE/2 - radius; 

     public BallCanvas() { 
      System.out.println(getWidth() + " " + getHeight()); 
     } 

     public BallCanvas(int initialRadius) { 
      radius = initialRadius; 
     } 

     public void setColor(Color color) { 
      this.color = color; 
      repaint(); 
     } 

     public void changeSize(MouseEvent e) { 

      int numClicks = e.getClickCount(); 

      if (e.isAltDown()) { 
       if (radius >= 6) { 
        this.radius -= 5 * numClicks; 
       } else { 
        // do nothing 
       } 
      } else { 

       this.radius += 5 * numClicks; 
      } 

      repaint(); 

     } 

     public void enlarge() { 

      this.radius += 5; 
      repaint(); 

     } 

     public void shrink() { 

      if (radius >= 10) { 
       this.radius -= 5; 
      } 
      repaint(); 
     } 

     public void move(MouseEvent e) { 

      ballX = e.getX() - radius; 
      ballY = e.getY() - radius; 
      repaint(); 

     } 

     @Override 
     protected void paintComponent(Graphics g) { 

      super.paintComponent(g); 
      g.setColor(color); 
      g.fillOval(ballX, ballY, 2 * radius, 2 * radius); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(SIZE, SIZE); 
     } 
    } 
} 
+2

另請參閱此[回覆](http://stackoverflow.com/a/5312702/230513)上的拖動對象;請注意示例的作者未能始終如一地使用適配器。 :-) – trashgod

+0

哇!非常非常詳細的答案,非常感謝你。這將需要一段時間來處理所有事情。如果它不點擊,我可能會打擾你一兩個問題。 –

+1

@ChrisMiddleton:很高興幫助。 – trashgod

相關問題