Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将鼠标听筒外部化?_Java_Swing_Listener - Fatal编程技术网

Java 如何将鼠标听筒外部化?

Java 如何将鼠标听筒外部化?,java,swing,listener,Java,Swing,Listener,(注意:我知道存在MouseAdapter-类,但由于我以后可能会重写所有方法,因此它的优势就消失了?) 我有一个MainProgram.java类,其中添加了几个组件。他们中的大多数人都有一个监听器(ActionListener,MouseListener,…),这在我的主课上有点拥挤 因此,我试图将这些听众“外部化”到他们自己的课堂中。到目前为止,我在我的主类中使用了内部类,这使得访问变量、组件。。。非常简单和直接 但是对于外部侦听器,我不确定实现它们的最佳方式是什么 例如,当我想知道单击了

注意:我知道存在
MouseAdapter
-类,但由于我以后可能会重写所有方法,因此它的优势就消失了?)

我有一个MainProgram.java类,其中添加了几个组件。他们中的大多数人都有一个监听器(ActionListener,MouseListener,…),这在我的主课上有点拥挤

因此,我试图将这些听众“外部化”到他们自己的课堂中。到目前为止,我在我的主类中使用了内部类,这使得访问变量、组件。。。非常简单和直接

但是对于外部侦听器,我不确定实现它们的最佳方式是什么

例如,当我想知道单击了哪个标签时,我会获取事件,获取事件源,将其转换为
JLabel
,然后获取标签上的文本,与之比较字符串

这是可行的,但似乎很容易出错(如果我在我的主类中更改JLabel文本怎么办?->侦听器中断)并且非常不干净

我试图通过google和StackOverflow搜索更好的方法,但只找到了内部类方法

那么,有没有更好的方法来访问我的组件/外部化我的侦听器

public class MainProgram extends JFrame {
    public MainProgram() {
        super("Landing Page");
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel westPanel = new JPanel();

        JLabel lbl_orderStatus = new JLabel("Order Status");
        JLabel lbl_technicalDocu = new JLabel("Technical Documentation");
        JLabel lbl_checkReport = new JLabel("Check Report");

        MouseListenerBoldFont mouseListenerLabelBoldPlain = new MouseListenerBoldFont();

        lbl_orderStatus.addMouseListener(mouseListenerLabelBoldPlain);
        lbl_technicalDocu.addMouseListener(mouseListenerLabelBoldPlain);
        lbl_checkReport.addMouseListener(mouseListenerLabelBoldPlain);

        westPanel.add(lbl_orderStatus);
        westPanel.add(lbl_technicalDocu);
        westPanel.add(lbl_checkReport);
        add(westPanel);
    }

    public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                MainProgram window = new MainProgram();
                window.setVisible(true);
            } 
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}
MouseListenerBoldFont.java

public class MouseListenerBoldFont implements MouseListener{

    Object lbl_westPanel;

    @Override
    public void mouseClicked(MouseEvent e) {
        if(((JLabel)e.getSource()).getText().equals("Order Status")){
            System.out.println("Order Status clicked");
        };
        if(((JLabel)e.getSource()).getText().equals("Technical Documentation")){
            System.out.println("Technical Documentation clicked");
        };
        if(((JLabel)e.getSource()).getText().equals("Check Report")){
            System.out.println("Check Report clicked");
        };
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        lbl_westPanel = e.getSource();
        ((JComponent) lbl_westPanel).setFont(new Font("tahoma", Font.BOLD, 12));
    }

    @Override
    public void mouseExited(MouseEvent e) {
        lbl_westPanel = e.getSource();
        ((JComponent) lbl_westPanel).setFont(new Font("tahoma", Font.PLAIN, 11));
    }

    @Override
    public void mousePressed(MouseEvent e) {    
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
}

您可能仍然希望使用扩展MouseAdapter的类,因为它可以同时用作MouseListener、MouseMotionListener和MouseWheelListener(您只需将其作为所有这些添加到组件中)。我不知道为什么需要获取JLabel上的文本来检测它是否是已单击的文本。您应该创建一个扩展MouseAdapter的类,使其仅用于JLabel,然后将其添加到该JLabel中。如果希望将JLabel作为参数,则应该定义一个自定义构造函数,以便它自动知道与JLabel交互的是什么。然后,您可以添加一个将事件传递给主类的方法。

我的建议是编写内联(匿名类)处理程序,将实际处理转发给另一个非匿名函数。这将为您提供如下信息:

