2011-01-18 74 views
14

Tôi đã có một ứng dụng Swing với mô hình và chế độ xem. Trong giao diện (GUI) có rất nhiều thành phần, mỗi thành phần ánh xạ tới một số thuộc tính của đối tượng mô hình và hiển thị giá trị của nó.Làm thế nào để tạm thời vô hiệu hóa người nghe sự kiện trong Swing?

Bây giờ, có một số thành phần giao diện người dùng tự động kích hoạt cập nhật một số thuộc tính mô hình khi giá trị của chúng thay đổi trong giao diện người dùng. Điều này đòi hỏi tôi phải tải lại mô hình hoàn chỉnh trong giao diện người dùng. Bằng cách này, tôi đang nhập một vòng lặp cập nhật vô hạn, vì mọi mô hình tải lại trong giao diện người dùng sẽ kích hoạt nạp lại mô hình khác.

Tôi có một cờ cho biết quy trình tải, mà tôi muốn sử dụng để tạm thời chặn thông báo người nghe, trong khi các trường giao diện người dùng đang được đặt từ mô hình. Vì vậy, câu hỏi của tôi là:

Có cách nào để tạm thời vô hiệu hóa một số trình lắng nghe của một số thành phần trong Swing mà không xóa và gắn lại chúng không?

+2

Xem thêm http://stackoverflow.com/questions/4716072 – trashgod

+0

Cảm ơn các liên kết! Trông giống như một vấn đề tương tự và không có giải pháp thỏa đáng cho nó. – MicSim

Trả lời

7

Bạn có thể sử dụng một lớp cơ sở chung cho thính giả của mình và trong đó, có một phương pháp tĩnh để biến người nghe hoặc tắt:

public abstract class BaseMouseListener implements ActionListener{ 

    private static boolean active = true; 
    public static void setActive(boolean active){ 
     BaseMouseListener.active = active; 
    } 

    protected abstract void doPerformAction(ActionEvent e); 

    @Override 
    public final void actionPerformed(ActionEvent e){ 
     if(active){ 
      doPerformAction(e); 
     } 
    } 
} 

thính giả của bạn sẽ phải thực hiện doPerformAction() thay vì actionPerformed().

(Đây sẽ là khủng khiếp trong một kịch bản doanh nghiệp, nhưng trong một mô hình đơn VM như trong Swing, nó sẽ hoạt động tốt)

4

Thông thường tôi sử dụng một lá cờ cho thấy những thay đổi API hoặc người dùng thay đổi. Đối với mỗi người nghe, tôi sẽ kiểm tra cờ và nếu các thay đổi API của nó chỉ trở lại.

2

This question trông giống như một vấn đề tương tự và không có giải pháp thỏa đáng cho nó .

Tôi tìm thấy điều này article hữu ích trong việc kiểm tra nghiêm túc thiết kế của riêng mình.

Có cách nào để tạm thời vô hiệu hóa một số trình lắng nghe của một số thành phần trong Swing mà không xóa và gắn lại chúng không?

Mỗi JComponent duy trì một số EventListenerList, có thể truy cập được vào lớp con của bạn. Nếu cần thiết, bạn luôn có thể hoạt động trực tiếp trên danh sách hoặc xây dựng hành vi mong muốn trong triển khai tùy chỉnh của mình EventListener

4

Trong khi tìm kiếm lưu lượng truy cập, tôi đã tìm thấy câu hỏi này. Tôi nghĩ để thêm ý kiến ​​/ câu trả lời của tôi.

Thực sự là không nên để tạm thời vô hiệu hóa trình xử lý sự kiện trong Swing. Nếu mã của bạn bị hỏng (hoặc có lỗi khác), bạn có thể không thể đưa ứng dụng của bạn trở lại với cuộc sống - trả lời cho người dùng và các sự kiện khác.

Nếu bạn muốn hủy (trả lời nhưng không làm gì) cho sự kiện của người dùng, bạn có thể sử dụng ngăn kính mà chỉ có thể bỏ qua các sự kiện.

Nếu EDT của bạn bận (bạn phải tránh càng nhiều càng tốt) và bạn muốn hủy tác vụ người dùng trong khoảng thời gian đó, bạn vẫn có thể sử dụng kính và xóa nó bằng cách sử dụng invokeLater để xóa bảng sau tất cả các sự kiện đã được trả lời (bị bỏ qua bởi glasspane).

Chi tiết đầy đủ bao gồm SSCE có thể được tìm thấy trong câu hỏi này.

java wait cursor display problem

3

Như đã đề cập ở trên, GlassPane là hữu ích trong lĩnh vực này. Dưới đây là một ví dụ đơn giản:

import javax.swing.JFrame; 
import javax.swing.JButton; 
import javax.swing.SwingWorker; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import java.awt.Color; 
import java.awt.Cursor; 
import java.awt.Graphics; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 


public class GlassPaneExample extends JFrame implements ActionListener { 

private JButton btnDisable; 
private JButton btnTestOne; 
private JButton btnTestTwo; 
private MyGlassPane glass; 
private boolean actionAllowed = true; 

public GlassPaneExample() { 

    // init JFrame graphics 
    setBounds(300, 300, 300, 110); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setLayout(new FlowLayout()); 
    setVisible(true); 

    // init buttons 
    btnTestOne = new JButton("Button one"); 
    add(btnTestOne); 
    btnTestTwo = new JButton("Button two"); 
    add(btnTestTwo); 
    btnDisable = new JButton("Disable ActionListeners for 2 seconds"); 
    add(btnDisable); 

    // create Glass pane 
    glass = new MyGlassPane(); 
    setGlassPane(glass); 

    // add listeners 
    btnTestOne.addActionListener(this); 
    btnTestTwo.addActionListener(this); 
    btnDisable.addActionListener(this); 

} 

public static void main(String[] args) { 
    new GlassPaneExample(); 
} 

@Override 
public void actionPerformed(ActionEvent e) { 
    JButton src = (JButton)e.getSource(); 
    if (src.equals(btnDisable)) { 

     // setting glasspane visibility to 'true' allows it to receive mouse events 
     glass.setVisible(true); 
     setCursor(new Cursor(Cursor.WAIT_CURSOR)); 

     SwingWorker sw = new SwingWorker() { 

      @Override 
      protected Object doInBackground() 
        throws Exception { 
       Thread.sleep(2000); 
       return null; 
      } 

      @Override 
      public void done() { 
       // set cursor and GlassPane back to default state 
       setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 
       glass.setVisible(false); 
       // allow actions to be received again 
       actionAllowed = true; 
      } 
     }; 
     sw.execute(); 

    } else if (actionAllowed) { 
     if (src.equals(btnTestOne)) { 
      JOptionPane.showMessageDialog(this, "BUTTON ONE PRESSED"); 
     } else if (src.equals(btnTestTwo)) { 
      JOptionPane.showMessageDialog(this, "BUTTON TWO PRESSED"); 
     } 
    } 
} 

class MyGlassPane extends JPanel { 

    public MyGlassPane() { 

     setOpaque(false); 

     addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       actionAllowed = false; 
      } 
     }); 
    } 

    //Draw an cross to indicate glasspane visibility 
    public void paintComponent(Graphics g) { 
     g.setColor(Color.red); 
     g.drawLine(0, 0, getWidth(), getHeight()); 
     g.drawLine(getWidth(), 0, 0, getHeight()); 
    } 
} 

}

Các vấn đề liên quan