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