2009-09-23 3 views
1

상황은 다음과 같습니다. 탭이있는 jFrame이 있고 탭 내에 몇 개의 jTables와 jTree가 있습니다. 사용자가 ctrl/shift + 클릭과 일반 클릭 중 어느 것을 사용하는지에 따라 테이블과 트리 사이에서 선택 항목을 연결할 수 있기를 원합니다. Ctrl 키를 누른 상태에서 첫 번째 표/트리를 클릭하면 전체 선택 항목에 추가됩니다. 일반 클릭을 사용하면 다른 표/트리의 선택 항목이 지워집니다. 현재 Java의 jTree 구성 요소에 문제가 있습니다. TreeSelectionListener와 두 인터페이스를 구현하는 클래스가있는 MouseListener를 추가했습니다. MyBigListener를 호출합니다. 즉Java JTree valueChanged before MouseEvent

MyBigListener listener = new MyBigListener(); 
jTree1.addMouseListener(listener); 
jTree1.addTreeSelectionListener(listener); 

MyBigListener implements TreeSelectionListener, MouseListener { 
    private boolean chained = false; 
    public synchronized setChained(boolean ch){ 
    chained = ch; 
    } 
    public synchronized boolean isChained(){ 
    return chained 
    } 
    public void valueChanged(TreeSelectionEvent e){ 
    if(isChained()){ blah... } 
    } 

    public void mousePressed(MouseEvent e){ 
    setChained(e.isControlDown() || e.isShiftDown()); 
    } 
} 

내 계획은 사용자가 Ctrl 키를/이동을 사용하는 경우 부울 플래그를 설정 + I 트리 선택 리스너에 의해 구현의 valueChanged (TreeSelectionEvent 전자) 동안 확인 할 수 있음을 클릭했다. valueChanged TreeSelectionEvents 이전에 마우스 이벤트를 처리 할 수 ​​있기를 원하지만, 문제는 valueChanged treeSelection 이벤트 다음에 마우스 이벤트를 수신한다는 것입니다. 마우스로 눌렀을 때 실제로 선택 변경이 시작될 때 마우스 누르기 이벤트가 시작되기 전에 선택 변경 사항을 수신한다는 것은 이상한 일입니다. (벌써 부울 플래그 설정을 동기화했는데, 아이러니하게도 이벤트의 오더 순서를 강조하는 데 도움이되었습니다.)

나는 이미 keyListener를 추가하는 것과 같은 대안을 시도했지만 포커스가 켜져 있으면 작동하지 않습니다. 사용자가 Ctrl 키를 누른 상태에서 jTree를 클릭하면 포커스를 수신하고 valueChanged 선택 이벤트를 발생시키는 별도의 프레임입니다.

감사합니다. 감사합니다.

--EDIT--는 @akf I는 노드 그래프에서 데이터 요약/조작부로서 기능 탭 구획 별도 jTables 및 jTrees있다. 필자는 별도의 jFrame에 표시된 그래프에 조율 된 선택을하기 위해 탭 패널에서 이러한 구성 요소를 사용하고 있습니다. 개별적으로 각 테이블은 jTree처럼 선택을 위해 잘 작동합니다. 그것은 까다로운 창 사이를 조정하고 있습니다. Shift/Ctrl 버튼이 눌려 졌는지 알 수있는 MouseEvent의 결과로 새 선택 항목을 실행하고 새 선택 항목을 공식화 한 다음 상위 항목으로 전달하여 선택 항목을 모두 조정하는 jTable 구성 요소를 사용하면 jTable 구성 요소와 잘 작동합니다. 마지막 선택 영역을 그래프로 보냅니다. 그러나 부모는 창 사이에서 선택을 연결해야하는지 또는 다른 창을 스쿼시해야 하는지를 알아야합니다. jTables을 사용하면 마우스 클릭의 결과로 선택 사항이 변경되므로 다시 괜찮습니다. jTree는 몇 가지 강제 선택을하기 때문에 더 많은 문제가 있습니다. 가지를 클릭하면 모든 나뭇잎이 선택 영역으로 강제 이동됩니다. 그렇게하기 위해 TreeSelectionListener를 구현해야했지만 변경 사항을 실현하기 위해 valueChanged (TreeSelectionEvent) 만 가져 왔습니다. Ctrl + 클릭 및 Shift + 클릭을 수신 대기하는 mouseListener를 추가했지만 이벤트가 항상 같은 순서로 발생하지는 않습니다. 적어도 지금까지는 mousePressed 이벤트 이전에 valueChanged 이벤트를 수신 했으므로 Ctrl 키를 누른 경우 + 선택이 이미 수정 된 후에 발생한 게시물을 클릭하십시오.

