1. 程式人生 > >李曉菁201771010114《面向物件程式設計(java)》第十三週學習總結

李曉菁201771010114《面向物件程式設計(java)》第十三週學習總結

理論知識:事件處理

1.事件源:能夠產生事件的物件都可以成為事件源,如文字框,按鈕等。一個事件源是一個能夠註冊監聽器並向監聽器傳送事件物件的物件。

2.事件監聽器:事件監聽器物件接收事件源傳送的通告(事件物件),並對發生的事件作出響應。一個監聽器物件就是一個實現了專門監聽器介面的類例項,該類必須實現介面中的方法,這些方法當事件發生時,被自動執行。

3.事件物件:Java將事件的相關資訊封裝在一個事件物件中,所有的事件物件都最終被派生於Java.util.EventObject類。不同的事件源可以產生不同類別的事件。

2.AWT事件處理機制的概要;

監聽器物件 :是一個實現了特定監聽器介面 ( listener interface )的類例項 。

當事件發生時,事件源將事件物件自動傳遞給所有註冊的監聽器 。

監聽器物件利用事件物件中的資訊決定如何對事件做出響應。

 3.事件源與監聽器之間的關係:

 

4.GUI設計中,程式設計師需要對元件的某種事件進行響應和處理時,必須完成兩個步驟;

(1)定義實現某事件監聽器介面的事件監聽器類,並具體化介面中宣告的事件的處理抽象方法。

(2)為元件註冊實現了規定介面的事件監聽器物件;

5.註冊監聽器方法:eventSourceObject.addEventListener(eventListenerObject)

 6.動態事件:當特定元件動作(點選按鈕)發生時,該元件生成此動作事件。

該事件被傳遞給元件註冊的每一個ActionListener物件,並呼叫監聽器物件的actionPerformed方法以接受這類事件物件。

能夠觸發事件動作的動作,主要包括:

(1)點選按鈕

(2)雙擊一個列表中的選項

(3)選擇選單項

(4)在文字框中輸入回車

7.監聽器介面的實現

監聽器類必須實現與事件源相對應的介面,即必須提供介面中方法的實現。

監聽器介面的方法實現

class MyListener implenments ActionListener

{

    public void actionPerformed(ActionEvent event)

{......}

}

8.命令按鈕Jbutton主要API

(1)建立按鈕物件

Jbutton類常用的一組構造方法;

(1) JButton(String text):建立一個帶文字的按鈕。
(2) JButton(Icon icon) :建立一個帶圖示的按鈕。
(3)JButton(String text, Icon icon) :建立一個帶文字和圖示
的按鈕

(2)按鈕物件的常用方法:

① getLabel( ):返回按鈕的標籤字串;
② setLabel(String s):設定按鈕的標籤為字串s。

9. 用匿名類、lambda表示式簡化程式

例ButtonTest.java中,各按鈕需要同樣的處理:
1) 使用字串構造按鈕物件;
2) 把按鈕新增到面板上;
3) 用對應的顏色構造一個動作監聽器;
4) 註冊動作監聽器

10.介面卡類

當程式使用者試圖關閉一個框架視窗時,Jframe
物件就是WindowEvent的事件源。
⚫ 捕獲視窗事件的監聽器:

WindowListener listener=…..;
frame.addWindowListener(listener);
⚫ 視窗監聽器必須是實現WindowListener介面的
類的一個物件,WindowListener介面中有七個
方法,它們的名字是自解釋的。

11.鑑於程式碼簡化的要求,對於有不止一個方法的AWT監聽器介面都有一個實現了它的所有方法,但卻

不做任何工作的介面卡類。
例:WindowAdapter類。

介面卡類動態地滿足了Java中實現監視器類的技術要求。

⚫ 通過擴充套件介面卡類來實現視窗事件需要的動作

12.註冊事件監聽器

可將一個Terminator物件註冊為事件監聽器:
WindowListener listener=new Terminator();
frame.addWindowListener(listener);
⚫ 只要框架產生一個視窗事件,該事件就會傳遞給
監聽器物件。

