2009-11-20 3 views
6

Swing (Java 1.6, Windows)이 mouseEntered 및 mouseExited 이벤트를 원하는 방식으로 트리거하지 않는 것 같습니다. JScrollPane에 세로로 쌓아 놓은 JPanel을 여러 개 갖고 자하는 응용 프로그램이 있으며 마우스가 위에있을 때 다른 색상으로 강조 표시해야합니다. 문제는 간단하지만 마우스 휠을 사용하여 스크롤 할 때마다 동작하지 않습니다.마우스 휠 이벤트 이후에 Swing이 mouseEntered/mouseExited를 제대로 트리거하지 않습니까?

문제점 (코드는 아래 참조)을 설명하기 위해 샘플 애플리케이션을 만들었습니다. 아래의 이미지는 "진짜"어플리케이션이 아니라 그 이미지입니다.

패널의 가장자리 위로 마우스 커서를 올리면 올바르게 강조 표시됩니다. 이제 마우스 휠을 사용하여 아래로 스크롤하면 커서가 상자 B 위에 있고 마우스 오른쪽 단추가 흰색으로 표시되고 B가 빨간색이되도록 적절한 mouseEntered/mouseExited 이벤트가 트리거 될 것으로 예상됩니다. 일하지 않는 것 같습니다 그러나

alt text http://perp.se/so/2.png

alt text http://perp.se/so/1.png

.

다른 마우스 이벤트를 "1 픽셀 이동", "버튼 클릭"또는 "다른 단계 스크롤"으로하면 B가 강조 표시됩니다. 이것을 알면 아마 해킹 된 방식으로 해결할 수 있지만, 적절한 해결책이 있다면 오히려하지 않을 것입니다.

기본적으로 내가 궁금해하는 점은 이것이 Swing에서 버그로 간주되는지 아니면 그냥 잘못하고있는 것인가?

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.SwingConstants; 
import javax.swing.SwingUtilities; 

public class ScrollTest extends JFrame { 

    public static class LetterPanel extends JPanel { 

     private static final Font BIG_FONT = new Font(Font.MONOSPACED, Font.BOLD, 24); 

     public LetterPanel(String text) { 
      setBackground(Color.WHITE); 
      setBorder(BorderFactory.createLineBorder(Color.BLACK)); 

      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mouseEntered(MouseEvent e) { 
        setBackground(Color.RED); 
       } 

       @Override 
       public void mouseExited(MouseEvent e) { 
        setBackground(Color.WHITE); 
       } 
      }); 

      setLayout(new GridLayout(1, 1)); 
      setPreferredSize(new Dimension(-1, 50)); 

      JLabel label = new JLabel(text, SwingConstants.CENTER); 
      label.setFont(BIG_FONT); 
      add(label); 
     } 
    } 

    public ScrollTest() { 
     setLayout(new GridLayout(1, 1)); 
     setSize(400, 400); 

     JPanel base = new JPanel(); 

     JScrollPane jsp = new JScrollPane(base); 
     jsp.getVerticalScrollBar().setUnitIncrement(16); 
     add(jsp); 

     base.setLayout(new GridBagLayout()); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridx = 0; 
     gbc.gridy = 0; 
     gbc.gridheight = 1; 
     gbc.gridwidth = 1; 
     gbc.fill = GridBagConstraints.HORIZONTAL; 
     gbc.insets = new Insets(0, 0, 10, 0); 
     gbc.weightx = 1.0; 

     for (char c = 'A'; c <= 'Z'; c++) { 
      base.add(new LetterPanel(String.valueOf(c)), gbc); 
      gbc.gridy++; 
     } 
    } 

    public static void main(String[] args) { 
     final JFrame f = new ScrollTest(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       f.setVisible(true); 
      } 
     }); 
    } 
}
+1

이유가 있습니다. 그것 없이는 SO가 스팸 게시물을 꽤 많이 가지고 있었을 것입니다. 이미지를 추가하고 규칙이 "지연됨"에 대한 의견을 삭제했습니다. –

+0

이러한 말 외에, 당신은 훌륭한 질문을 해왔다 : 선명한 이미지, 코드 스 니펫. 나는 스윙 전문가는 아니지만 나중에 (이미 답변하지 않은 경우) 나중에 살펴볼 것입니다. +1 –

+0

편집 해 주셔서 감사합니다.그것은 처음으로 문제와 싸우고, 질문을 쓰고, 스 니펫을 작성하고, 좋은 스크린 샷을 찍고, 서버에 업로드 한 다음, 내가 새로운 사용자이기 때문에 내 게시물에 SO barf를 갖는 것에 조금 실망했습니다. 기분이 나아 졌어. :-) – perp

답변

5

이것은 Tooltips and Scrollpanes에 설명 된 것과 비슷한 문제인 것처럼 보입니다. 즉, 마우스 자체가 움직이지 않고 뷰포트가 움직이기 때문에 마우스 이벤트가 생성되지 않습니다. 정확한 솔루션 마우스를 위치에서 구성 요소를 추적하려면 AdjustmentListener를 사용하여 다른 확실하지 않습니다. 변경 사항이있을 때마다 mouseExited 이벤트를 이전 패널에 발생시키고 mouseEntered 이벤트를 새 패널에 발생시킬 수 있습니다.

3

스크롤을 완전히 끝내지 않은 경우에만 코드를 안정적으로 재현 할 수있는 코드를 얻을 수 있습니다. 내 마우스에는 적어도 마우스 휠이 스크롤을 끝낼 때의 "잡기"가 있습니다. 매우 느리게 스크롤하면 움직일 수 있지만 마우스 휠이 "잡기"에 도달 할 때까지 강조 표시가 변경되지 않습니다.

이렇게하면 마우스 입력 메시지가 이전 패널에서 수신됩니다 (보고있는 것과 동일한 동작).

마우스 휠을 스크롤하면 "catch"할 수있을만큼 마우스를 스크롤하지 않으면 마우스를 스크롤하고 실제로 나가는 이벤트/이벤트가 실제로 표시되지 않습니다. Windows가 "catch"가 발생할 때까지 Java에 메시지를 보내지 않을 수 있습니다. 내 테스트에서 보입니다.

MouseWheelListener 인터페이스와 MouseInfo 클래스를 살펴볼 수 있습니다. 휠 운동을 감지하고 MouseInfo.getPointerInfo(). getLocation()을 사용하여 현재 위치를 파악한 다음 어떤 구성 요소가 끝났는 지 파악하고 강조 표시를 변경할 수 있습니다.

+0

호기심 ... "잡기"가 거칠어서 마우스를 조금 움직이면 마우스 이벤트가 발생합니다. 빛이 어떤 견인력도 얻을 수 없도록 공중의 아래쪽을 가리키는 마우스를 사용해보십시오. 스크롤 휠을 사용하여 버튼 3이 내려 지거나 다른 방법으로 알아 채지 못할 수도 있습니다. –

관련 문제