-2

我制作了一个 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。

问题我试图通过在它周围创建一个面板并使用该 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);
}
}
4

3 回答 3

2
  • 对我有用,但有一些错误

  • JScrollPane(在容器的情况下)仅对其子项周围的一个像素(1pixel Border)做出反应

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

  • JPanel 在 API 中有 FlowLayout 实现者,改变它

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

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

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

  • 接近真实的是@Omid +1

在此处输入图像描述 . . . . . 在此处输入图像描述

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();
            }
        });
    }
}
于 2013-05-02T19:54:27.750 回答
-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,它就不再可见。

于 2013-05-02T18:19:00.537 回答
-2

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

scrollPane.addMouseListener(this);

实际上,您可能必须在两者中都有侦听器,具体取决于您希望这一切如何工作,并且可能设置一个锁定,以便只要鼠标在其中至少一个中,滚动条就会显示,但如果鼠标不在则使它们不可见。

于 2013-05-02T18:13:05.670 回答