建立擴充套件於WindowAdapter的監聽器類是很好的
改進,但還可以進一步將上面語句也可簡化為:
frame.addWindowListener(new Terminator());

13.動作事件

(1)啟用一個命令可以有多種方式,如使用者可以通過
選單、擊鍵或工具欄上的按鈕選擇特定的功能。
(2)在AWT事件模型中,無論是通過哪種方式下達命
令(如:點選按鈕、選單選項、按下鍵盤),其
操作動作都是一樣的。

14.動作介面及其類

Swing包提供了非常實用的機制來封裝命令,並將它
們連線到多個事件源,這就是Action介面。
⚫ 動作物件是一個封裝下列內容的物件:
–命令的說明:一個文字字串和一個可選圖示;
–執行命令所需要的引數。

⚫ Action是一個介面,而不是一個類,實現這個接
口的類必須要實現它的7個方法。
⚫ AbstractAction 類 實 現 了 Action 接 口 中 除
actionPerformed方法之外的所有方法,這個類存
儲了所有名/值對,並管理著屬性變更監聽器。

在 動 作 事 件 處 理 應 用 中 , 可 以 直 接 擴 展
AbstractAction 類 , 並 在 擴 展 類 中 實 現
actionPerformed方法。

15.滑鼠事件

⚫ 滑鼠事件
– MouseEvent
⚫ 滑鼠監聽器介面
– MouseListener
– MouseMotionListener
⚫ 滑鼠監聽器介面卡
– MouseAdapter
– MouseMotionAdapter

使用者點選滑鼠按鈕時,會呼叫三個監聽器方法:
– 滑鼠第一次被按下時呼叫mousePressed方法;
– 滑鼠被釋放時呼叫mouseReleased方法;
– 兩個動作完成之後,呼叫mouseClicked方法。
⚫ 滑鼠在元件上移動時,會呼叫mouseMoved方法。

如果滑鼠在移動的時候還按下了滑鼠,則會呼叫
mouseDragged方法

⚫ 滑鼠事件返回值
– 滑鼠事件的型別是MouseEvent,當發生滑鼠事件時:
MouseEvent類自動建立一個事件物件,以及事件發生
位置的x和y座標,作為事件返回值。

MouseEvent類中的重要方法
– public int getX( );
– public int getY( );
– public Point getPoint( );
– public int getClickCount( );

實驗十三  圖形介面事件處理技術

實驗時間 2018-11-22

1、實驗目的與要求

(1) 掌握事件處理的基本原理,理解其用途;

(2) 掌握AWT事件模型的工作機制;

(3) 掌握事件處理的基本程式設計模型;

(4) 瞭解GUI介面元件觀感設定方法;

(5) 掌握WindowAdapter類、AbstractAction類的用法;

(6) 掌握GUI程式中滑鼠事件處理技術。

2、實驗內容和步驟

實驗1: 匯入第11章示例程式,測試程式並進行程式碼註釋。

測試程式1:

l 在elipse IDE中除錯執行教材443頁-444頁程式11-1,結合程式執行結果理解程式;

l 在事件處理相關程式碼處添加註釋;

lambda表示式簡化程式;

掌握JButton元件的基本API;

l 掌握Java中事件處理的基本程式設計模型。

package button;

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

/**
 * @version 1.34 2015-06-12
 * @author Cay Horstmann
 */
public class ButtonTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(() -> {
         JFrame frame = new ButtonFrame();
         frame.setTitle("ButtonTest");//設定視窗的標題
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);//將視窗設為可見的
      });
   }
}
button
package button;

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

/**
 * A frame with a button panel
 */
public class ButtonFrame extends JFrame
{
   private JPanel buttonPanel;//該類物件屬性
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 200;

   public ButtonFrame()
   {      
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);//通過setsize來更改框架的寬度和高度

      // create buttons
      JButton yellowButton = new JButton("Yellow");
      JButton blueButton = new JButton("Blue");
      JButton redButton = new JButton("Red");//生成三個按鈕物件,string影響的是顯示在button上的文字

