2016-01-27 5 views
2

(Примечание: Я знаю о существовании MouseAdapter -класса, но так как я, вероятно, отвергая все методы позже, преимущество его теряется)Как экстернализировать MouseListener?

У меня есть класс MainProgram.java в который я добавляю несколько компонентов. У большинства из них есть Listener (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) { 
    } 
} 
+3

Часть проблемы является использование JLabels как кнопки. JLabels на самом деле не предназначены для кликов, как кнопки. Если вы используете JButton, то в вашем ActionListener вы можете использовать getActionCommand() вместо отображаемого текста компонента. Еще лучше создайте константы для сравнения с вашими командами действий. Если вы сделаете это, я думаю, что головная боль экстернализации ваших слушателей исчезнет. – whiskeyspider

+1

Чтобы продолжить с комментарием @whiskeyspider, в этом разделе показано использование JButton, похожего на JLabel: http://stackoverflow.com/questions/9635126/which-jlabel-has-been-clicked – Berger

+0

Сравнение 'Strings' через '==' очень опасно. Вместо этого используйте 'equals()' (поскольку 'Strings' являются объектами). – tucuxi

ответ

2

уверен, что это не лучший способ, но может быть полезно для вашей проблемы

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

Интересная идея создать новый тип метки, но разве у этой проблемы еще не возникло бы необходимость сравнивать строки? Например, в 'mouseClicked()' -метод, что, если я хочу использовать несколько 'ifs'? Подобно 'if (getText(). Equals (« Статус заказа ») ... это ... if (getText(). Equals (« Проверить отчет ») ... сделать это ...'? – hamena314

+0

@ hamena314, каждый ярлык имеет свой собственный mouselistener, который слушает события щелчка ярлыка, поэтому нет необходимости сравнивать строки. mouseClicked из lbl_orderStatus будет вызываться только при нажатии на lbl_orderStatus. – guleryuz

+0

Я решил использовать этот подход, поскольку он довольно прост (и ленив: вам даже не нужно вводить 'component.addMouseListener' ...). Но в вашем ответе вы написали «это не лучший способ», не могли бы вы уточнить? Я не вижу недостатков этого подхода (пока). – hamena314

0

Вы, вероятно, хотите использовать класс, который расширяет MouseAdapter, так как он может быть использован в качестве MouseListener, в MouseMotionListener, и MouseWheelListener все в один раз (вам просто нужно добавить его как все в компонент). Я не уверен, почему вам нужно получить текст в JLabel, чтобы определить, был ли он нажат. Вы должны создать класс, который расширяет MouseAdapter и делает его исключительно для JLabels, а затем добавляет его в JLabel. Вы должны определить настраиваемый конструктор, если вы хотите, чтобы он использовал JLabel для аргумента, чтобы он автоматически знал, с чем взаимодействует JLabel. Затем вы можете добавить метод, который передает событие в основной класс.

+0

Это решение идет в том же направлении, что и @guleryuz? Тогда что, если у меня есть несколько if-условий. Разве не нужно было бы теперь сравнивать строки? – hamena314

+0

Я ответил до @guleryuz, но его решение, вероятно, тоже сработает. Если вам действительно нужно сравнить строки, моя работа будет работать, поскольку класс, расширяющий MouseAdapter, будет иметь JLabel в нем и может получить из него строку. – ViperLordX

1

Моя рекомендация - написать обработчики inline (анонимного класса), которые пересылают фактическую обработку другой, не анонимной функции. Это даст вам что-то вроде:

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

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

Название метода внешнего не совсем обработчика (doWhateverClickOnOrderStatusRequires) должен захватить задачу, которую он пытается достичь (например, launchRockets); и с помощью этого шаблона вы можете вызвать тот же метод не-обработчика из нескольких обработчиков. Поскольку компилятор проверяет, что вызовы действительны во время компиляции, не существует хрупких строковых констант.

+0

Действительно, это избавит вас от хрупких строк, но разве это не будет в основном классе, и поэтому, если у меня много логического кода (например, несколько if-условий), все еще раздувает мой основной класс? – hamena314

+1

Я склонен писать один класс для пользовательского интерфейса (больше, если части пользовательского интерфейса достаточно сложны) и запускают его из основного класса. Главные классы должны, как правило, выполнять только запуск, но не содержать код для запуска. Методы не-обработчика должны затем вызвать соответствующий код домена-модели, который ничего не должен знать о существовании пользовательского интерфейса: искать разделение модели-представления-контроллера; который часто сводится к контроллеру модели + контроллера, при этом V & C переворачивается в один. – tucuxi

+0

Вам не нужны никакие «if-conditions» при использовании этого шаблона (или, по крайней мере, не решить, какая метка была нажата). Как отметил Гульерюз, если у вас есть куча компонентов, которые являются подклассами X и ведут себя одинаково, напишите подкласс X, который включает в себя поведение, испеченное во избежание дублирования. – tucuxi

Смежные вопросы