지금 당장, 보류중인 선택 변경 사항을 게시하고 MouseListener를 가져 와서 체인으로 보냈지 만 이러한 순서가 같은 순서로 발생한다고 보장되지 않으면 어떤 시점에서 실패. 지연 기 구현은 또한 나에게 잘못된 방식으로 문지른다.

지금까지 도움을 주셔서 감사합니다.

--EDIT2-- @ykaganovich

은 내가 fireValueChanged 메서드를 재정하는 것들에 대해 갈 수있는 올바른 방법에 가까운 생각합니다.내 구성 요소에 따라 다른 구성 요소에 "체인으로 연결된"선택을 야기하는 것에 대한 정의에 따라 valuedChanged 메서드가 실행되기 전에 진행되는 작업에 대한 컨텍스트를 수집해야합니다. 이것은 기본적으로 누가 그것을 트리거하는지에 의해 정의 할 수있는 모든 경우에 직접 호출하는 것을 의미합니다. 나는. 마우스 이벤트가 발생하면 Ctrl 키를 누른 다음 설정 (해석)하고 화재가 발생하도록 설정합니다. 키보드 이벤트로 인해 변경 될 경우, 다시 설정해야하는 항목을 설정 한 다음 실행하십시오. TreeSelectionModel은 갈 길이 멀지 않다고 생각합니다. 이벤트가 발생했을 때의 상황을 여전히 알 수 없기 때문입니다. 이것은 jTree의 일부를 다시 작성해야 할 필요가 있음을 의미한다고 생각하지만, 어떻게 진행되는지 살펴볼 것입니다. 감사.

+0

트리를 마치 테이블의 첫 번째 열을 선택하고 트리 및 테이블 구성 요소를 가로 지르는 선택을 마치 하나처럼 적용하려고합니까? – akf

답변

1

의 구현과 밀접하게 참여하고있다. 이 같은

시도 뭔가 (테스트되지 않은) :

class ChainedSelectionEvent extends TreeSelectionEvent { 
    ChainedSelectionEvent(TreeSelectionEvent e) { 
    super(e.newSource, e.paths, e.areNew, e.oldLeadSelectionPath, e.newLeadSelectionPath); 
    } 
} 

protected void fireValueChanged(TreeSelectionEvent e) { 
    if(chained) { // figure out separately 
     super.fireValueChanged(new ChainedSelectionEvent(e)); 
    } else { 
     super.fireValueChanged(e); 
    } 
} 

그런 다음 리스너에 ChainedSelectionEvent instanceof를 확인은

사실 EDIT

, 나는 생각이 작업을 수행하는 올바른 방법은 구현하는 것입니다 독자적인 TreeSelectionModel를 작성해, 대신에 fireValueChanged를 오버라이드 (override)합니다. setSelectionPath(s) 방법이 새로운 선택을 암시하고 add/removeSelectionPath(s)이 연결을 암시한다고 가정하면이 두 가지를 깔끔하게 구분할 수 있습니다. 선택 사항을 변경하는 데는 여러 가지 방법이 있으므로 (예 : 누군가가 Shift 키를 누른 상태에서 아래쪽 화살표를 누르면 마우스 이벤트가 발생하지 않음) 키보드 나 마우스 이벤트를 명시 적으로 듣는 것을 좋아하지 않습니다.

+0