      buttonPanel = new JPanel();

      // add buttons to panel
      buttonPanel.add(yellowButton);
      buttonPanel.add(blueButton);
      buttonPanel.add(redButton);//向內容窗格新增三個容器元件

      // add panel to frame
      add(buttonPanel);

      // create button actions
      ColorAction yellowAction = new ColorAction(Color.YELLOW);
      ColorAction blueAction = new ColorAction(Color.BLUE);
      ColorAction redAction = new ColorAction(Color.RED);//生成三個ColorAction(監聽器類)物件

      // associate actions with buttons
      yellowButton.addActionListener(yellowAction);
      blueButton.addActionListener(blueAction);
      redButton.addActionListener(redAction);//將對應的監聽器類和元件之間進行註冊
   }

   /**
    * An action listener that sets the panel's background color.
    */
   private class ColorAction implements ActionListener//實現監聽器介面
   {
      private Color backgroundColor;

      public ColorAction(Color c)
      {
         backgroundColor = c;
      }

      public void actionPerformed(ActionEvent event)
      {
         buttonPanel.setBackground(backgroundColor);//更改背景色
      }
   }
}
buttonFrame

通過內部類方法實現:

package button;

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

/**
 * A frame with a button panel
 */
public class ButtonFrame extends JFrame {
    private JPanel buttonPanel;// 該類物件屬性
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 200;

    public ButtonFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);// 通過setsize來更改框架的寬度和高度

        buttonPanel = new JPanel();

        add(buttonPanel);

        makeButton("yellow", Color.yellow);
        makeButton("blue", Color.blue);
        makeButton("red", Color.red);
        makeButton("green", Color.green);//新增一個新的元件只需要該條語句
    }

    public void makeButton(String name, Color backgroundColor) {
        JButton button = new JButton(name);
        buttonPanel.add(button);
        ColorAction action = new ColorAction(backgroundColor);
        button.addActionListener(action);

    }

    /**
     * An action listener that sets the panel's background color.
     */
    private class ColorAction implements ActionListener// 實現監聽器介面
    {
        private Color backgroundColor;

        public ColorAction(Color c) {
            backgroundColor = c;
        }

        public void actionPerformed(ActionEvent event) {
            buttonPanel.setBackground(backgroundColor);// 更改背景色
        }
    }
}
buttonFrame

通過匿名內部類方法實現:

package button;

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

/**
 * A frame with a button panel
 */
public class ButtonFrame extends JFrame {
    private JPanel buttonPanel;// 該類物件屬性
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 200;

    public ButtonFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);// 通過setsize來更改框架的寬度和高度

        buttonPanel = new JPanel();

        add(buttonPanel);

        makeButton("yellow", Color.yellow);
        makeButton("blue", Color.blue);
        makeButton("red", Color.red);
        makeButton("green", Color.green);// 新增一個新的元件只需要該條語句
    }

    public void makeButton(String name, Color backgroundColor) {
        JButton button = new JButton(name);
        buttonPanel.add(button);
        // ColorAction action = new ColorAction(backgroundColor);
        // button.addActionListener(action);
        button.addActionListener(new ActionListener() {
            // 不能直接使用介面,new後面有一個匿名的類名,後面的ActionListener通過匿名類呼叫
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                buttonPanel.setBackground(backgroundColor);
            }
        });

    }

}
buttonFrame

通過lambda表示式實現:

package button;

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

/**
 * A frame with a button panel
 */
public class ButtonFrame extends JFrame {
    private JPanel buttonPanel;// 該類物件屬性
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 200;

    public ButtonFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);// 通過setsize來更改框架的寬度和高度

        buttonPanel = new JPanel();

        add(buttonPanel);

        makeButton("yellow", Color.yellow);
        makeButton("blue", Color.blue);
        makeButton("red", Color.red);
        makeButton("green", Color.green);// 新增一個新的元件只需要該條語句
    }

    public void makeButton(String name, Color backgroundColor) {
        JButton button = new JButton(name);
        buttonPanel.add(button);
        button.addActionListener((e) -> {
            buttonPanel.setBackground(backgroundColor);
        });

    }

}
buttonFrame

