我正在为多用户绘图程序开发一个项目,并且遇到了一个问题,我的GUI已锁定。多线程锁定Java Swing GUI
我已经完成了大部分的程序,除了这个错误,它是一个相当大的程序,所以我试图在较小的程序中重现错误。
在这个较小的程序中,我有2个JFrame。他们都可以通过点击并拖动鼠标来绘制。辅助JFrame是一个睡眠10秒的线程,然后将你绘制的内容发送到另一个要显示的帧。
然而,一旦在主框架已经接收到图像从所述第二框架,所述GUI锁死和主框架不再能在绘制。
我目前使用的SwingUtilities.invokeLater()方法跟...共事。在寻找答案时,我找到了SwingWorker类,但我想先看看是否有一个简单的解决方案,然后再对代码进行大量重写,以使其与SwingWorker一起工作。
感谢您的阅读。我的代码如下。此外,这是我第一次在这里发布。我似乎在格式化代码时遇到了一些麻烦,所以如果它出错,我会提前道歉。我会尽我所能解决它。
package gui_thread_test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
public class DrawPanel extends JComponent
{
private Image canvas;
private int x, y, prevX, prevY;
Graphics2D g2;
public DrawPanel()
{
setDoubleBuffered(false);
addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
prevX = e.getX();
prevY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter()
{
@Override
public void mouseDragged(MouseEvent e)
{
x = e.getX();
y = e.getY();
g2.drawLine(prevX, prevY, x, y);
repaint();
prevX = x;
prevY = y;
}
});
}
@Override
public void paintComponent(Graphics g)
{
if (canvas == null)
{
canvas = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) canvas.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.drawImage(canvas, 0, 0, null);
}
public synchronized void updateCanvas(Image _canvas)
{
canvas = _canvas;
repaint();
}
public Image getImage()
{
return canvas;
}
}
-
package gui_thread_test;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ThreadTest extends JFrame implements Runnable
{
private Image canvas;
private Graphics2D g2;
private DrawPanel panel;
private DrawPanel threadPanel;
public ThreadTest(DrawPanel _panel)
{
super("Secondary");
panel = _panel;
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(500,500));
this.setMinimumSize(new Dimension(500,500));
this.setVisible(true);
threadPanel = new DrawPanel();
this.add(threadPanel);
}
public void paintComponent(Graphics g)
{
if (canvas == null)
{
canvas = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) canvas.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.drawImage(canvas, 0, 0, null);
}
@Override
public void run() {
//Sleep thread for 10 seconds to give time to draw on the image
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
//Posts the message to the server chat window
panel.updateCanvas(threadPanel.getImage());
}
});
}
}
-
package gui_thread_test;
import java.awt.Dimension;
import javax.swing.JFrame;
public class GUI_Thread_Test {
public static void main(String[] args)
{
JFrame window = new JFrame("Main");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setPreferredSize(new Dimension(500,500));
window.setMinimumSize(new Dimension(500,500));
DrawPanel draw = new DrawPanel();
window.add(draw);
Thread testThread = new Thread(new ThreadTest(draw));
testThread.start();
window.pack();
window.setVisible(true);
}
}
传输实际上是通过我的流套接字连接来的。我只是使用线程睡眠作为例子来重现我的锁定错误。但是,我检查了你的代码,它似乎解决了这个问题。我现在要更深入地研究它。我想我应该能够弄清楚我的问题。也许不使用BufferedImages是我出错的地方。谢谢。 – Lucas 2013-04-05 04:16:33