[英]GUI doesn't respond to mouse click and drag while running from another class
I have 2 classes: TestingPanel
and SnipIt
. 我有2个类:
TestingPanel
和SnipIt
。
SnipIt
is used for selecting an area on the screen. SnipIt
用于选择屏幕上的区域。
TestingPanel
is the main frame, containing a button to run method Snip() and receiving the return values. TestingPanel
是主框架,包含一个按钮来运行方法Snip()并接收返回值。
If I test the SnipIt class separately, it works. 如果我单独测试SnipIt类,它可以工作。 But if I create a SnipIt object and run method Snip() from
TestingPanel
class, it doesn't work. 但是如果我创建一个SnipIt对象并从
TestingPanel
类运行方法Snip(),它就不起作用。 The GUI just freezes and doesn't respond to mouse click or drag event. GUI只是冻结并且不响应鼠标单击或拖动事件。 I guess something block the thread handle the mouse events but I'm not sure.
我想有些东西会阻止线程处理鼠标事件,但我不确定。
I have been stuck for couple hours and still don't know what caused the issue. 我被困了几个小时仍然不知道是什么导致了这个问题。 Please help.
请帮忙。
TestingPanel TestingPanel
package Testing;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TestingPanel {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestingPanel window = new TestingPanel();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public TestingPanel() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 200, 160);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnSnip = new JButton("Snip");
btnSnip.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getSelectionSize();
}
});
btnSnip.setBounds(47, 87, 89, 23);
frame.getContentPane().add(btnSnip);
}
private void getSelectionSize() {
int[] size = new int[4];
Thread worker = new Thread(new Runnable() {
public void run() {
SnipIt sn = new SnipIt();
sn.snip();
while(!sn.complete) {
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size[0] = sn.returnSize()[0];
size[1] = sn.returnSize()[1];
size[2] = sn.returnSize()[2];
size[3] = sn.returnSize()[3];
}
});
worker.start();
try {
worker.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(size[0] + " " + size[1] + " " + size[2] + " " + size[3]);
}
}
SnipIt SnipIt
package Testing;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class SnipIt {
private int recX = 0;
private int recY = 0;
private int recWidth = 0;
private int recHeight = 0;
public boolean complete = false;
/*
public static void main(String [] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
SnipIt s = new SnipIt();
s.snip();
}
});
}
*/
public void snip() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SnipItPane());
frame.setBounds(getVirtualBounds());
frame.setVisible(true);
}
@SuppressWarnings("serial")
public class SnipItPane extends JPanel {
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
private ControlPane controlPane;
public SnipItPane() {
setOpaque(false);
setLayout(null);
selectionPane = new SelectionPane();
controlPane = new ControlPane();
add(selectionPane);
add(controlPane);
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
controlPane.setLocation(mouseAnchor);
controlPane.setSize(0, 0);
}
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
int controlY = y + height + 5;
controlPane.setBounds(x, controlY, width, 25);
controlPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
Area area = new Area(bounds);
area.subtract(new Area(selectionPane.getBounds()));
g2d.setColor(new Color(102, 102, 102, 80));
g2d.fill(area);
}
}
@SuppressWarnings("serial")
public class ControlPane extends JPanel {
private JButton btnClose;
public ControlPane() {
setOpaque(false);
btnClose = new JButton("Save");
setLayout(new BorderLayout());
this.add(btnClose, BorderLayout.NORTH);
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
complete = true;
SwingUtilities.getWindowAncestor(ControlPane.this).dispose();
}
});
}
}
@SuppressWarnings("serial")
public class SelectionPane extends JPanel {
public SelectionPane() {
setOpaque(false);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
recX = getX();
recY = getY();
recWidth = getWidth();
recHeight = getHeight();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
float strokeWidth = 1.0f;
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(strokeWidth,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
public int[] returnSize() {
int[] size = new int[4];
size[0] = recX;
size[1] = recY;
size[2] = recWidth;
size[3] = recHeight;
return size;
}
}
You're running the Snipit application in a background thread and then freezing that thread with Thread.sleep and a while true block, something guaranteed to freeze the GUI. 您正在后台线程中运行Snipit应用程序,然后使用Thread.sleep和while true块冻结该线程,保证冻结GUI。 Read Lesson: Concurrency in Swing and then be sure to always run Swing applications on the single Swing event thread, and do any long running or sleeping code in a background thread.
阅读课程:Swing中的并发性,然后确保始终在单个Swing事件线程上运行Swing应用程序,并在后台线程中执行任何长时间运行或休眠代码。
Possible solutions to your issue: 您的问题的可能解决方案:
eg, 例如,
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class TestSnipit {
private static void createAndShowGui() {
boolean runTest = true;
if (runTest) {
TestingPanel.main(null);
} else {
SnipIt.main(null);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class TestingPanel {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestingPanel window = new TestingPanel();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public TestingPanel() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 200, 160);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnSnip = new JButton("Snip");
btnSnip.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getSelectionSize();
}
});
btnSnip.setBounds(47, 87, 89, 23);
frame.getContentPane().add(btnSnip);
}
private void getSelectionSize() {
int[] size = new int[4];
// !!
SnipIt sn = new SnipIt();
sn.snip(frame);
// Thread worker = new Thread(new Runnable() {
// public void run() {
// SnipIt sn = new SnipIt();
// sn.snip();
//
// while (!sn.complete) {
// try {
// Thread.sleep(800);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
//
size[0] = sn.returnSize()[0];
size[1] = sn.returnSize()[1];
size[2] = sn.returnSize()[2];
size[3] = sn.returnSize()[3];
// }
// });
//
// worker.start();
//
// try {
// worker.join();
// } catch (InterruptedException e1) {
// e1.printStackTrace();
// }
System.out.println(size[0] + " " + size[1] + " " + size[2] + " " + size[3]);
}
}
class SnipIt {
private int recX = 0;
private int recY = 0;
private int recWidth = 0;
private int recHeight = 0;
public boolean complete = false;
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
SnipIt s = new SnipIt();
s.snip(null); // !!
}
});
}
public void snip(Window owner) { // !!
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
// JFrame frame = new JFrame();
JDialog frame = new JDialog(owner, null, ModalityType.APPLICATION_MODAL); // !!
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // !!
frame.setLayout(new BorderLayout());
frame.add(new SnipItPane());
frame.setBounds(getVirtualBounds());
frame.setVisible(true);
}
@SuppressWarnings("serial")
public class SnipItPane extends JPanel {
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
private ControlPane controlPane;
public SnipItPane() {
setOpaque(false);
setLayout(null);
selectionPane = new SelectionPane();
controlPane = new ControlPane();
add(selectionPane);
add(controlPane);
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
controlPane.setLocation(mouseAnchor);
controlPane.setSize(0, 0);
}
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
int controlY = y + height + 5;
controlPane.setBounds(x, controlY, width, 25);
controlPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
Area area = new Area(bounds);
area.subtract(new Area(selectionPane.getBounds()));
g2d.setColor(new Color(102, 102, 102, 80));
g2d.fill(area);
}
}
@SuppressWarnings("serial")
public class ControlPane extends JPanel {
private JButton btnClose;
public ControlPane() {
setOpaque(false);
btnClose = new JButton("Save");
setLayout(new BorderLayout());
this.add(btnClose, BorderLayout.NORTH);
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
complete = true;
SwingUtilities.getWindowAncestor(ControlPane.this).dispose();
}
});
}
}
@SuppressWarnings("serial")
public class SelectionPane extends JPanel {
public SelectionPane() {
setOpaque(false);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
recX = getX();
recY = getY();
recWidth = getWidth();
recHeight = getHeight();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
float strokeWidth = 1.0f;
float dash1[] = { 10.0f };
BasicStroke dashed = new BasicStroke(strokeWidth, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
public int[] returnSize() {
int[] size = new int[4];
size[0] = recX;
size[1] = recY;
size[2] = recWidth;
size[3] = recHeight;
return size;
}
}
A side issue unrelated to your initial problem is your use of null layougs. 与您的初始问题无关的一个侧面问题是您使用了无效的问题。 While null layouts and
setBounds()
might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. 虽然null布局和
setBounds()
似乎可以像创建复杂GUI的最简单和最好的方式一样使用Swing GUI,但是你创建的Swing GUI越多,在使用它们时就会遇到更严重的困难。 They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one. 当GUI调整大小时,它们不会调整组件的大小,它们是增强或维护的皇室女巫,当它们被放置在滚动窗格中时它们完全失败,当它们在所有平台上观看时或者与原始平台不同的屏幕分辨率时它们看起来很糟糕。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.