通過以上三種方式實現事件處理的基本程式碼越來越簡化。

測試程式2:

l 在elipse IDE中除錯執行教材449頁程式11-2,結合程式執行結果理解程式;

l 在元件觀感設定程式碼處添加註釋;

l 瞭解GUI程式中觀感的設定方法。

package plaf;

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

/**
 * @version 1.32 2015-06-12
 * @author Cay Horstmann
 */
public class PlafTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(() -> {
         JFrame frame = new PlafFrame();
         frame.setTitle("PlafTest");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      });
   }
}
plaf
package plaf;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * A frame with a button panel for changing look-and-feel
 */
public class PlafFrame extends JFrame
{
   private JPanel buttonPanel;

   public PlafFrame()
   {
      buttonPanel = new JPanel();
//元件觀感設定
      UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();//UIManager 管理當前外觀、可用外觀集合及獲取各種預設值的便捷方法。
      //返回表示當前可用的 LookAndFeel 實現的 LookAndFeelInfo 陣列。應用程式可以使用 LookAndFeelInfo 物件為使用者構造外觀選項的選單,或確定在啟動時要設定哪個外觀 
      for (UIManager.LookAndFeelInfo info : infos)
         makeButton(info.getName(), info.getClassName());
//適合選單或其他展示的形式返回外觀的名稱 ,返回實現此外觀的類名稱
      add(buttonPanel);
      pack();//調整此視窗的大小,以適合其子元件的首選大小和佈局
   }

   /**
    * Makes a button to change the pluggable look-and-feel.
    * @param name the button name
    * @param className the name of the look-and-feel class
    */
   private void makeButton(String name, String className)
   {
      // add button to panel

      JButton button = new JButton(name);
      buttonPanel.add(button);

      // set button action

      button.addActionListener(event -> {
         // button action: switch to the new look-and-feel
         try
         {
            UIManager.setLookAndFeel(className);
            SwingUtilities.updateComponentTreeUI(this);//簡單的外觀更改
            pack();
         }
         catch (Exception e)
         {
            e.printStackTrace();
         }
      });
   }
}
plafFrame

不同的元件有不同的觀感

測試程式3:

l 在elipse IDE中除錯執行教材457頁-458頁程式11-3,結合程式執行結果理解程式;

l 掌握AbstractAction類及其動作物件;

l 掌握GUI程式中按鈕、鍵盤動作對映到動作物件的方法。

package action;

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

/**
 * @version 1.34 2015-06-12
 * @author Cay Horstmann
 */
public class ActionTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(() -> {
         JFrame frame = new ActionFrame();
         frame.setTitle("ActionTest");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      });
   }
}
action
package action;

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

/**
 * A frame with a panel that demonstrates color change actions.
 */
public class ActionFrame extends JFrame
{
   private JPanel buttonPanel;
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 200;

   public ActionFrame()
   {
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

      buttonPanel = new JPanel();

      // define actions
      Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"),//Action 介面提供 ActionListener 介面的一個有用擴充套件,以便若干控制元件訪問相同的功能
            Color.YELLOW);//可以將此介面新增到現有類中,或者用它建立一個介面卡(通常通過子類化 AbstractAction 來實現)。
      Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE);
      Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED);
