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);