나는 이벤트가 순서가 맞지 않기 때문에 선택이 묶여 져야 하는지를 결정할 수 없다는 점을 감안할 때 여전히 같은 문제에 직면 할 것이라고 생각한다. 누가 fireValueChanged의 호출을 제어합니까? 그 나무 그 자체? jTree를 완전히 다시 쓰고 싶지는 않았지만 이미 드래그 드롭 지원을 추가하기는했지만 이미 그렇게하지 않았습니다. 흠 ...내가 내 트리에서 그것을 타고, 거기에 MouseListener을 구현할 수있을 것 같아요 마우스 이벤트의 결과로만이 메서드를 호출하지만 분기 축소/확장에 대한 선택이 까다로워집니다 .. 나는 jTrees를 싫어한다고 생각합니다 :) – user49913

+0

나는 이것이 효과가 있다고 생각한다. fireValueChanged는, 선택에 응해 JTree에 의해 불려갑니다. MouseEvent를 명시 적으로 처리해야한다고 생각하지 않습니다. – ykaganovich

+0

사용자가 Shift/Ctrl 버튼을 누른 상태에서 항목을 추가/제거한 경우 알 수있는 유일한 방법이므로 MouseEvents를 처리해야합니다. 이것은 무언가를 묶는 지 아닌지에 대한 나의 정의입니다. 나는 그것이 깨끗하지 않다는 데 동의하지만 KeyListener가 기본적으로 동일한 이벤트를 캡처하여 응답하도록 할 수 있습니다. 체인 연결 여부에 대한 내 정의에 대해 사용자가 선택 항목을 수정할 수있는 모든 방법을 포착하고 선택 변경을 실행하기 전에 어떤 일이 진행되고 있는지에 대한 상황을 파악해야한다고 생각합니다. 도와 주셔서 감사합니다. – user49913

1

트리 이벤트가 발생하기 전이나 후에 마우스 이벤트가 발생할 수 있습니다. 그러한 명령에 의지하지 않는 것이 최선입니다. 그 이유는 트리 선택 이벤트가 마우스 이벤트에 대한 응답으로 인해 발생하기 때문입니다. 마우스 이벤트 청취자가 청취자 전후에 불려지나요? 어느 쪽이든 될 수 있습니다.

것은 이런 종류의

는 그런 식으로 할 대신 JTree.fireValueChanged을 무시하지 마십시오 PL & F.

0

여기서 핵심은 JTree가 BasicTreeUI.MouseHandler와 함께 제공된다는 것을 이해하는 것입니다. 자세한 내용은 javax.swing.plaf.basic.BasicTreeUI를 참조하십시오.

"fireValueChanged가 무엇입니까?"라는 대답은 "this mouse handler"입니다 ... tree.getMouseListeners()를 호출했을 때 반환되는 유일한 마우스 수신기입니다.

그래서이 기본 마우스 수신기를 자신의 버전으로 교체해야합니다 ... 다소 까다 롭습니다. 나는 모두가 알아 내야 할 자이 썬을 사용한다.

from javax.swing.plaf.basic import BasicTreeUI  
    def makeMouseHandlerClass(): 
    class MouseHandlerClass(BasicTreeUI.MouseHandler): 
     def mousePressed(self, mouseEvent): 
     genLog.info("mouse handler MOUSE PRESSED!") 
     nTFSelf.mousePressedStatus = True 
     BasicTreeUI.MouseHandler.mousePressed(self, mouseEvent) 
     nTFSelf.mousePressedStatus = False 

    return MouseHandlerClass 
    suppliedMouseHandler = nTFSelf.taskTree.mouseListeners[ 0 ] 
    nTFSelf.taskTree.removeMouseListener(suppliedMouseHandler ) 
    nTFSelf.taskTree.addMouseListener(makeMouseHandlerClass()(nTFSelf.taskTree.getUI())) 

... 기본적으로 해당 자바 여기 MyMouseHandler로 BasicTreeUI.MouseHandler을 확장하는 것, 그리고 마지막 줄에 (새 MyMouseHandler로 대체 :이 코드는하지만 자바로 번역하기 너무 어려운해서는 안됩니다 tree.getUI()) ... 여기서 "nTFSelf"는이 코드가 쓰여지고있는 코드의 "this"객체에 대한 참조 일뿐입니다 ...