//根據指定的檔案建立一個 ImageIcon。使用 MediaTracker 預載影象以監檢視像的載入狀態。指定 String 可以是一個檔名或是一條檔案路徑。
      // add buttons for these actions
      buttonPanel.add(new JButton(yellowAction));
      buttonPanel.add(new JButton(blueAction));
      buttonPanel.add(new JButton(redAction));

      // add panel to frame
      add(buttonPanel);//新增元件

      // associate the Y, B, and R keys with names
      InputMap imap = buttonPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);//使用繼承自 JComponent 的元件
      //當接收元件是獲得焦點的元件的祖先或者其本身就是獲得焦點的元件時,應該呼叫命令。 
      imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
      imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue");
      imap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red");
       //InputMap 提供輸入事件(目前只使用 KeyStroke)和 Object 之間的繫結。InputMap 通常與 ActionMap 一起使用,
      //以確定按下鍵時執行一個 Action。InputMap 可以有一個父級,可搜尋它來獲得 InputMap 中未定義的繫結。
      // associate the names with actions
      ActionMap amap = buttonPanel.getActionMap();
      amap.put("panel.yellow", yellowAction);
      amap.put("panel.blue", blueAction);
      amap.put("panel.red", redAction);
      //ActionMap 提供從 Object(稱為鍵 或 Action 名)到 Action 的對映。當按下某一個鍵時,ActionMap 通常與 InputMap 一起使用來定位特定操作。
      //與 InputMap 一同使用時,ActionMap 可以有一個父級,用來搜尋沒有在該 ActionMap 中定義的鍵。
      
   }
   
   public class ColorAction extends AbstractAction
   {
      /**
       * Constructs a color action.
       * @param name the name to show on the button
       * @param icon the icon to display on the button
       * @param c the background color
       */
      public ColorAction(String name, Icon icon, Color c)
      {//putvalue設定與指定鍵關聯的值
         putValue(Action.NAME, name);//用於選單或按鈕的名字
         putValue(Action.SMALL_ICON, icon);//該鍵通常用於選單,同時指定了要使用SMALL-ICON
         putValue(Action.SHORT_DESCRIPTION, "Set panel color to " + name.toLowerCase());//用來儲存動作的簡短 String 描述的鍵,用於工具提示文字。
       //toLowerCase使用預設語言環境的規則將此 String 中的所有字元都轉換為小寫
         putValue("color", c);
      }

      public void actionPerformed(ActionEvent event)//actionListener中的一個方法
      {
         Color c = (Color) getValue("color");
         buttonPanel.setBackground(c);
      }
   }
}
actionFrame

 

測試程式4:

l 在elipse IDE中除錯執行教材462頁程式11-4、11-5,結合程式執行結果理解程式;

l 掌握GUI程式中滑鼠事件處理技術。

package mouse;

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

/**
 * @version 1.34 2015-06-12
 * @author Cay Horstmann
 */
public class MouseTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(() -> {
         JFrame frame = new MouseFrame();
         frame.setTitle("MouseTest");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setVisible(true);
      });
   }
}
mouse
package mouse;

import javax.swing.*;

/**
 * A frame containing a panel for testing mouse operations
 */
public class MouseFrame extends JFrame
{
   public MouseFrame()
   {
      add(new MouseComponent());
      pack();
   }
}
mouseFrame
package mouse;

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

/**
 * A component with mouse operations for adding and removing squares.
 */
public class MouseComponent extends JComponent
{
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 200;

   private static final int SIDELENGTH = 10;
   private ArrayList<Rectangle2D> squares;//Rectangle2D 類描述通過位置 (x,y) 和尺寸 (w x h) 定義的矩形
   private Rectangle2D current; // the square containing the mouse cursor

   public MouseComponent()
   {
      squares = new ArrayList<>();//構造一個空列表
      current = null;

      addMouseListener(new MouseHandler());//新增滑鼠監聽器
      addMouseMotionListener(new MouseMotionHandler());//新增指定的滑鼠移動偵聽器,以接收發自此元件的滑鼠移動事件。
   }

