gpt4 book ai didi

java - 将 mouseMoved() 事件转发到 JTree 节点?

转载 作者:行者123 更新时间:2023-11-30 11:48:18 25 4
gpt4 key购买 nike

如果我将 JCheckBox 放在 JTree 之外,当我将鼠标悬停在它上面时它会播放动画。当我将相同的 JCheckbox 放置在 JTree 节点内时,它不再接收任何 mouseMoved() 事件并且不播放动画。我尝试将这些事件从 JTree 转发到 JCheckBox,但没有任何显示。

我猜问题是同一个 JCheckBox 实例被 JTree“标记”(每个节点一次)。当我将 mouseMoved() 事件转发到共享实例时,它不知道在哪里重新绘制自己。

有什么想法吗?

编辑:这是一个独立的测试用例。请注意,使 JCheckBox 可点击超出了这个问题的范围(我已经在我的应用程序中使用 TreeCellEditor 这样做了)。

import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;

public class HoverBug
{
public static class TreeRenderer implements TreeCellRenderer
{
private final JCheckBox checkbox = new JCheckBox();

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus)
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
checkbox.setSelected((Boolean) node.getUserObject());
return checkbox;
}
}

public static void main(String[] args)
{
JCheckBox checkbox = new JCheckBox("See... this works!");

DefaultMutableTreeNode root = new DefaultMutableTreeNode(Boolean.TRUE);
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(Boolean.FALSE);
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(Boolean.FALSE);
root.add(child1);
root.add(child2);
DefaultTreeModel model = new DefaultTreeModel(root);

JTree tree = new JTree(model);
tree.setCellRenderer(new TreeRenderer());

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(checkbox, BorderLayout.NORTH);
frame.getContentPane().add(tree, BorderLayout.CENTER);
frame.setSize(800, 600);
frame.setVisible(true);
}

最佳答案

我认为没有解决方案,原因有二:

  1. JCheckBox UI 类(例如 BasicCheckBoxUI)在修改外观时调用 repaint(),但您不会看到这些更改,除非您要求 JTree 使用 DefaultTreeModel.nodeChanged(TreeNode) 重绘节点。 .
  2. 即使您监听与 UI 类相同的模型事件并触发 DefaultTreeModel.nodeChanged(TreeNode)在 repaint() 之后,一些 L&F(特别是 Insubstantial)检查 JCheckBox 是否在 CellRendererPane 内,并在这种情况下禁用动画(可能出于性能原因)。

总而言之,JTree 设计使得为节点设置动画变得不切实际。

就其值(value)而言,这是我将事件转发到底层节点的尝试(它有问题,但你明白了):

[...]
MouseAdapterImpl listener = new MouseAdapterImpl(tree);
tree.addMouseListener(listener);
tree.addMouseMotionListener(listener);
tree.addMouseWheelListener(listener);
[...]
private class MouseAdapterImpl implements MouseListener, MouseWheelListener, MouseMotionListener
{
private final JTree tree;
private int lastRow = -1;

public MouseAdapterImpl(JTree tree)
{
this.tree = tree;
}

/**
* Returns the mouse position relative to the JTree row.
* <p/>
* @param e the mouse event
*/
private void forwardEvent(MouseEvent e)
{
int row = tree.getRowForLocation(e.getX(), e.getY());
Rectangle bounds;
Point point;
if (row == -1)
{
bounds = null;
point = null;
}
else
{
bounds = tree.getRowBounds(row);
point = new Point(e.getX() - bounds.x, e.getY() - bounds.y);
}
if (lastRow != row)
{
if (lastRow != -1)
{
Rectangle lastBounds = tree.getRowBounds(lastRow);
if (lastBounds != null)
{
Point lastPoint = new Point(e.getX() - lastBounds.x, e.getY() - lastBounds.y);
dispatchEvent(new MouseEvent(checkbox, MouseEvent.MOUSE_EXITED,
System.currentTimeMillis(), 0, lastPoint.x, lastPoint.y, 0, false, 0), lastRow);
}
}
if (row != -1)
{
dispatchEvent(new MouseEvent(checkbox, MouseEvent.MOUSE_ENTERED,
System.currentTimeMillis(), 0, point.x, point.y, 0, false, 0), row);
}
}
lastRow = row;
if (row == -1)
return;
dispatchEvent(new MouseEvent(checkbox, e.getID(),
System.currentTimeMillis(), e.getModifiers(), point.x, point.y, e.getClickCount(),
e.isPopupTrigger(), e.getButton()), row);
}

private void dispatchEvent(MouseEvent e, int row)
{
checkbox.dispatchEvent(e);
TreePath pathForLocation = tree.getPathForRow(row);
if (pathForLocation == null)
return;
Object lastPathComponent = pathForLocation.getLastPathComponent();
if (lastPathComponent instanceof DefaultMutableTreeNode)
{
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.nodeChanged((DefaultMutableTreeNode) lastPathComponent);
}
}

@Override
public void mouseEntered(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mouseMoved(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mouseExited(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mouseClicked(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mousePressed(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mouseReleased(MouseEvent e)
{
forwardEvent(e);
}

@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
forwardEvent(e);
}

@Override
public void mouseDragged(MouseEvent e)
{
forwardEvent(e);
}
}

编辑:好消息。他们在 JavaFX 中修复了这个问题:http://javafx-jira.kenai.com/browse/RT-19027

关于java - 将 mouseMoved() 事件转发到 JTree 节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8898770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com