问题代码:
textArea.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
posX = e.getX();
posY = e.getY();
}
});
textArea.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
setLocation(e.getXOnScreen() - posX, e.getYOnScreen() - posY);
}
});
背景
我有一个JFrame,JFrame中有一个JScrollPane,而在JScrollPane中有一个名为“textArea”的JTextArea。此JTextArea占用整个JFrame,JFrame未修饰。所以为了给出一些观点,这里通常是JFrame的样子......
当鼠标在JTextArea中单击并移动时,将拖动整个窗口。一切都设置为不能专注于这项工作,它意味着是一个叠加。
问题:
上面列出的代码运行良好,世界处于和平状态。但是,一旦有足够的文本显示垂直滚动条(由于换行没有水平),拖动窗口就成了问题。当您单击并开始移动时,JFrame会立即在屏幕上移动得更高。 JTextArea中的行,当您尝试移动它时它向上移动得越高。我假设get * OnScreen()方法是问题,因为它与JTextArea都有关。
问题类:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main extends JFrame {
private JTextArea textArea;
private JScrollPane textAreaScroll;
private int posX = 0;
private int posY = 0;
public Main() {
initComponents();
initListeners();
for(int i = 0; i < 20; i++){
addLine(i+" Hello");
}
}
public void addLine(String line){
textArea.append("\n> "+line);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
private void initListeners(){
textArea.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
posX = e.getX();
posY = e.getY();
}
});
textArea.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
setLocation(e.getXOnScreen() - posX, e.getYOnScreen() - posY);
}
});
}
private void initComponents() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {}
textAreaScroll = new JScrollPane();
textArea = new JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setUndecorated(true);
setAlwaysOnTop(true);
setAutoRequestFocus(false);
setBackground(new Color(130,210,255,130));
setFocusCycleRoot(false);
setFocusable(false);
setFocusableWindowState(false);
setName("main");
setOpacity(0.4f);
setResizable(false);
textAreaScroll.setBorder(null);
textAreaScroll.setFocusable(false);
textAreaScroll.setRequestFocusEnabled(false);
textArea.setEditable(false);
textArea.setBackground(new Color(0, 0, 0));
textArea.setColumns(20);
textArea.setFont(new Font("Consolas", 0, 14));
textArea.setForeground(new Color(255, 255, 255));
textArea.setLineWrap(true);
textArea.setRows(5);
textArea.setText("> Hello world!\n> another line!");
textArea.setBorder(null);
textArea.setFocusable(false);
textArea.setRequestFocusEnabled(false);
textAreaScroll.setViewportView(textArea);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(textAreaScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(textAreaScroll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 214, Short.MAX_VALUE)
);
pack();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Main().setVisible(true);
}
});
}
}
答案 0 :(得分:1)
您说 JFrame会立即在屏幕上移动得更高。 JTextArea中的行但实际上它向下滚动,因此只有最后几行可见。
如果您想从顶部看到textArea内容,请点击此处
initComponents();
initListeners();
for (int i = 0; i < 20; i++) {
addLine(i + " Hello");
}
//set scrolling position to top
textArea.setCaretPosition(0);
答案 1 :(得分:1)
你的诊断绝对是正确的:
当您单击并开始移动时,JFrame会立即移动 在屏幕上更高。 JTextArea中的线条移动得越高 当你试图移动它时。我假设get * OnScreen()方法 是问题,因为它与JTextArea都有关。
因此要解决此问题JFrame
使用MouseXXXListener
附加JFrame
因此我们可以在拖动时获得正确的坐标,此解决方案的主要问题是 glasspane < / em>将使用适用于MouseEvent
上其他组件的事件,这可以通过适当地重新调整JPanel
来克服:
创建JPanel
(此 glassPane / setOpaque(false)
将通过xxxAdapters
透明,并在此附加MouseEvent
。
将redispacth JTextArea
的自定义侦听器类创建为必要的组件(因为 glasspane 将消耗所有事件到JScollPane
/ JPanel
)
通过JFrame
将JFrame#setGlassPane(..)
设为JFrame
的GlassPane。
设置setVisible(true)
可见而不是通过import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.MouseInputAdapter;
public class Main extends JFrame {
private JTextArea textArea;
private JScrollPane textAreaScroll;
private JPanel glassPane;//create variable for glasspane
public Main() {
initComponents();
initListeners();
for (int i = 0; i < 20; i++) {
addLine(i + " Hello");
}
}
public void addLine(String line) {
textArea.append("\n> " + line);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
private void initListeners() {
GlassPaneListener gpl = new GlassPaneListener(textAreaScroll.getVerticalScrollBar(), this);
//add the adapters/listeners to the glasspane
glassPane.addMouseMotionListener(gpl);
glassPane.addMouseListener(gpl);
}
private void initComponents() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
}
textAreaScroll = new JScrollPane();
textArea = new JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setUndecorated(true);
setAlwaysOnTop(true);
setAutoRequestFocus(false);
setBackground(new Color(130, 210, 255, 130));
setFocusCycleRoot(false);
setFocusable(false);
setFocusableWindowState(false);
setName("main");
setOpacity(0.4f);
setResizable(false);
textAreaScroll.setBorder(null);
textAreaScroll.setFocusable(false);
textAreaScroll.setRequestFocusEnabled(false);
textArea.setEditable(false);
textArea.setBackground(new Color(0, 0, 0));
textArea.setColumns(20);
textArea.setFont(new Font("Consolas", 0, 14));
textArea.setForeground(new Color(255, 255, 255));
textArea.setLineWrap(true);
textArea.setRows(5);
textArea.setText("> Hello world!\n> another line!");
textArea.setBorder(null);
textArea.setFocusable(false);
textArea.setRequestFocusEnabled(false);
textAreaScroll.setViewportView(textArea);
textAreaScroll.setPreferredSize(new Dimension(200, 200));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(textAreaScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE));
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(textAreaScroll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 214, Short.MAX_VALUE));
//create and make glasspane not opaque
glassPane = new JPanel();
glassPane.setOpaque(false);
//set glasspane as JFrame glassPane
setGlassPane(glassPane);
pack();
setVisible(true);//set JFrame visible
//glassPane can only be setVisible after JFrame is visible
glassPane.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
}
class GlassPaneListener extends MouseInputAdapter {
private int posX = 0;
private int posY = 0;
Toolkit toolkit;
private final Container contentPane;
private final Component textAreaScroll;
private final Component glassPane;
private final JFrame frame;
private boolean wasClickOnInterestedComponent = false;
public GlassPaneListener(Component textAreaScroll, JFrame frame) {
toolkit = Toolkit.getDefaultToolkit();
this.textAreaScroll = textAreaScroll;
this.frame = frame;
this.glassPane = frame.getGlassPane();
this.contentPane = frame.getContentPane();
}
@Override
public void mouseDragged(MouseEvent e) {
if (!redispatchMouseEvent(e)) {
frame.setLocation(e.getXOnScreen() - posX, e.getYOnScreen() - posY);
}
}
@Override
public void mousePressed(MouseEvent e) {
if (!redispatchMouseEvent(e)) {//check if event was redispatched if not its meant for us :)
posX = e.getX();
posY = e.getY();
}
}
@Override
public void mouseReleased(MouseEvent me) {
wasClickOnInterestedComponent = false;
}
private boolean redispatchMouseEvent(MouseEvent e) {
Point glassPanePoint = e.getPoint();
Container container = contentPane;
Point containerPoint = SwingUtilities.convertPoint(glassPane, glassPanePoint, contentPane);
// The mouse event is probably over the content pane.
// Find out exactly which component it's over.
Component component = SwingUtilities.getDeepestComponentAt(container, containerPoint.x,
containerPoint.y);
if ((component != null) && (component.equals(textAreaScroll)) || wasClickOnInterestedComponent) {
wasClickOnInterestedComponent = true;//so that if we drag iur cursor off JScrollBar tghe window wont be moved
// Forward events over the scrollbar
Point componentPoint = SwingUtilities.convertPoint(glassPane, glassPanePoint, component);
component.dispatchEvent(new MouseEvent(component, e.getID(), e.getWhen(), e.getModifiers(),
componentPoint.x, componentPoint.y, e.getClickCount(), e.isPopupTrigger()));
return true;//the event was redispatched
} else {
return false;//event was not redispatched
}
}
}
设置 glassPane (如果在框架可见之前将其设置为可见,这已经是一段时间的Swing故障了它不会被显示出来。)
这是您的固定代码:
{{1}}