有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

MouseeEvent之前的Java JTree valueChanged事件

情况是这样的,我有一个带有选项卡式窗格的jFrame,在选项卡中有两个jTables和一个jTree。我希望能够根据用户是使用ctrl/shift+单击还是常规单击在表和树之间链接选择。(如果按住ctrl键并在第一个表/树中单击,则会添加到总体选择中;如果使用常规单击,则会清除其他表/树中的选择)。目前我对Java的jTree组件有一个问题。我添加了一个TreeSelectionListener和一个MouseListener,其中一个类实现了这两个接口,称之为MyBigListener; i、 e

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/shift+click,我可以在树选择侦听器实现的valueChanged(TreeSelectionEvent e)期间进行检查,则设置一个布尔标志。 我希望能够在valueChanged treeSelection事件之前处理鼠标事件,但问题是我在valueChanged treeSelection事件之后接收鼠标事件。这对我来说似乎很奇怪,我在按下鼠标事件触发之前收到选择更改,而选择更改实际上是由按下鼠标启动的。(我已经同步了布尔标志设置,讽刺的是,这有助于突出事件的错误顺序。)

我已经尝试过添加keyListener之类的替代方法,但当焦点位于单独的帧上时,这不起作用,当用户按住ctrl键,然后单击jTree,使其接收焦点并触发任何valueChanged选择事件时,这会使我陷入困境

任何帮助都将不胜感激,谢谢

--编辑--@akf 我在选项卡式窗格中有单独的jTables和jTrees,用作节点图中数据的摘要/控制面板。我在选项卡式窗格中使用这些组件对单独jFrame中显示的图形进行协调选择。每个表都可以单独工作,就像jTree一样。窗格之间的协调很棘手。到目前为止,这在jTable组件中工作得很好,因为我在MouseeEvent中触发了新的选择,在MouseeEvent中,我可以判断shift/ctrl按钮是否已按下,形成我的新选择,并将其传递给父帧,该父帧协调所有窗格之间的选择,并将最终选择发送到图形。但是,父级需要知道是否需要在窗格之间链接选择,或者挤压其他窗格。对于jTables,它又可以了,因为我通过鼠标点击触发选择更改。jTree是一个更大的问题,因为我正在做一些强制选择。如果单击一个分支,它将强制所有叶子进入选择。我需要实现一个TreeSelectionListener来实现这一点,但只需要获得一个valueChanged(TreeSelectionEvent)来实现更改。我添加了一个鼠标侦听器来侦听ctrl+clicks和shift+clicks,但显然事件并不总是以相同的顺序发生。。至少到目前为止,我在mousePressed事件之前收到valueChanged事件,因此检查在修改选择之后是否发生了ctrl+单击

现在,我正在发布一个悬而未决的选择更改,然后让MouseListener抓取它并将其发送到链上,但是如果这些事件不能保证以相同的顺序发生,那么在某个时候它将失败。实施延迟器也会让我感到不舒服

谢谢你迄今为止的帮助

--EDIT2--@ykaganovich

我认为重写fireValueChanged方法更接近正确的方式。根据我对哪些操作应该导致对其他组件的“链接”选择的定义,我需要在valuedChanged方法触发之前收集一些关于发生了什么的上下文。这基本上意味着在任何情况下,我都可以通过谁触发它来定义它的含义。也就是说,如果鼠标事件导致它,并且ctrl键按下,那么设置我需要设置的内容(I(解释)然后开火。如果由于键盘事件而改变,再次设置需要设置的内容,然后启动。我不认为TreeSelectionModel是可行的,因为我仍然不知道事件发生时的情况。我想这意味着我需要重写jTree的一些部分来实现这一点,但我想我会看看它是如何进行的。谢谢


共 (3) 个答案

  1. # 1 楼答案

    不要那样做,而是重写JTree.fireValueChanged

    试试这样(未经测试):

    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

    编辑

    实际上,我认为正确的方法是实现自己的TreeSelection模型,并覆盖fireValueChanged。假设setSelectionPath(s)方法意味着一个新的选择,而add/removeSelectionPath(s)意味着链接,您可以清楚地区分这两种方法。我不喜欢直接听键盘或鼠标事件,因为改变选择的方法不止一种(例如,如果有人按住SHIFT键并按下向下箭头,你就不会看到鼠标事件)

  2. # 2 楼答案

    这里的关键是要理解JTree是与BasicTreeUI一起交付的。MouseHandler,参见javax。摆动普拉夫。基本的基本的

    要回答核心问题“什么改变了”,答案是“这个鼠标处理器”。。。这是你去树上时唯一返回的鼠标侦听器。getMouseListeners()

    所以你必须用你自己的版本替换这个默认的鼠标侦听器。。。这有点棘手。我使用Jython,每个人都需要发现。但是,将这段代码翻译成Java应该不会太难:

      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() ))
    

    。。。基本上,这里的Java等价于扩展BasicTreeUI。将MouseHandler替换为MyMouseHandler,然后在最后一行中替换为新的MyMouseHandler(tree.getUI())。。。这里的“nTFSelf”只是对代码中“this”对象的引用,所有这些都是在这里编写的

  3. # 3 楼答案

    您可以在树选择事件之前或之后获得鼠标事件。最好不要依赖这样的命令。原因是树选择事件是响应鼠标事件而产生的。鼠标事件侦听器是在侦听器之前还是之后调用的?两者都有可能

    这类事情与PL&;F