La Mã C câu trả lời ban đầu và được chấp nhận sẽ không AUTO Đóng menu với MenuItem con như một phần của JMenuBar.
Chạy ((JMenu) e.getSource()). DoClick(); trên chuộtNhập mô phỏng nhấp chuột vào một trong các bậc cha mẹ của JMenu nhưng không thể chỉ đơn giản là được thêm vào phương pháp mouseExited vì MouseListener cần phải được gắn vào MenuItems con cũng như các phụ huynh JMenu. (Mà nó không làm trong việc gán thông thường cho MenuBar - chỉ gắn vào các đối tượng JMenu mẹ).
Ngoài ra, một vấn đề phát sinh do cố gắng để người nghe MouseExit kích hoạt phương thức "đóng" CHỈ khi chuột đã rời khỏi toàn bộ cấu trúc Trình đơn (tức là menu thả xuống Trình đơn con).
Dưới đây là một câu trả lời hoàn toàn làm việc lấy từ ứng dụng trực tiếp của tôi:
Con đường tôi giải quyết menu gần trên chuột ra là để chạy một biến boolean "isMouseOut" ở phía trên cùng của các nhà xây dựng để theo dõi và sau đó phân bổ MouseListener theo cách thân thiện hơn với OO để theo dõi nhiều sự kiện MouseIn-MouseOut khi người dùng tương tác với trình đơn. Mà các cuộc gọi một trình đơn riêng biệt phương pháp Delete hành động theo trạng thái của boolean "isMouseOut". Lớp thực hiện MouseListener. Đây là cách mà nó được hoàn thành.
Tạo một ArrayList thêm tất cả các mục menu vào mảng này trước tiên.Cũng giống như vậy:
Font menuFont = new Font("Arial", Font.PLAIN, 12);
JMenuBar menuBar = new JMenuBar();
getContentPane().add(menuBar, BorderLayout.NORTH);
// Array of MenuItems
ArrayList<JMenuItem> aMenuItms = new ArrayList<JMenuItem>();
JMenuItem mntmRefresh = new JMenuItem("Refresh");
JMenuItem mntmNew = new JMenuItem("New");
JMenuItem mntmNormal = new JMenuItem("Normal");
JMenuItem mntmMax = new JMenuItem("Max");
JMenuItem mntmStatus = new JMenuItem("Status");
JMenuItem mntmFeedback = new JMenuItem("Send Feedback");
JMenuItem mntmEtsyTWebsite = new JMenuItem("EtsyT website");
JMenuItem mntmAbout = new JMenuItem("About");
aMenuItms.add(mntmRefresh);
aMenuItms.add(mntmNew);
aMenuItms.add(mntmNormal);
aMenuItms.add(mntmMax);
aMenuItms.add(mntmStatus);
aMenuItms.add(mntmFeedback);
aMenuItms.add(mntmEtsyTWebsite);
aMenuItms.add(mntmAbout);
sau đó lặp qua các ArrayList ở giai đoạn này thêm một MouseListener sử dụng cho() vòng lặp:
for (Component c : aMenuItms) {
if (c instanceof JMenuItem) {
c.addMouseListener(ml);
}
}
Bây giờ đặt cha mẹ JMenu cho thanh menu:
// Now set JMenu parents on MenuBar
final JMenu mnFile = new JMenu("File");
menuBar.add(mnFile).setFont(menuFont);
final JMenu mnView = new JMenu("View");
menuBar.add(mnView).setFont(menuFont);
final JMenu mnHelp = new JMenu("Help");
menuBar.add(mnHelp).setFont(menuFont);
Sau đó, thêm menu thả xuốngMục trẻ em vào cha mẹ của JMenu:
// Now set menuItems as children of JMenu parents
mnFile.add(mntmRefresh).setFont(menuFont);
mnFile.add(mntmNew).setFont(menuFont);
mnView.add(mntmNormal).setFont(menuFont);
mnView.add(mntmMax).setFont(menuFont);
mnHelp.add(mntmStatus).setFont(menuFont);
mnHelp.add(mntmFeedback).setFont(menuFont);
mnHelp.add(mntmEtsyTWebsite).setFont(menuFont);
mnHelp.add(mntmAbout).setFont(menuFont);
Thêm mouseListeners để các bậc phụ huynh JMenu như một bước riêng biệt:
for (Component c : menuBar.getComponents()) {
if (c instanceof JMenu) {
c.addMouseListener(ml);
}
}
Bây giờ các yếu tố MenuItem con tất cả đều có thính giả của riêng họ mà là riêng biệt đến các yếu tố phụ huynh JMenu và thanh menu riêng của mình - Điều quan trọng là xác định loại đối tượng trong quá trình khởi tạo MouseListener() để bạn tự động mở menu khi di chuột qua (trong ví dụ này là cha mẹ JMenu 3x) NHƯNG CSONG tránh lỗi ngoại lệ của trẻ và cho phép nhận dạng sạch mouseOUT của cấu trúc menu mà không cần theo dõi vị trí vị trí chuột là. MouseListener như sau:
MouseListener ml = new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
isMouseOut = true;
timerMenuClear();
}
public void mouseEntered(MouseEvent e) {
isMouseOut = false;
Object eSource = e.getSource();
if(eSource == mnHelp || eSource == mnView || eSource == mnFile){
((JMenu) eSource).doClick();
}
}
};
Ở trên chỉ mô phỏng chuột vào JMenu 'cha mẹ' (3x trong ví dụ này) vì chúng là trình kích hoạt cho menu thả xuống của trình đơn con. Phương pháp timerMenuClear() gọi trên MenuSelectionManager để trống bất cứ điểm selectedpath đã sống tại thời điểm mouseout thực:
public void timerMenuClear(){
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isMouseOut == true){
System.out.println("Timer");
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
};
//Delay timer half a second to ensure real mouseOUT
Timer timer = new Timer(1000, task);
timer.setInitialDelay(500);
timer.setRepeats(false);
timer.start();
}
Nó đã cho tôi một thử nghiệm nhỏ, theo dõi những giá trị nào tôi có thể truy cập vào bên trong JVM quá trình phát triển của nó - nhưng nó hoạt động một điều trị! ngay cả với các menu lồng nhau :) Tôi hy vọng nhiều người thấy ví dụ đầy đủ này rất hữu ích.
Bất kỳ lý do chính đáng nào khiến bạn muốn thực hiện việc này? Tất cả các thanh menu trong tất cả các ứng dụng đều hoạt động như thế – Robin
Trình đơn của tôi có giao diện tùy chỉnh và hành vi này phù hợp với nó một cách tự nhiên hơn. Ngoài ra, tôi tin rằng hành vi này tương tác nhiều hơn cho người dùng. – springcorn