   public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }   
   //如果 preferredSize 已設定為一個非 null 值,則返回該值。如果 UI 委託的 getPreferredSize 方法返回一個非 null 值,則返回該值;
   public void paintComponent(Graphics g)
   {
      Graphics2D g2 = (Graphics2D) g;

      // draw all squares
      for (Rectangle2D r : squares)
         g2.draw(r);//在畫布上畫出一個矩形
   }

   /**
    * Finds the first square containing a point.
    * @param p a point
    * @return the first square that contains p
    */
   public Rectangle2D find(Point2D p)//通過位置 (x,y) 和尺寸 (w x h) 定義的矩形。
   {
      for (Rectangle2D r : squares)
      {
         if (r.contains(p)) return r;//測試指定的 Point2D 是否在 Shape 的邊界內
      }
      return null;
   }

   /**
    * Adds a square to the collection.
    * @param p the center of the square
    */
   public void add(Point2D p)
   {
      double x = p.getX();//返回該圖形的X,Y座標
      double y = p.getY();

      current = new Rectangle2D.Double(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH,
            SIDELENGTH);
      squares.add(current);
      repaint();
   }

   /**
    * Removes a square from the collection.
    * @param s the square to remove
    */
   public void remove(Rectangle2D s)
   {
      if (s == null) return;
      if (s == current) current = null;
      squares.remove(s);
      repaint();
   }

   private class MouseHandler extends MouseAdapter//滑鼠監聽器介面卡
   {
      public void mousePressed(MouseEvent event)//滑鼠按鍵在元件上按下時呼叫mousepressed方法,
      {
         // add a new square if the cursor isn't inside a square
         current = find(event.getPoint());
         if (current == null) add(event.getPoint());//若滑鼠指標不在之前的矩形內,則點選滑鼠時,重新畫一個矩形
      }

      public void mouseClicked(MouseEvent event)//滑鼠按鍵在元件上單擊(按下並釋放)時呼叫。 
      {
         // remove the current square if double clicked
         current = find(event.getPoint());
         if (current != null && event.getClickCount() >= 2) remove(current);//當滑鼠在矩形框內雙擊時,取消該矩形框
      }
   }

   private class MouseMotionHandler implements MouseMotionListener//實現移動監聽器介面
   {
      public void mouseMoved(MouseEvent event)//滑鼠游標移動到元件上但無按鍵按下時呼叫
      {
         // set the mouse cursor to cross hairs if it is inside
         // a rectangle

         if (find(event.getPoint()) == null) setCursor(Cursor.getDefaultCursor());//為指定的游標設定游標影象
         else setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));//十字游標型別。
      }

      public void mouseDragged(MouseEvent event)//滑鼠按鍵在元件上按下並拖動時呼叫。在釋放滑鼠按鍵前,MOUSE_DRAGGED 事件被連續地傳遞到發起該拖動的元件(而不管滑鼠位置是否處於該元件的邊界內)。
      {
         if (current != null)
         {
            int x = event.getX();
            int y = event.getY();
//當發生滑鼠事件時: MouseEvent類自動建立一個事件物件,以及事件發生位置的x和y座標,作為事件返回值。
            // drag the current rectangle to center it at (x, y)
            current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH);
            repaint();//重組此繪件
         }
      }
   }   
}
mousecomponent

當滑鼠點選畫布時,繪製一個矩形,當滑鼠在窗體上移動時,如果滑鼠經過一個小方塊的內部,游標會變成一個十字形;

當雙擊一個小方塊內部時,會擦除該小方塊;實現用滑鼠拖動小方塊。

當滑鼠點選在所有小方塊的畫素之外時,會繪製一個新的小方塊;

實驗2:結對程式設計練習

利用班級名單檔案、文字框和按鈕元件,設計一個有如下介面(圖1)的點名器,要求使用者點選開始按鈕後在文字輸入框隨機顯示2017級網路與資訊安全班同學姓名,如圖2所示,點選停止按鈕後,文字輸入框不再變換同學姓名,此同學則是被點到的同學姓名。

 

1 點名器啟動介面

 

2 點名器點名介面

 

 

package 點名器;

import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileNotFoundException;

import javax.swing.event.*;

public class NameFrame extends JFrame implements ActionListener {//採用多執行緒
    private JLabel jla;//JLabel 物件可以顯示文字、影象或同時顯示二者。
    private JLabel jlb;
    private JButton jba;
    private static boolean flag = true;//定義一個靜態常量並將其值設定為true

    public NameFrame() {
        this.setLayout(null);//類 Container 中的 setLayout,設定 LayoutManager。重寫此方法,從而有條件地將呼叫轉發到 contentPane

        jla = new JLabel("姓名");
        jlb = new JLabel("準備中");
        jba = new JButton("開始");//建立按鈕並將其命名為開始
        this.add(jla);
        this.add(jlb);
        jla.setFont(new Font("Courier", Font.PLAIN, 25));//設定該元件的字型
        jla.setHorizontalAlignment(JLabel.CENTER);//設定標籤內容沿 X 軸的對齊方式並在該區域的中心位置
        jla.setVerticalAlignment(JLabel.CENTER);//設定標籤內容沿 Y 軸的對齊方式並在該區域的中心位置
        jla.setBounds(20, 100, 180, 30);
        jlb.setOpaque(true);//如果為 true,則該元件繪製其邊界內的所有畫素。否則該元件可能不繪製部分或所有畫素,從而允許其底層畫素透視出來。 
        jlb.setBackground(Color.cyan);//設定此元件的背景色。
        jlb.setFont(new Font("Courier", Font.PLAIN, 22));
        jlb.setHorizontalAlignment(JLabel.CENTER);
        jlb.setVerticalAlignment(JLabel.CENTER);
        jlb.setBounds(150, 100, 120, 30);

        this.add(jba);//設定開始按鈕的一些屬性
        jba.setBounds(150, 150, 80, 26);//移動元件並調整其大小。由 x 和 y 指定左上角的新位置,由 width 和 height 指定新的大小。

        jba.addActionListener(this);//將一個 ActionListener 新增到按鈕中

        this.setTitle("點名器");
        this.setBounds(400, 400, 400, 300);
        this.setVisible(true);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);//呼叫任意已註冊 WindowListener 的物件後自動隱藏並釋放該窗體。 
    }

    public void actionPerformed(ActionEvent e) {
        int i = 0;
        String names[] = new String[50];//建立一個數組,該陣列的最大容量為50
        try {
            Scanner in = new Scanner(new File("D:\\studentnamelist.txt"));
            while (in.hasNextLine()) {//如果在此掃描器的輸入中存在另一行,則返回 true。在等待輸入資訊時,此方法可能阻塞。掃描器不執行任何輸入。 
                names[i] = in.nextLine();
                i++;//遍歷名單
            }
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        if (jba.getText() == "開始") {//返回按鈕的文字
            jlb.setBackground(Color.BLUE);//設定元件的背景色
            flag = true;
            new Thread() {//分配新的 Thread 物件。這種構造方法與 Thread(null, null, gname) 具有相同的作用,其中 gname 是一個新生成的名稱。自動生成的名稱的形式為 "Thread-"+n,其中的 n 為整數。
                public void run() {
                    while (NameFrame.flag) {
                        Random r = new Random();
                        int i = r.nextInt(47);
                        jlb.setText(names[i]);//定義此元件將要顯示的單行文字。如果 text 值為 null 或空字串,則什麼也不顯示,此時為name則顯示停止時的名字
                    }
                }
            }.start();//使該執行緒開始執行;Java 虛擬機器呼叫該執行緒的 run 方法。
            jba.setText("停止");
            jba.setBackground(Color.ORANGE);
        } else if (jba.getText() == "停止") {
            flag = false;//當點選按鈕的停止時,返回該按鈕的名字,並且變數flag的布林值為flase
            jba.setText("開始");//按鈕的名字為開始
            jba.setBackground(Color.WHITE);//開始按鈕的顏色為白色
            jlb.setBackground(Color.gray);//未開始點選開始按鈕時,姓名輸入框為灰色
        }
    }

    public static void main(String arguments[]) {
        new NameFrame();
    }
}
nameframe

在點名器的程式設計中,完全沒有思路該如何寫,在學長的例項程式上做了註釋及稍許改動,但對於多執行緒還是沒有理解該如何使用。

 

 實驗總結:通過本週學習,我基本掌握了事件處理的基本原理及AWT事件模型的工作機制;掌握事件處理的基本程式設計模型;並用多種方法簡化程式碼,在老師和學長的教導進一步

理解了匿名內部類,但對於 GUI介面元件觀感設定方法還不太理解; 掌握了AbstractAction類的用法及GUI程式中滑鼠事件處理技術。