2013-03-06 2 views
1

내부의 정확한 마우스 위치를 얻기가 내 문제입니다 : 나는 기본적으로 가지는 JTree의 요소가 클릭에서 오른쪽 드롭 다운 메뉴를 만드는거야JScrollPane의 다음

enter image description here

, 문제는 JTree가이 내부에 있다는 것입니다 JScrollPane이 스크롤 될 때마다 더 많은 팝업 메뉴가 나타납니다.

마우스 오른쪽 버튼을 클릭하면 다음 코드에서 가로 챌 수있는 MouseEvent가 발생하고 새 팝업 메뉴가 만들어집니다.

jp.show(this, e.getX(), e.getY()); 
:

@Override 
public void mouseClicked(MouseEvent e) { 
    if (SwingUtilities.isRightMouseButton(e)) { 

     int row = tree.getClosestRowForLocation(e.getX(), e.getY()); 
     tree.setSelectionRow(row); 

     TreePath path = tree.getPathForRow(row); 

     DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); 

     // If this object is a Search... 
     if(node.getUserObject().getClass() == Search.class) { 
      jp = new ItemEditPopUpMenu(tree, row, true); 
     } else { 
      jp = new ItemEditPopUpMenu(tree, row, false); 
     } 

     jp.show(this, e.getX(), e.getY()); 
    } 
} 

당신이 볼 수 있듯이, 내가 뭘 모두가 된 MouseEvent에서 위치를 잡아 팝업 메뉴가 다음 줄에 작성되는 위치로 사용하고

이제는 이것이 이벤트를 보낸 요소에 대한 상대적인 위치라는 것을 알게되었습니다. JScrollPanel이 스크롤 될 때 JFrame에서 오프셋을 가져 오는 문제가 무엇인지 설명 할 수 있습니다.

저는 잘 모릅니다. 그게 내가 도움이 필요한 것입니다. 미리 감사드립니다.

+0

하여 작성하고 당신이 괜찮은 답변을 얻을하지 않는 경우 [sscce] (http://sscce.org) 게시 고려 곧. –

답변

5

나는 문제가없는 것 같습니다.

"보기"보기 포트를 팝업에 대한 참조로 사용하면 팝업이 마우스가 클릭 한 위치를 정확히 보여줍니다. 이 회전으로

난 단지 당신이 팝업에 나무에 대한 참조를 전달하지 않는 것을 상상할 수

...

enter image description here

가 나는 점의 전환 엉망이 될 거라고 생각했지만, 밖으로, 그것은 간단 할 수 있었다 ...

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestScrollPane { 

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

    public TestScrollPane() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(new TestPane())); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private List<Point> points; 
     private JPopupMenu pm; 

     public TestPane() { 
      pm = new JPopupMenu(); 
      pm.add(new JLabel("Suprise")); 
      points = new ArrayList<>(3); 
      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseClicked(MouseEvent e) { 
        Point p = e.getPoint(); 
        points.clear(); 
        points.add(p); 
        // View port 
        Container parent = getParent(); 
        Point pp = SwingUtilities.convertPoint(TestPane.this, p, parent); 
        points.add(pp); 
        // ScrollPane... 
        parent = parent.getParent(); 
        Point ppp = SwingUtilities.convertPoint(TestPane.this, p, parent); 
        points.add(ppp); 

        pm.show(TestPane.this, p.x, p.y); 

        repaint(); 
       } 
      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(1000, 1000); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      if (points.size() == 3) { 
       g2d.setColor(Color.RED); 
       Point p = points.get(0); 
       g2d.fillOval(p.x - 2, p.y - 2, 4, 4); 

       g2d.setColor(Color.GREEN); 
       p = points.get(1); 
       g2d.fillOval(p.x - 2, p.y - 2, 4, 4); 

       g2d.setColor(Color.BLUE); 
       p = points.get(2); 
       g2d.fillOval(p.x - 2, p.y - 2, 4, 4); 
      } 
      g2d.dispose(); 
     } 
    } 
} 

그냥 내가 모르는 뭔가가되지 않았다 확인하기 위해이 여기에 JTree

enter image description here

이 (당신은 테스트를 위해 렌더링 사용자 지정 셀을 도랑 수 사용 버전입니다, 이것은 일부 스크랩 코드 I이었다) 주위

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.io.IOException; 
import java.util.Random; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 
import javax.swing.UIManager; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeCellRenderer; 
import javax.swing.tree.DefaultTreeModel; 

public class TestCustomTreeNode { 

    public static void main(String args[]) { 
     new TestCustomTreeNode(); 
    } 
    private JPopupMenu pm; 

    public TestCustomTreeNode() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (Exception ex) { 
       } 

       pm = new JPopupMenu(); 
       pm.add(new JLabel("Suprise")); 

