退出JScrollPane中的组件时,防止滚动条消失

时间:2013-05-02 17:50:43

标签: java swing jpanel jscrollpane jtextarea

我制作了一个JPanel,其中包含一个围绕JTextArea的JScrollPane。我想在鼠标退出JScrollPane时隐藏滚动条。

如果我在JScrollPane上设置MouseListener,则没有任何反应。如果我在JTextArea上设置它,那么滚动条会正确隐藏/取消隐藏,但是您无法单击它们,因为它们超出了JTextArea的范围。\

当您尝试点击时,如何防止滚动条消失?

代码示例1.隐藏和取消隐藏+更改透明度有效

问题:您无法点击滚动条,因为退出JTextArea,它们会消失。

public class TransparentTextArea extends JTextArea {

private static final Color LIGHT_TRANSPARENT = new Color(0, 0, 0, 150);
private static final Color HEAVY_TRANSPARENT = new Color(0, 0, 0, 50);

public TransparentTextArea(final GameModel model) {
    setOpaque(false);
    setForeground(Color.WHITE);
    setBackground(HEAVY_TRANSPARENT);
    setEditable(false);
    addMouseListener(new MouseListener() {

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseExited(MouseEvent e) {
            model.setLogActive(false);
            setBackground(HEAVY_TRANSPARENT);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            model.setLogActive(true);
            setBackground(LIGHT_TRANSPARENT);
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    });
}
}

public class Logger extends JScrollPane implements PanelObserver,
    ChangeListener {

private GameModel model;

public Logger(final GameModel model) {
    super(new TransparentTextArea(model));
    this.model = model;
    setOpaque(false);
    getViewport().setOpaque(false);
    setBorder(BorderFactory.createEmptyBorder());
    setViewportBorder(BorderFactory.createEmptyBorder());
    model.addPanelObserver(this);
    model.addChangeListener(this);
}

@Override
public void panelResized() {
    float x = model.getPanelWidth() * 0.01f;
    float y = model.getPanelHeight() * 0.70f;
    float width = model.getPanelWidth() * 0.30f;
    float height = model.getPanelHeight() * 0.28f;

    setBounds((int) x, (int) y, (int) width, (int) height);
}

@Override
public void stateChanged(ChangeEvent e) {
    if (model.isLogActive()) {
        setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    } else {
        setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    }
}
}

代码示例2.

问题我试图通过围绕它创建一个Panel并使用该MouseExited来解决这个问题,但是由于孩子们使用了它,它不起作用。

public class Logger extends JPanel implements PanelObserver, MouseListener {

private static final Color LIGHT_TRANSPARENT = new Color(0, 0, 0, 150);
private static final Color HEAVY_TRANSPARENT = new Color(0, 0, 0, 50);

private GameModel model;
private JTextArea textArea;
private JScrollPane scrollPane;

public Logger(GameModel model) {
    super(null);

    this.model = model;
    setOpaque(false);

    textArea = new JTextArea();
    textArea.setOpaque(false);
    textArea.setForeground(Color.WHITE);
    textArea.setBackground(HEAVY_TRANSPARENT);
    textArea.setEditable(false);

    scrollPane = new JScrollPane(textArea);
    scrollPane.setOpaque(false);
    scrollPane.getViewport().setOpaque(false);
    scrollPane.setBorder(BorderFactory.createEmptyBorder());
    scrollPane.setViewportBorder(BorderFactory.createEmptyBorder());
    add(scrollPane);

    model.addPanelObserver(this);
    addMouseListener(this);
}

@Override
public void panelResized() {
    float x = model.getPanelWidth() * 0.01f;
    float y = model.getPanelHeight() * 0.70f;
    float width = model.getPanelWidth() * 0.30f;
    float height = model.getPanelHeight() * 0.28f;

    setBounds((int) x, (int) y, (int) width, (int) height);
    scrollPane.setBounds(0, 0, (int) width, (int) height);
}

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mousePressed(MouseEvent e) {}


@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    textArea.setBackground(LIGHT_TRANSPARENT);
}

@Override
public void mouseExited(MouseEvent e) {
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        textArea.setBackground(HEAVY_TRANSPARENT);
}
}

3 个答案:

答案 0 :(得分:2)

  • 适合我,但有一些错误

  • JScrollPane(在容器的情况下)只响应其子项周围的一个像素(1像素边框)

  • 鼠标事件由其子节点使用,然后添加到JPanel内的JScrollPane以消耗()鼠标事件

  • JPanel在API中有FlowLayout实现,更改

  • 不要使用NullLayout,使用适当的LayourManager进行JPanel(BorderLayout,GridLayout)

  • JComponents可以很容易地将PreferredSize返回到容器覆盖JPAnel,JTextArea(20,20)等的getPreferredSize

  • JPanel必须大于JScrollPane中的JViewport,否则(不覆盖JScrollBars)JScrollBar永远不可见

  • 接近真实的是@Omid +1

enter image description here。 。 。 。 。 enter image description here

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
//http://stackoverflow.com/q/16344529/714968
public class MyLogger {

    private JTextArea textArea;
    private JScrollPane scrollPane;

    public MyLogger() {
        textArea = new JTextArea(20, 20);
        scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        textArea.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mousePressed(MouseEvent e) {
            }

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
                scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
                scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            }
        });
        JFrame frame = new JFrame();
        frame.add(scrollPane);
        frame.setPreferredSize(new Dimension(100, 100));// JFrame must be smaller
        frame.pack();
        frame.setLocation(150, 150);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyLogger myLogger = new MyLogger();
            }
        });
    }
}

修改

再次回到@Omid发布的回答,看看会发生什么

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
//http://stackoverflow.com/q/16344529/714968
public class MyLogger {

    private JTextArea textArea;
    private JScrollPane scrollPane;

    public MyLogger() {
        textArea = new JTextArea(20, 20);
        textArea.setText("This text pane contains no html. It supports letter wrapping, "
                + "\nThis text pane contains no html. It supports letter wrapping!, "
                + "\nThis text pane contains no html. It supports letter wrapping!, "
                + "\nThis text pane contains no html. It supports letter wrapping!, "
                + "\nThis text pane contains no html. It supports letter wrapping!, "
                + "\nThis text pane contains no html. It supports letter wrapping!");
        textArea.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
                scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            }
        });
        scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseExited(MouseEvent e) {
                scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
                scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            }
        });
        JFrame frame = new JFrame();
        frame.add(scrollPane);
        frame.setPreferredSize(new Dimension(100, 100));// JFrame must be smaller
        frame.pack();
        frame.setLocation(150, 150);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyLogger myLogger = new MyLogger();
            }
        });
    }
}

答案 1 :(得分:-1)

试过这个并且它运行正常:

 textArea.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent arg0) {
                    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
                    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                }
            });

 scrollPane.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseExited(MouseEvent e) {

                scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
                scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            }
        });

这个想法是,只要鼠标在textArea中移动,ScrollBar就可见并且工作正常。一旦它移出ScrollPane,它就不再可见了。

答案 2 :(得分:-2)

您可能必须将侦听器放在JScrollPane本身而不是支持JPanel上。 JScrollPane封装了你的JPanel,因此只将鼠标监听器添加到JPanel只会告诉你鼠标何时进入/离开JPanel,而不是封装JScrollPane。

scrollPane.addMouseListener(this);

你可能实际上必须在两者中都有听众,这取决于你想要这一切的工作方式,并且可能设置一个锁定,这样只要鼠标至少在其中一个中,滚动条就会显示,但如果鼠标不在,则将它们隐藏起来。