    JLabel lblOrderStatus = new JLabel("Order Status");
    lblOrderStatus.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent evt) { 
            doWhateverClickOnOrderStatusRequires();
        }
    });

    // much later
    private void doWhateverClickOnOrderStatusRequires() { ... }

外部不完全处理程序方法的名称(
doWhateverClickOnOrderStatusRequires
)应捕获它试图实现的任务(例如,
launchRockets
);使用此模式,您可以从多个处理程序调用相同的不完全处理程序方法。由于编译器将在编译时检查调用是否有效,因此不涉及脆弱的字符串常量

确定这不是最好的方法,但可能对您的问题有用

public class MyLabel extends JLabel implements MouseListener {
    public MyLabel() {
        addMouseListener(this);
    }
    public MyLabel(String txt) {
        super(txt);
        addMouseListener(this);
    }
    public void mouseClicked(MouseEvent e) {
        System.out.println(getText() + " clicked");
    }
    public void mouseEntered(MouseEvent e) {
        setFont(new Font("tahoma", Font.BOLD, 12));
    }
    public void mouseExited(MouseEvent e) {
        setFont(new Font("tahoma", Font.PLAIN, 11));
    }
    public void mousePressed(MouseEvent e) { }
    public void mouseReleased(MouseEvent e) { }
}
然后


部分问题在于将JLabel用作按钮。JLabel的设计并不像按钮那样被点击。如果使用JButton,那么在ActionListener中可以使用getActionCommand()而不是组件的显示文本。更好的做法是创建常量以与动作命令进行比较。如果你这样做,我认为将你的听众外部化的头痛就会消失。为了进一步讨论@wiskyspider的评论,本主题展示了JButton的使用,它看起来像一个JLabel:通过
==
比较
字符串是非常危险的。使用<代码>均衡器()>代码>(因为<代码>字符串是对象).@ TuuCXI:你是对的,我已经改变了我的代码。如果你想让侦听器外部化,考虑每个组件提供一个侦听器,这样你可以为组件(或组件正在运行的操作类型)专门化功能。创建一种新类型的标签是一个有趣的想法,但这是否仍然存在需要比较字符串的问题?例如,在
mouseClicked()
-方法中,如果要使用多个
ifs
,该怎么办?像
if(getText().equals(“订单状态”)…如果(getText().equals(“检查报告”)这样做…这样做…
?@hamena314,每个标签都有自己的mouselistener,用于侦听标签的单击事件,因此无需比较字符串。lbl\u orderStatus的mouseClicked仅在单击lbl\u orderStatus时才会调用。我决定使用这种方法,因为它非常简单(还有lazy:你甚至不需要键入
component.addMouseListener
)。但是在你的回答中,你写了“这不是最好的方法”,你能详细说明一下吗?我还看不出这种方法的缺点。如果你想调用通用逻辑(例如onmouseover)然后,第二个鼠标侦听器可能会被卸载…这可能是一个缺点。另一个小缺点是:当您从(到?
JLabel
扩展时,您不能也从(到?)扩展
MouseAdapter
。相反,您必须实现
MouseListener
及其所有方法,不管您是否需要它们。确实,这消除了脆弱的字符串,但是如果我有很多逻辑代码(例如,几个if条件),这不是仍然在主类中吗仍然膨胀我的主类?我倾向于为UI编写一个类(如果UI的某些部分足够复杂,则会编写更多),并从主类启动。主类通常只执行启动操作,但不包含要启动的代码。不完全的处理程序方法应调用相关的域模型代码,而域模型代码对UI的存在一无所知:查找模型-视图-控制器分离;这通常被简化为模型view+控制器,将V&C合并为一个。使用此模式时,您不需要任何“如果条件”(或者至少不需要确定按下了哪个标签).正如guleryuz所指出的,如果您有一堆子类X的组件,并且它们的行为相同,那么请务必编写一个包含烘焙行为的子类X,以避免任何重复。现在我明白了:您可以“插件”将外部方法放入处理程序中,这样可以保存代码,因为您可以根据需要组合方法和处理程序
    JLabel lbl_orderStatus = new MyLabel("Order Status");
    JLabel lbl_technicalDocu = new MyLabel("Technical Documentation");
    JLabel lbl_checkReport = new MyLabel("Check Report");

//        MouseListenerBoldFont mouseListenerLabelBoldPlain = new MouseListenerBoldFont();
//
//        lbl_orderStatus.addMouseListener(mouseListenerLabelBoldPlain);
//        lbl_technicalDocu.addMouseListener(mouseListenerLabelBoldPlain);
//        lbl_checkReport.addMouseListener(mouseListenerLabelBoldPlain);