<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Java Swing 事件 > 原文: [http://zetcode.com/tutorials/javaswingtutorial/swingevents/](http://zetcode.com/tutorials/javaswingtutorial/swingevents/) 所有 GUI 應用都是事件驅動的。 應用會對在其生命周期內生成的不同事件類型做出反應。 事件主要由應用的用戶生成,但也可以通過其他方式生成,例如互聯網連接,窗口管理器或計時器。 [Tweet](https://twitter.com/share) 在事件模型中,有三個參與者: * 事件來源 * 事件對象 * 事件監聽器 事件源是狀態更改的對象。 它生成事件。事件對象(事件)將狀態更改封裝在事件源中。事件監聽器是要通知的對象。 事件源對象將處理事件的任務委托給事件監聽器。 Java Swing 工具箱中的事件處理功能非常強大且靈活。 Java 使用事件委托模型。 我們指定發生特定事件時要通知的對象。 ## 事件對象 當應用發生故障時,將創建一個事件對象。 例如,當我們單擊按鈕或從列表中選擇一個項目時。 事件有幾種類型,包括`ActionEvent`,`TextEvent`,`FocusEvent`和`ComponentEvent`。 它們每個都是在特定條件下創建的。 事件對象保存有關已發生事件的信息。 在下一個示例中,我們將更詳細地分析`ActionEvent`。 `EventObjectEx.java` ```java package com.zetcode; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; public class EventObjectEx extends JFrame { private JList mylist; private DefaultListModel model; public EventObjectEx() { initUI(); } private void initUI() { model = new DefaultListModel(); mylist = new JList(model); mylist.setBorder(BorderFactory.createEtchedBorder()); var okBtn = new JButton("OK"); okBtn.addActionListener(new ClickAction()); createLayout(okBtn, mylist); setTitle("Event object"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1], 250, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE) ); gl.setVerticalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1], 150, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE) ); pack(); } private class ClickAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { var formatter = DateTimeFormatter.ISO_TIME; var localTime = Instant.ofEpochMilli(e.getWhen()).atZone( ZoneId.systemDefault()).toLocalTime(); var text = localTime.format(formatter); if (!model.isEmpty()) { model.clear(); } if (e.getID() == ActionEvent.ACTION_PERFORMED) { model.addElement("Event Id: ACTION_PERFORMED"); } model.addElement("Time: " + text); var source = e.getSource().getClass().getName(); model.addElement("Source: " + source); var mod = e.getModifiers(); var buffer = new StringBuffer("Modifiers: "); if ((mod & ActionEvent.ALT_MASK) < 0) { buffer.append("Alt "); } if ((mod & ActionEvent.SHIFT_MASK) < 0) { buffer.append("Shift "); } if ((mod & ActionEvent.META_MASK) < 0) { buffer.append("Meta "); } if ((mod & ActionEvent.CTRL_MASK) < 0) { buffer.append("Ctrl "); } model.addElement(buffer); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new EventObjectEx(); ex.setVisible(true); }); } } ``` 發生動作時,將調用`actionPerformed()`方法。 它的參數是`ActionEvent`對象。 ```java var formatter = DateTimeFormatter.ISO_TIME; var localTime = Instant.ofEpochMilli(e.getWhen()).atZone( ZoneId.systemDefault()).toLocalTime(); var text = localTime.format(formatter); ``` 我們獲得事件發生的時間。 `getWhen()`方法返回以毫秒為單位的時間值。 我們將值轉換為`LocalTime`并使用`DateTimeFormatter`將其格式化為 ISO 時間。 ```java var source = e.getSource().getClass().getName(); model.addElement("Source: " + source); ``` 在這里,我們將事件源的名稱添加到列表中。 在我們的情況下,源是`JButton`。 ```java var mod = e.getModifiers(); ``` 我們得到了修飾鍵。 它是修飾符常量的按位或。 ```java if ((mod & ActionEvent.SHIFT_MASK) > 0) buffer.append("Shift "); ``` 在這里,我們確定是否按下了 `Shift` 鍵。 ![Event Object](https://img.kancloud.cn/01/d8/01d85cd6c2859b86544fe0a5a41a5b53_336x199.jpg) 圖:事件對象 ## 事件處理的實現 我們有幾種方法可以在 Java Swing 中實現事件處理: * 匿名內部類 * 內部類 * 派生類 ### 匿名內部類 我們從一個匿名內部類開始。 `AnonymousInnerClassEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class AnonymousInnerClassEx extends JFrame { public AnonymousInnerClassEx() { initUI(); } private void initUI() { var closeBtn = new JButton("Close"); closeBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { System.exit(0); } }); createLayout(closeBtn); setTitle("Anonymous inner class"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(220) ); gl.setVerticalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addGap(220) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new AnonymousInnerClassEx(); ex.setVisible(true); }); } } ``` 在此示例中,我們有一個按鈕,單擊后會關閉窗口。 ```java var closeBtn = new JButton("Close"); ``` “關閉”按鈕是事件源。 它將生成事件。 ```java closeBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { System.exit(0); } }); ``` 在這里,我們使用按鈕注冊一個動作監聽器。 事件被發送到事件目標。 在我們的案例中,事件目標是`ActionListener`類; 在此代碼中,我們使用匿名內部類。 ```java closeBtn.addActionListener((ActionEvent event) -> { System.exit(0); }); ``` 使用 lambda 表達式重寫的代碼。 ### 內部類 在這里,我們使用內部`ActionListener`類實現示例。 `InnerClassEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class InnerClassEx extends JFrame { public InnerClassEx() { initUI(); } private void initUI() { var closeBtn = new JButton("Close"); var listener = new ButtonCloseListener(); closeBtn.addActionListener(listener); createLayout(closeBtn); setTitle("Inner class example"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(220) ); gl.setVerticalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addGap(220) ); pack(); } private class ButtonCloseListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new InnerClassEx(); ex.setVisible(true); }); } } ``` 我們在面板上有一個關閉按鈕。 它的監聽器在一個命名的內部類中定義。 ```java var listener = new ButtonCloseListener(); closeBtn.addActionListener(listener); ``` 在這里,我們有一個非匿名內部類。 ```java private class ButtonCloseListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } } ``` 在此定義了按鈕監聽器。 ### 實現監聽器的派生類 下面的示例將從組件派生一個類,并在該類內部實現一個動作監聽器。 `DerivedClassEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class DerivedClassEx extends JFrame { public DerivedClassEx() { initUI(); } private void initUI() { var closeBtn = new MyButton("Close"); createLayout(closeBtn); setTitle("Derived class"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(220) ); gl.setVerticalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addGap(220) ); pack(); } private class MyButton extends JButton implements ActionListener { public MyButton(String text) { super.setText(text); addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { System.exit(0); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new DerivedClassEx(); ex.setVisible(true); }); } } ``` 在此示例中,我們創建一個派生的`MyButton`類,該類實現了動作監聽器。 ```java var closeButton = new MyButton("Close"); ``` 在這里,我們創建自定義`MyButton`類。 ```java private class MyButton extends JButton implements ActionListener { public MyButton(String text) { super.setText(text); addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { System.exit(0); } } ``` `MyButton`類是從`JButton`類擴展的。 它實現了`ActionListener`接口。 這樣,事件處理在`MyButton`類中進行管理。 ## 多種來源 監聽器可以插入多個源。 在下一個示例中將對此進行解釋。 `MultipleSourcesEx.java` ```java package com.zetcode; import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; public class MultipleSourcesEx extends JFrame { private JLabel statusBar; public MultipleSourcesEx() { initUI(); } private void initUI() { statusBar = new JLabel("Ready"); statusBar.setBorder(BorderFactory.createEtchedBorder()); var butListener = new ButtonListener(); var closeBtn = new JButton("Close"); closeBtn.addActionListener(butListener); var openBtn = new JButton("Open"); openBtn.addActionListener(butListener); var findBtn = new JButton("Find"); findBtn.addActionListener(butListener); var saveBtn = new JButton("Save"); saveBtn.addActionListener(butListener); createLayout(closeBtn, openBtn, findBtn, saveBtn, statusBar); setTitle("Multiple Sources"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4], GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(250) ); gl.setVerticalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addComponent(arg[2]) .addComponent(arg[3]) .addPreferredGap(RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(arg[4]) ); gl.linkSize(arg[0], arg[1], arg[2], arg[3]); pack(); } private class ButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { var o = (JButton) e.getSource(); var label = o.getText(); statusBar.setText(" " + label + " button clicked"); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new MultipleSourcesEx(); ex.setVisible(true); }); } } ``` 我們創建四個按鈕和一個狀態欄。 單擊按鈕后,狀態欄將顯示一條消息。 ```java var closeBtn = new JButton("Close"); closeBtn.addActionListener(butListener); var openBtn = new JButton("Open"); openBtn.addActionListener(butListener); ... ``` 每個按鈕注冊相同的`ButtonListener`對象。 ```java private class ButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { var o = (JButton) e.getSource(); var label = o.getText(); statusBar.setText(" " + label + " button clicked"); } } ``` 我們確定按下了哪個按鈕,并為狀態欄創建一條消息。 `getSource()`方法返回最初發生事件的對象。 該消息是用`setText()`方法設置的。 ![Multiple sources](https://img.kancloud.cn/57/83/578343120340f5ea261be51344d0c1cb_373x251.jpg) 圖:多個來源 ## 多監聽器 可以為一個事件注冊多個監聽器。 `MultipleListenersEx.java` ```java package com.zetcode; import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.time.Year; import static javax.swing.GroupLayout.Alignment.BASELINE; import static javax.swing.GroupLayout.DEFAULT_SIZE; import static javax.swing.GroupLayout.PREFERRED_SIZE; import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; public class MultipleListenersEx extends JFrame { private JLabel statusBar; private JSpinner spinner; private int count = 0; public MultipleListenersEx() { initUI(); } private void initUI() { statusBar = new JLabel("0"); statusBar.setBorder(BorderFactory.createEtchedBorder()); JButton addBtn = new JButton("+"); addBtn.addActionListener(new ButtonListener1()); addBtn.addActionListener(new ButtonListener2()); int currentYear = Year.now().getValue(); var yearModel = new SpinnerNumberModel(currentYear, currentYear - 100, currentYear + 100, 1); spinner = new JSpinner(yearModel); spinner.setEditor(new JSpinner.NumberEditor(spinner, "#")); createLayout(addBtn, spinner, statusBar); setTitle("Multiple Listeners"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(20) .addComponent(arg[1], DEFAULT_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) .addComponent(arg[2], GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup(BASELINE) .addComponent(arg[0]) .addGap(20) .addComponent(arg[1], DEFAULT_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) .addPreferredGap(RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(arg[2]) ); pack(); } private class ButtonListener1 implements ActionListener { @Override public void actionPerformed(ActionEvent e) { var val = (Integer) spinner.getValue(); spinner.setValue(++val); } } private class ButtonListener2 implements ActionListener { @Override public void actionPerformed(ActionEvent e) { statusBar.setText(Integer.toString(++count)); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new MultipleListenersEx(); ex.setVisible(true); }); } } ``` 在此示例中,我們有一個按鈕,一個微調器和一個狀態欄。 對于一個事件,我們使用兩個按鈕監聽器。 一鍵單擊將為微調器組件增加一年并更新狀態欄。 狀態欄將顯示我們單擊按鈕的次數。 ```java addBtn.addActionListener(new ButtonListener1()); addBtn.addActionListener(new ButtonListener2()); ``` 我們注冊了兩個按鈕監聽器。 ```java var yearModel = new SpinnerNumberModel(currentYear, currentYear - 100, currentYear + 100, 1); spinner = new JSpinner(yearModel); ``` 在這里,我們創建微調器組件。 我們使用微調器的年度模型。 `SpinnerNumberModel`參數是初始值,最小值和最大值以及步長。 ```java spinner.setEditor(new JSpinner.NumberEditor(spinner, "#")); ``` 我們刪除了千位分隔符。 ```java private class ButtonListener1 implements ActionListener { @Override public void actionPerformed(ActionEvent e) { var val = (Integer) spinner.getValue(); spinner.setValue(++val); } } ``` 第一個按鈕監聽器增加微調器組件的值。 ```java private class ButtonListener2 implements ActionListener { @Override public void actionPerformed(ActionEvent e) { statusBar.setText(Integer.toString(++count)); } } ``` 第二個按鈕監聽器增加狀態欄的值。 ![Multiple Listeners](https://img.kancloud.cn/27/10/2710b9c7bb31aba16749258cfaf24525_317x150.jpg) 圖:多個監聽器 ## 刪除監聽器 可以使用`removeActionListener()`方法刪除注冊的監聽器。 下面的示例演示了這一點。 `RemoveListenerEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; public class RemoveListenerEx extends JFrame { private JLabel lbl; private JButton addBtn; private JCheckBox activeBox; private ButtonListener buttonlistener; private int count = 0; public RemoveListenerEx() { initUI(); } private void initUI() { addBtn = new JButton("+"); buttonlistener = new ButtonListener(); activeBox = new JCheckBox("Active listener"); activeBox.addItemListener((ItemEvent event) -> { if (activeBox.isSelected()) { addBtn.addActionListener(buttonlistener); } else { addBtn.removeActionListener(buttonlistener); } }); lbl = new JLabel("0"); createLayout(addBtn, activeBox, lbl); setTitle("Remove listener"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[2])) .addGap(30) .addComponent(arg[1]) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1])) .addGap(30) .addComponent(arg[2]) ); pack(); } private class ButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { lbl.setText(Integer.toString(++count)); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new RemoveListenerEx(); ex.setVisible(true); }); } } ``` 面板上有三個組件:按鈕,復選框和標簽。 通過切換復選框,我們可以添加或刪除按鈕的監聽器。 ```java buttonlistener = new ButtonListener(); ``` 如果要稍后刪除它,我們必須創建一個非匿名監聽器。 ```java activeBox.addItemListener((ItemEvent event) -> { if (activeBox.isSelected()) { addBtn.addActionListener(buttonlistener); } else { addBtn.removeActionListener(buttonlistener); } }); ``` 我們確定是否選中該復選框。 然后,我們添加或刪除監聽器。 ![Remove listener](https://img.kancloud.cn/8c/8a/8c8a2cd718ab684b598a54f775d3ef61_222x119.jpg) 圖:刪除監聽器 ## 移動窗口 以下示例將在屏幕上尋找窗口的位置。 `MovingWindowEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.EventQueue; import java.awt.Font; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; public class MovingWindowEx extends JFrame implements ComponentListener { private JLabel labelx; private JLabel labely; public MovingWindowEx() { initUI(); } private void initUI() { addComponentListener(this); labelx = new JLabel("x: "); labelx.setFont(new Font("Serif", Font.BOLD, 14)); labelx.setBounds(20, 20, 60, 25); labely = new JLabel("y: "); labely.setFont(new Font("Serif", Font.BOLD, 14)); labely.setBounds(20, 45, 60, 25); createLayout(labelx, labely); setTitle("Moving window"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addGap(250) ); gl.setVerticalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addGap(130) ); pack(); } @Override public void componentResized(ComponentEvent e) { } @Override public void componentMoved(ComponentEvent e) { var x = e.getComponent().getX(); var y = e.getComponent().getY(); labelx.setText("x: " + x); labely.setText("y: " + y); } @Override public void componentShown(ComponentEvent e) { } @Override public void componentHidden(ComponentEvent e) { } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new MovingWindowEx(); ex.setVisible(true); }); } } ``` 該示例在面板上顯示當前窗口坐標。 要獲取窗口位置,我們使用`ComponentListener`。 ```java public class MovingWindowExample extends JFrame implements ComponentListener { ``` 主類實現`ComponentListener`接口。 它必須提供所有方法的實現。 ```java @Override public void componentResized(ComponentEvent e) { } @Override public void componentMoved(ComponentEvent e) { var x = e.getComponent().getX(); var y = e.getComponent().getY(); labelx.setText("x: " + x); labely.setText("y: " + y); } @Override public void componentShown(ComponentEvent e) { } @Override public void componentHidden(ComponentEvent e) { } ``` 我們必須創建所有四種方法,即使我們對其中一種方法`componentMoved()`感興趣。 其他三種方法為空。 ```java var x = e.getComponent().getX(); var y = e.getComponent().getY(); ``` 在這里,我們獲得了組件的 x 和 y 位置。 ```java labelx.setText("x: " + x); labely.setText("y: " + y); ``` 檢索到的值設置為標簽。 ![Moving a window](https://img.kancloud.cn/b9/c4/b9c40dc262064b205035da165f9c00bd_264x209.jpg) 圖:移動窗口 ## 適配器 適配器是一種方便的類,它為所有必需的方法提供空的實現。 在前面的代碼示例中,即使沒有使用它們,我們也必須實現`ComponentListener`類的所有四個方法。 為了避免不必要的編碼,我們可以使用適配器。 然后,我們使用實現我們實際需要的那些方法。 沒有用于按鈕單擊事件的適配器,因為只有一種方法可以實現`actionPerformed()`。 在有多種方法可以實現的情況下,可以使用適配器。 下面的示例是使用`ComponentAdapter`重寫前一個示例。 `AdapterEx.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.EventQueue; import java.awt.Font; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; public class AdapterEx extends JFrame { private JLabel labelx; private JLabel labely; public AdapterEx() { initUI(); } private void initUI() { addComponentListener(new MoveAdapter()); labelx = new JLabel("x: "); labelx.setFont(new Font("Serif", Font.BOLD, 14)); labely = new JLabel("y: "); labely.setFont(new Font("Serif", Font.BOLD, 14)); createLayout(labelx, labely); setTitle("Adapter example"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addGap(250) ); gl.setVerticalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addGap(130) ); pack(); } private class MoveAdapter extends ComponentAdapter { @Override public void componentMoved(ComponentEvent e) { var x = e.getComponent().getX(); var y = e.getComponent().getY(); labelx.setText("x: " + x); labely.setText("y: " + y); } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new AdapterEx(); ex.setVisible(true); }); } } ``` 此示例是對上一個示例的重寫。 在這里,我們使用`ComponentAdapter`。 ```java addComponentListener(new MoveAdapter()); ``` 在這里,我們注冊組件監聽器。 ```java private class MoveAdapter extends ComponentAdapter { @Override public void componentMoved(ComponentEvent e) { var x = e.getComponent().getX(); var y = e.getComponent().getY(); labelx.setText("x: " + x); labely.setText("y: " + y); } } ``` 在`MoveAdapter`內部類中,我們定義`componentMoved()`方法。 其他所有方法均保留為空。 Java Swing 教程的這一部分專門用于 Swing 事件。 我們介紹了事件源,事件對象,事件監聽器,創建事件處理器的幾種方法,多個源和監聽器,刪除監聽器以及事件適配器。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看