我的觀點:要使某組件獲得焦點,必須先使組件所在的架構設定為可見,才能有效。
驗證(實踐中遇到的問題):
程式功能:畫圖形元素
程式結構:DoodlePa.java Doodle1.java
先貼出組件類DoodlePa的實現:
DoodlePad.java
import java.awt.Color;<br />import java.awt.Graphics;<br />import java.awt.event.*;<br />import java.util.ArrayList;<br />import javax.swing.JComponent;<br />public class DoodlePad extends JComponent {<br /> private ArrayList<DoodleShape> shapeList = new ArrayList<DoodleShape>();<br /> private int shapeType;<br /> private Color shapeColor;<br /> DoodleShape curShape;</p><p> public DoodlePad() {<br /> shapeType = DoodleShape.TRIANGLE;<br /> shapeColor = Color.black;<br /> addMouseListener(new MouseHandler());<br /> addMouseMotionListener(new MouseMotionHandler());<br /> addKeyListener(new KeyHandler());<br /> }</p><p> public void paint(Graphics g) {<br /> if (curShape != null) {<br /> curShape.draw(g);<br /> }</p><p> for (int i = 0; i < shapeList.size(); i++) {<br /> shapeList.get(i).draw(g);<br /> }<br /> }</p><p> class MouseHandler extends MouseAdapter {<br /> @Override<br /> public void mousePressed(MouseEvent e) {<br /> curShape = new DoodleShape(shapeType, e.getPoint(),<br /> e.getPoint(), shapeColor);<br /> }<br /> @Override<br /> public void mouseReleased(MouseEvent e) {<br /> curShape.setEnd(e.getPoint());<br /> shapeList.add(curShape);<br /> repaint();<br /> }<br /> }</p><p> class MouseMotionHandler extends MouseMotionAdapter {<br /> @Override<br /> public void mouseDragged(MouseEvent e) {</p><p> Graphics g = getGraphics();<br /> g.setXORMode(Color.white);<br /> curShape.draw(g);<br /> curShape.setEnd(e.getPoint());<br /> curShape.draw(g);</p><p> //or: 會閃<br /> //curShape.setEnd(e.getPoint());<br /> //repaint();<br /> }<br /> }</p><p> class KeyHandler extends KeyAdapter {<br /> @Override<br /> public void keyPressed(KeyEvent e) {<br /> switch (e.getKeyCode()) {<br /> case KeyEvent.VK_SPACE:<br /> ++shapeType;<br /> if (shapeType > DoodleShape.OVAL) {<br /> shapeType = DoodleShape.LINE;<br /> }<br /> break;<br /> case KeyEvent.VK_R:<br /> shapeColor = Color.red;<br /> break;<br /> case KeyEvent.VK_B:<br /> shapeColor = Color.black;<br /> break;<br /> default:<br /> break;<br /> }<br /> }<br /> }<br />}
以下為程式主架構(Doodle1類):
import java.awt.event.WindowAdapter;<br />import java.awt.event.WindowEvent;<br />import javax.swing.JFrame;<br />public class Doodle1 extends JFrame {<br /> private DoodlePad pad;<br /> public Doodle1() {<br /> super("Doodle1");</p><p> addWindowListener(new WindowAdapter() {<br /> public void windowClosing(WindowEvent e) {<br /> System.exit(0);<br /> }<br /> });<br /> pad = new DoodlePad();<br /> getContentPane().add(pad);<br /> pad.requestFocusInWindow(); //problem here: cannot get focus<br /> }</p><p> public static void main(String[] args) {<br /> Doodle1 app = new Doodle1();<br /> app.setSize(400, 400);<br /> app.setVisible(true);<br /> }<br />}
發現的問題:pad無法獲得焦點,輸出結果總是為false。畫圖時不響應鍵盤的輸入。
通過在網上搜尋,發現在1991年,老外就遇到同樣的問題了(http://www.codeguru.com/forum/archive/index.php/t-31997.html),跟貼的一個仁兄給出了他的解答:組件所在的Frame必須先設定為可見,requestFocusInWindow才會起作用。在構造器中是不可能獲得焦點的。
於是我對Doodle1進行了改寫,果然可以獲得焦點了:
import java.awt.event.WindowAdapter;<br />import java.awt.event.WindowEvent;<br />import javax.swing.JFrame;<br />public class Doodle1 extends JFrame {<br /> public Doodle1() {<br /> super("Doodle1");</p><p> addWindowListener(new WindowAdapter() {<br /> public void windowClosing(WindowEvent e) {<br /> System.exit(0);<br /> }<br /> });<br /> }</p><p> public static void main(String[] args) {<br /> Doodle1 app = new Doodle1();<br /> DoodlePad pad = new DoodlePad();<br /> app.setSize(400, 400);<br /> app.setVisible(true);<br /> app.getContentPane().add(pad);</p><p> pad.requestFocusInWindow();<br /> }<br />}
結論:我的觀點得到驗證了哇~