簡體   English   中英

Java Swing中具有自定義事件的接口后的.class

[英].class after an Interface with Custom Events in Java Swing

我正在學習Java Swing,並且發現了使用MVC和Observer模式的關於Swing的高級代碼。 這對我來說非常困難,我試圖理解它。 我有兩個問題:

  1. DetailListener.class到底是什么? 這是我第一次在接口后使用.class。 我試圖搜索有關“ .class語法”的stackoverflow,但我發現它可以在使用一個類后使用,但是我仍然不了解它在這種情況下的作用。

  2. 方法fireDetailEvent()到底是什么?

提前致謝!

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class App {

    public static void main(String args[]) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                JFrame frame = new MainFrame("Hello world Swing");
                frame.setSize(500, 400);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
                frame.setVisible(true);
            }
        });
    }
}

大型機

import java.awt.BorderLayout;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JTextArea;

public class MainFrame extends JFrame {

    private JTextArea textArea;

    public MainFrame(String title) {

        super(title);

        Container c = getContentPane();

        c.setLayout(new BorderLayout()); 

        textArea = new JTextArea();

        DetailsPanel detailsPanel = new DetailsPanel();

        detailsPanel.addDetailListener(new DetailListener() {

            public void detailEventOccurred(DetailEvent event) {

                String text = event.getText();
                textArea.append(text); 
            }
        });

        c.add(textArea, BorderLayout.CENTER);
        c.add(detailsPanel, BorderLayout.WEST);
    }
}

DetailsPanel

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;

public class DetailsPanel extends JPanel {

    private static final long serialVersionUID = -5115286206114930420L;

    private EventListenerList listenerList = new EventListenerList();

    public DetailsPanel() {

        Dimension size = getPreferredSize();
        size.width = 250;
        setPreferredSize(size); 

        setBorder(BorderFactory.createTitledBorder("Personal details"));

        JLabel nameLabel = new JLabel("Name:");
        JLabel occupationLabel = new JLabel("Occupation:");

        JTextField nameField = new JTextField(10);
        JTextField occupationField = new JTextField(10);

        JButton addBtn = new JButton("Add");

        setLayout(new GridBagLayout());

        GridBagConstraints gc = new GridBagConstraints();

        ////// First column /////
        gc.anchor = GridBagConstraints.LINE_END;


        gc.weightx = 0.5;
        gc.weighty = 0.5;

        gc.gridx = 0;
        gc.gridy = 0;
        add(nameLabel, gc);

        gc.gridy = 1;
        add(occupationLabel, gc);

        ////// Second column /////

        gc.anchor = GridBagConstraints.LINE_START;

        gc.gridx = 1;
        gc.gridy = 0;
        add(nameField, gc);

        gc.gridy = 1;
        add(occupationField, gc);

        //////  Final row /////

        gc.anchor = GridBagConstraints.FIRST_LINE_START;
        gc.weightx = 10;
        gc.weighty = 10;
        gc.gridy = 2;
        add(addBtn, gc); 

        addBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                String name = nameField.getText();
                String occupation = occupationField.getText();

                String text = name + ": " + occupation + "\n";
                System.out.println(text); 

                fireDetailEvent(new DetailEvent(this, text));

            }
        });
    }

    public void fireDetailEvent(DetailEvent event) {

        Object[] listeners = listenerList.getListenerList();

        for (int i = 0; i < listeners.length; i += 2) {

            if (listeners[i] == DetailListener.class) {

                ((DetailListener)listeners[i+1]).detailEventOccurred(event);
            }
        }
    }

    public void addDetailListener(DetailListener listener) {

        listenerList.add(DetailListener.class, listener);
    }

    public void removeDetailListener(DetailListener listener) {

        listenerList.remove(DetailListener.class, listener); 
    }
}

DetailListener

import java.util.EventListener;

public interface DetailListener extends EventListener {

    public void detailEventOccurred(DetailEvent event);
}

DetailEvent

import java.util.EventObject;

public class DetailEvent extends EventObject {

    private String text;

    public DetailEvent(Object source, String text) { 

        super(source);
        this.text = text;
    } 

    public String getText() {

        return text;
    }
}

1)DetailListener.class到底是什么?

API中

類Class的實例表示正在運行的Java應用程序中的類和接口。

這有點令人困惑,所以讓我們看一個例子。 調用DetailListener.class提供其Class表示形式。 在這種特定情況下, DetailListener.class提供了一個Class<DetailListener>因此可以執行以下操作:

Class<DetailListener> cdl = DetailListener.class;

cdl只是另一個變量,類似於frame只是另一個變量。 frame恰好是提供某些方法的JFrame ,而cdl是提供不同方法集的Class<DetailListener>

cdl的類型是Class<DetailListener> ,它表示DetailListener類。

但我仍然不明白在這種情況下它會做什么

考慮以下代碼:

listenerList.add(DetailListener.class, listener);

listenerList的類型為EventListenerList 根據其APIadd(...)方法參數需要一個Class和一個T實例。 在這種情況下,通用T為DetailListener。 到目前為止,聽眾已經注冊,但是它會引出您的下一個問題。

#2 fireDetailEvent()方法到底是什么?

注冊listenerList器后, listenerList會保留一個內部數組,以后可以引用該數組。 該數組同時包含Class和實際的偵聽器實例。 如此調用

Object[] listeners = listenerList.getListenerList();

提供對陣列的訪問。 在這種情況下:

listeners[0] = DetailListener.class
listeners[1] = reference to the anonymous inner class instance created from detailsPanel.addDetailListener(...)

因此, fireDetailEvent(...)的循環保證為2的倍數(如果沒有注冊的偵聽器,則0也適用)。 但是listenerList可以容納任何類型的偵聽器,因此

if (listeners[i] == DetailListener.class) {

使用Class檢查是否相等,以確保能夠安全地進行等級傳遞,以便能夠將DetailEvent傳遞給偵聽器(這是數組中的下一個元素)。 在這種情況下,可以使用== (而不是.equals() ),因為DetailListener.class始終提供相同的Class。

  1. DetailListener.class到底是DetailListener.class

    DetailListener.class是所謂的類文字。 基本上,它是Class類型的常量,表示DetailListener類型。

    您可以在Java什么是類文字中找到更多更好的解釋 及其答案。

  2. 方法fireDetailEvent()到底是什么?

    您的DetailsPanel類使用EventListenerList來處理事件偵聽器並將事件發送給他們。

    EventListenerList中給出的注釋詳細說明了如何使用它。 仔細閱讀本說明,你會認識到,這些方法addDetailListenerremoveDetailListenerfireDetailEvent類的DetailsPanel寫這正好說明如下。

    該方法fireDetailEvent觸發一個DetailEvent所有那些已經由早期注冊自己的聽眾addDetailListener

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM