gpt4 book ai didi

java - 从另一个类运行时,GUI 不响应鼠标单击和拖动

转载 作者:行者123 更新时间:2023-11-29 04:33:13 25 4
gpt4 key购买 nike

我有 2 个类:TestingPanelSnipIt

SnipIt 用于选择屏幕上的区域。

TestingPanel 是主框架,包含一个按钮来运行方法 Snip() 并接收返回值。

如果我单独测试 SnipIt 类,它会起作用。但是,如果我创建一个 SnipIt 对象并从 TestingPanel 类运行方法 Snip(),它就不起作用。 GUI 只是卡住并且不响应鼠标单击或拖动事件。我猜有些东西会阻止线程处理鼠标事件,但我不确定。

我已经被困了几个小时,仍然不知道是什么导致了这个问题。请帮忙。

测试面板

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]);
}
}

截图

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;
}
}

最佳答案

您在后台线程中运行 Snipit 应用程序,然后使用 Thread.sleep 和 while true block 卡住该线程,保证卡住 GUI。阅读Lesson: Concurrency in Swing然后确保始终在单个 Swing 事件线程上运行 Swing 应用程序,并在后台线程中执行任何长时间运行或 hibernate 的代码。

您的问题的可能解决方案:

  • 使 Snipit 窗口成为未修饰的模态对话框。这样,调用代码的程序流在对话框可见时停止,并在不再可见时恢复。
  • 或者使 Snipit 窗口 JFrame 成为类的实例字段,并允许外部类为其添加监听器,以便在关闭时通知它们。

例如,

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;
}
}

与您最初的问题无关的一个附带问题是您对空布局的使用。虽然空布局和 setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整组件的大小,它们是增强或维护的皇家女巫,当放置在滚动 Pane 中时它们会完全失败,当在所有平台或与原始屏幕分辨率不同的屏幕分辨率上查看时,它们看起来很糟糕.

关于java - 从另一个类运行时,GUI 不响应鼠标单击和拖动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42935345/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com