【问题标题】:JTree & JButtons - Wrong Rendering when mouse hovers over ButtonJTree & JButtons - 当鼠标悬停在 Button 上时出现错误的渲染
【发布时间】:2012-12-25 23:46:59
【问题描述】:

我对 JTree 和 JButton 有疑问 似乎当进入编辑模式并将鼠标悬停在 TreeCells 上的按钮上时,它会在按钮内渲染树的某些部分。 即使在同一行中从一个按钮拖动到另一个按钮时,它也会将一个按钮呈现在另一个按钮之上。

这里有一个简短的自我解释示例,您可以复制粘贴以了解我的意思。

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.EventObject;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;


public class MyProblemWithTree {

    public static void main(String...args) {
        JFrame frame = new JFrame("Panel");
        JScrollPane scroll = new JScrollPane();

        DefaultMutableTreeNode node = new DefaultMutableTreeNode("Root");

        DefaultMutableTreeNode nodeChild = new DefaultMutableTreeNode("childcaretaker1");
        nodeChild.add(new DefaultMutableTreeNode("child1"));
        nodeChild.add(new DefaultMutableTreeNode("child2"));

        node.add(nodeChild);


        final JTree tree = new JTree(node);

        tree.setCellRenderer(new MyTreeCellRenderer());
        tree.setEditable(true);
        tree.setCellEditor(new MyTreeCellEditor(tree));

        tree.addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseMoved(MouseEvent e) {
                // TODO Auto-generated method stub
                if (tree.getRowForLocation(e.getX(), e.getY()) != -1)
                {
                    tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY()));
                } 
            }

            @Override
            public void mouseDragged(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }
        });

        scroll.setViewportView(tree);
        frame.add(scroll);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}
class MyTreeCellEditor extends DefaultTreeCellEditor {

    JPanel      leafPanel;
    JLabel      colorIcon;
    PlayButton  play; 
    PauseButton pause;
    JLabel      name; 

    public MyTreeCellEditor(JTree tree) {
        super(tree, (MyTreeCellRenderer)tree.getCellRenderer());
        leafPanel   = new JPanel(new FlowLayout());
        colorIcon   = new JLabel(UIManager.getIcon("OptionPane.informationIcon"));
        play        = new PlayButton();
        pause       = new PauseButton();
        name        = new JLabel();

        play.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                System.out.println("Playbutton klickt");
            }
        });

        leafPanel.add(colorIcon);
        leafPanel.add(name);
        leafPanel.add(pause);
        leafPanel.add(play);
    }


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

        name.setText((String)((DefaultMutableTreeNode)value).getUserObject());
        pause.setVisible(!leaf);
        return leafPanel;
    }

    @Override
    public boolean isCellEditable(EventObject arg0) {
        return true;
    }
}
class MyTreeCellRenderer extends DefaultTreeCellRenderer {
    private static final long serialVersionUID = 3691823996133806942L;

    JPanel leafPanel;
    JLabel colorIcon;
    PlayButton play; 
    PauseButton pause;
    JLabel name; 

    DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();

    Color backgroundSelectionColor; 
    Color backgroundNonSelectionColor;


    public MyTreeCellRenderer() {
        leafPanel = new JPanel(new FlowLayout());
        colorIcon = new JLabel(UIManager.getIcon("OptionPane.informationIcon"));
        play = new PlayButton();
        pause = new PauseButton();
        name = new JLabel();

        leafPanel.add(colorIcon);
        leafPanel.add(name);
        leafPanel.add(pause);
        leafPanel.add(play);

        backgroundSelectionColor = new Color(200,200,255,50);
        backgroundNonSelectionColor = new Color(0,0,0,0);
    }

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        name.setText((String)((DefaultMutableTreeNode) value).getUserObject());
        if (selected) {
            leafPanel.setBackground(backgroundSelectionColor);
        } else {
            leafPanel.setBackground(backgroundNonSelectionColor);                       
        }
        leafPanel.setEnabled(tree.isEnabled());
        pause.setVisible(!leaf);
        return leafPanel;
    }
}

class PlayButton extends JButton{
    private static final long serialVersionUID = 550654173835539853L;

    Dimension size = new Dimension(140,28);

    public PlayButton() {
        setIcon(UIManager.getIcon("OptionPane.informationIcon"));
        setPressedIcon(UIManager.getIcon("OptionPane.errorIcon"));
        setBackground(new Color(0,0,0,0));
        setBorderPainted(false);
        setPreferredSize(size);
        setMaximumSize(size);
        setMinimumSize(size);
    }
}
class PauseButton extends JButton{
    private static final long serialVersionUID = -5877843953696256070L;

    Dimension size = new Dimension(140,28);

    public PauseButton() {
        setIcon(UIManager.getIcon("OptionPane.warningIcon"));
        setPressedIcon(UIManager.getIcon("OptionPane.questionIcon"));
        setBackground(new Color(0,0,0,0));
        setBorderPainted(false);
        setPreferredSize(size);
        setMaximumSize(size);
        setMinimumSize(size);
    }
}

即使我删除了这部分。我必须单击一个单元格才能进入编辑模式我仍然可以通过鼠标离开单元格并返回来获得效果。

        public void mouseMoved(MouseEvent e) {
            // TODO Auto-generated method stub
            if (tree.getRowForLocation(e.getX(), e.getY()) != -1)
            {
                tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY()));
            } 
        }

我已经花了 4 天的时间来完成这个 JTree 定制。但这真的让我很困惑,我怎么能通过输入按钮来停止渲染。

【问题讨论】:

  • 使用 UIManager.getIcon("OptionPane.errorIcon / informationIcon / warningIcon / questionIcon");而是在这里编辑您的问题
  • 也可以考虑simpler example
  • 可能相关或不相关:编辑器实现无效 - 它必须通知其侦听器因内部原因终止编辑
  • 感谢您的建议@mKorbel 我编辑了它。
  • @trashgod 我试着让它更简单一些。但它必须保留一些你注意到行为的东西,比如没有按钮的不必要的图标。

标签: java swing jbutton jtree treecellrenderer


【解决方案1】:

我不知道如何解决这个问题,但使用 invokeLatersetRowHeight() 会有所帮助。

public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            JFrame frame = new JFrame("Panel");
            ...
            tree.setRowHeight(icon.getIconHeight());
            ...
            frame.setVisible(true);
        }
    });
}

【讨论】:

  • 嗨@Catalina Island我试图用invokeLater包围我的main代码并设置高度,但它没有解决问题。你试过了吗,它有效吗?如果是这样的话,通过做我写的来说明我的错误在哪里。隐藏东西不会解决我的问题,因为它只是在这里简单化。所以改变高度和宽度并没有帮助。我故意将按钮制作得如此之大以至于人们可以看到它是呈现到按钮中的单元格
  • @Sven: invokeLater 停止显示“按钮内树的某些部分”,无论如何您都应该这样做; setRowHeight 减少了顶部和底部的图标剪辑。老实说,我尽量避免树上的按钮,但我可能会尝试 kleopatra 的方式。
  • 我想我找到了一些东西,但我不能在下周之前肯定地说出来。在另一台 PC 上,奇怪的渲染没有出现。所以我可能会在工作中更改使用的 jdk 并查看是否可以解决问题。实际上我不能在家里复制它。
猜你喜欢
  • 2021-09-23
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多