       JFrame f = new JFrame("JTree Sample"); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       JPanel pnlMain = new JPanel(new BorderLayout()); 
       pnlMain.setBackground(Color.white); 

       createTree(pnlMain); 

       f.setContentPane(new JScrollPane(pnlMain)); 

       f.setSize(300, 200); 
       f.setVisible(true); 
      } 
     }); 
    } 

    private void createTree(JPanel pnlMain) { 
     Employee bigBoss = new Employee(Employee.randomName(), true); 
     Employee[] level1 = new Employee[5]; 
     bigBoss.employees = level1; 

     for (int i = 0; i < level1.length; i++) { 
      level1[i] = new Employee(Employee.randomName(), true); 
     } 


     for (int i = 0; i < level1.length; i++) { 
      Employee employee = level1[i]; 
      if (employee.isBoss) { 
       int count = 5; 
       employee.employees = new Employee[count]; 

       for (int j = 0; j < employee.employees.length; j++) { 
        employee.employees[j] = new Employee(Employee.randomName(), false); 
       } 
      } 
     } 

     CustomTreeNode root = new CustomTreeNode(loadResource("/pirate.png"), bigBoss); 
     root.setUserObject("Root"); 
     DefaultTreeModel model = new DefaultTreeModel(root); 

     for (Employee employee : bigBoss.employees) { 
      CustomTreeNode boss = new CustomTreeNode(loadResource("/angel.png"), employee); 
      root.add(boss); 
      if (employee.isBoss) { 
       for (Employee employee1 : employee.employees) { 
        CustomTreeNode emp = new CustomTreeNode(loadResource("/devil.png"), employee1); 
        boss.add(emp); 
       } 
      } 
     } 

     JTree tree = new JTree(model); 
     tree.setCellRenderer(new CustomeTreeCellRenderer()); 
     pnlMain.add(tree, BorderLayout.CENTER); 

     tree.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseReleased(MouseEvent e) { 
       if (e.isPopupTrigger()) { 
        pm.show(e.getComponent(), e.getX(), e.getY()); 
       } 
      } 
     }); 

    } 

    protected ImageIcon loadResource(String name) { 

     ImageIcon image = null; 
     try { 
      image = new ImageIcon(ImageIO.read(getClass().getResource(name))); 
      System.out.println(name + " - " + image); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 

     return image; 

    } 

    public static class Employee { 

     public String name; 
     public int id; 
     public boolean isBoss; 
     public Employee[] employees; 

     public Employee(String name, boolean isBoss) { 
      this.name = name; 
      this.isBoss = isBoss; 
      this.id = new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE); 
     } 

     @Override 
     public String toString() { 
      return this.name; 
     } 

     static String randomName() { 
      String chars = "abcdefghijklmnopqrstuvwxyz"; 
      StringBuilder builder = new StringBuilder(); 
      Random r = new Random(System.currentTimeMillis()); 
      int length = r.nextInt(10) + 1; 
      for (int i = 0; i < length; i++) { 
       builder.append(chars.charAt(r.nextInt(chars.length()))); 
      } 

      return builder.toString(); 
     } 
    } 

    public class CustomTreeNode extends DefaultMutableTreeNode { 

     /** 
     * The icon which is displayed on the JTree object. open, close, leaf icon. 
     */ 
     private ImageIcon icon; 

     public CustomTreeNode(ImageIcon icon) { 
      this.icon = icon; 
     } 

     public CustomTreeNode(ImageIcon icon, Object userObject) { 
      super(userObject); 
      this.icon = icon; 
     } 

     public CustomTreeNode(ImageIcon icon, Object userObject, boolean allowsChildren) { 
      super(userObject, allowsChildren); 
      this.icon = icon; 
     } 

     public ImageIcon getIcon() { 
      return icon; 
     } 

     public void setIcon(ImageIcon icon) { 
      this.icon = icon; 
     } 
    } 

    class CustomeTreeCellRenderer extends DefaultTreeCellRenderer { 

     public CustomeTreeCellRenderer() { 
     } 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 

//   if (!leaf) { 
      CustomTreeNode node = (CustomTreeNode) value; 

      if (node.getIcon() != null) { 
       System.out.println(node + " - " + node.getIcon()); 
       setClosedIcon(node.getIcon()); 
       setOpenIcon(node.getIcon()); 
       setLeafIcon(node.getIcon()); 
      } else { 
       System.out.println(node + " - default"); 
       setClosedIcon(getDefaultClosedIcon()); 
       setLeafIcon(getDefaultLeafIcon()); 
       setOpenIcon(getDefaultOpenIcon()); 
      } 
//   } 

      super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); 

      return this; 
     } 
    } 
} 

브라 반트을 마련했다 : 당신은 팝업 트리거로 마우스 이벤트를 변경해야하는 것은 differe에 따라 다를 수 있습니다 NT 플랫폼에서 작동합니다.

여기에서 JPopupMenu#show으로 전달하는 구성 요소 참조는 마우스 이벤트를 생성 한 구성 요소 참조가 아니라는 결론을 내릴 수 있습니다.

+0

이것이 [sscce] (http://sscce.org)가 그렇게 중요한 이유입니다. 작업 코드가 없으면 관련된 이슈 또는 비 이슈를 완전히 이해하는 것은 불가능합니다. 당신은 시간, 에너지 및 능력을 가지고 행운이지만 다음에 그는 그렇게 운이 좋지 않을 수 있으며 스스로 노력을 기울여야합니다. 1+ –

1

내가 사용 :

구성 요소 내 JTree가이었다
PointerInfo a = MouseInfo.getPointerInfo(); 
Point b = a.getLocation(); 
SwingUtilities.convertPointFromScreen(b, component); 

. 이것은 마우스 화면 위치를 잡는 것처럼 보이며 Swing에 파묻힌 변환 유틸리티 함수를 사용하여 문제를 해결합니다. 희망이 사람을 도와줍니다!

+0

이 답변으로 문제가 해결됩니까? –

+0

그리드에서 비슷한 문제가 발생했습니다.이 답변도 도움이됩니다. –

1

이것은 좋은 해결책이 아니지만 문제를 해결할 수 있습니다.

여기에서 문제는 e.getX() 또는 e.getY()이라고 할 때 반환되는 좌표가 JTree를 기준으로 한 것입니다. 주어진 스크린 샷에서 볼 수 있듯이 JTree를 아래로 스크롤 한 경우 "Y"좌표에서 수직 스크롤 막대 값의 차이를 빼야합니다.

int verticalScrollValue = scrollPane.getVerticalScrollBar().getValue(); 
jp.show(this, e.getX(), e.getY() - verticalScrollValue); 
+0

이 답변의 유효성에 대해 진지한 의문을 가지고 있습니다 만, 'JPopupMenu # show' 메서드에 전달 된'Component' 참조가 마우스 이벤트를 생성하는 것이 아닙니다. 팝업 메뉴는이 세 가지 매개 변수를 사용하여 화면에서 자동으로 상대 위치를 계산합니다. – MadProgrammer

+0

나는 왜 당신이 대답의 타당성에 의문을 가지고 있는지 이해하지 못합니까? 이 문제는 좋은 해결책이 아니지만 올바른 해결책입니다. –

+0

죄송합니다. 적절한 해결책이라고 생각하지 않습니다. 다른 개발자를 빗나가게하고 앞으로 더 많은 문제를 야기 할 것입니다. OP가 직면하고있는 문제는 JPopupMenu # show에 전달 된 'Component' 참조가 마우스 이벤트가 생성 된 것이 아니라는 가능성이 높습니다. 팝업 메뉴의 기본 동작이 작동해야합니다 (내가 시연했듯이) 실제로 OP의 (그리고 잠재적으로 다른 개발자들에게) 문제를 해결하기보다는 출혈에 밴드 보조 장치를 넣었습니다. 이것은 후속 속도를 늦출 수는 있지만 문제를 해결하지는 못할 것입니다. – MadProgrammer

0

나는이 문제를 그대로 (JTree)했습니다. 허용 된 답변이 유용하다는 것을 알았지 만, 무엇이 잘못되었거나 수정본이 어떻게 생겼는지 파악하기 위해 어느 정도 파고 들었습니다.

인체 공학적, 여기에 문제의 코드가 어떻게 표시되는지를 보여줍니다 :

final Component parent = ... 
final JTree tree = ... 
final JPopupMenu menu = ... 

parent.add(tree); 

tree.addMouseListener(new MouseAdapter() { 
    @Override 
    public void mousePressed(MouseEvent e) { 
     if (e.getButton() == MouseEvent.BUTTON3) // Right click 
      menu.show(parent, e.getX(), e.getY()); 
    } 
}); 

오류는 이제 명백해야한다!

MouseEvent

MouseListener 추가의 tree에 의해 발생했지만, 우리는 invoker menu.show(...)parent로 전달된다. 이렇게하면 스크린 샷에 바람직하지 않은 동작이 발생합니다.

수정 프로그램으로 tree을 통과하는 것입니다 invoker 아래 menu.show(...)에 :

final Component parent = ... 
final JTree tree = ... 
final JPopupMenu menu = ... 

parent.add(tree); 

tree.addMouseListener(new MouseAdapter() { 
    @Override 
    public void mousePressed(MouseEvent e) { 
     if (e.getButton() == MouseEvent.BUTTON3) // Right click 
      menu.show(tree, e.getX(), e.getY()); 
    } 
});