日安!我想使用全屏独占模式的标准摆动计时器。为此,我应用了一个SwingWorker来控制应该设置图形模式的事件。以下所有步骤都在run方法中执行。run()是从main调用的。1)首先,我创建了SwingWorker对象并覆盖了它的两个方法(doInBackground和done)。初始化是一个重要方法,因为它应该将所有需要的图形设置都设置为当前的JFrame对象,并将我的关键侦听器对象(称为screen_list)与其绑定:
...
worker = new SwingWorker<Window, Void>()
{
public Window doInBackground()
{
init();
return gdev.getFullScreenWindow();
}
public void done()
{
try {
disp = get();
}
catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
...2)然后我创建了我的屏幕监听器,它实现了一个ActionListener和一个键监听器,它在init()方法中绑定了disp作为KeyListener:
private void init()
{
...
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
disp.createBufferStrategy(2);
disp.setFocusTraversalKeysEnabled(false);
disp.addKeyListener((KeyListener)screen_list);
}
}
catch(IllegalArgumentException ex)
{
}
...
}3)我创建并初始化我的Swing计时器并启动它;4)最后我调用execute方法:
public void run(int pause, int delay)
{
...
try
{
screen_list = new ScreenListener();
tm = new Timer(delay, screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
worker.execute();
}
catch(Exception e)
{}
...
}正如我所写的那样,ScreenListener类实现了一个KeyListener和一个ActionListener。在ActionPerfomed方法中,我检查worker是否完成了它的工作(init方法),如果是,我将引用到当前显示模式并绘制一些内容:
class ScreenListener implements ActionListener, KeyListener
{
public void actionPerformed(ActionEvent e)
{
if(!worker.isDone())
{
return;
}
else
{
//gdev - GraphicsDevice type
disp = gdev.getFullScreenWindow();
if (disp != null)
{
...
draw(gr);
...
}
}
}
...
}为什么不处理来自键盘的事件?
发布于 2011-05-15 22:13:34
我使用了SwingWorker的功能,因为全屏模式还没有设置到计时器已经启动的时间。Ок。我放弃了使用SwingWorker。相反,我添加了一个简单的条件:
class ScreenListener implements ActionListener, KeyListener
{
public void actionPerformed(ActionEvent e)
{
System.out.println("ScreenListener: actionPerformed");
disp = gdev.getFullScreenWindow();
if(disp == null)
{
return;
}
else
{
//draw something
...
}
}}
所以现在我的run方法看起来像这样
public void run(int pause, int delay)
{
screen_list = new ScreenListener();
init();
try
{
tm = new Timer(delay, (ActionListener)screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
if(!tm.isRunning())
{
...
}
}
}我把我的disp设为可聚焦的:
private void init()
{
JFrame frame = new JFrame();
...
disp = new Window(frame);
DisplayMode[] dms = gdev.getDisplayModes();
DisplayMode use_dm = null;
if(gdev.isFullScreenSupported())
{
disp.setBackground(Color.CYAN);
disp.setForeground(Color.WHITE);
gdev.setFullScreenWindow(disp);
}
use_dm = getMatchMode(dms, def_dm);
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
...
disp.setFocusable(true);
disp.addKeyListener((KeyListener)screen_list);
...
}
}
catch(IllegalArgumentException ex)
{
ex.printStackTrace();
}
}但是我仍然不能捕捉我的键盘事件。KeyTyped,KeyPressed,KeyReleased还没有被调用,所以这是我在编程中的问题。
我的第一个目标是用全屏模式制作一个简单的动画。首先,我使用了一个简单的线程方法--睡眠--作为主线程。然后,我为同样的目的添加了一个摆动计时器,但正如你所看到的,我有一个问题:我不能让我的KeyListener工作。
发布于 2011-05-14 20:02:04
我并不是从
发起所有的Swing调用。初始化应该将所有需要的图形设置都设置为当前的JFrame对象,并将其绑定到键监听器。
好的,我看到你已经修改了你的代码:
private void init()
{
...
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
disp.createBufferStrategy(2);
disp.setFocusTraversalKeysEnabled(false);
disp.addKeyListener((KeyListener)screen_list);
}
}
catch(IllegalArgumentException ex)
{
}
...
}但是当你得到JFrame,设置它的显示模式和缓冲策略,它是焦点遍历业务,并添加一个键监听器时,你仍然需要在init中进行Swing调用。为什么这些调用是在后台线程中进行的,因为它们不会干扰Swing处理(所以不需要在后台完成),并且实际上是"Swing调用“,因为您正在使用它们更改Swing对象的状态。doInBackground用于运行长时间运行或cpu密集型进程,如果在EDT上运行,将冻结图形用户界面并使其无响应。您所显示的代码不能做到这一点。在后台线程中执行Swing调用的危险在于,虽然它可以在95%的时间内正常工作,但它会在意想不到的时候失败,导致应用程序崩溃和烧毁,通常是在最不合适的时候。
另外,为什么catch块是空的?我至少在里面放了一个ex.printStackTrace(),这样就不会盲目地运行了。
2)然后我创建了我的屏幕监听器,它实现了一个ActionListener和一个键监听器,它在init()方法中绑定了disp作为KeyListener:
那么,我说您正在向JFrame添加KeyListener,这样说对吗?我怀疑这是否会起作用,因为只有当绑定的组件具有焦点时,KeyListeners才会响应,这是JFrame很少会做或想要做的事情。也许您希望使用更通用的键绑定,因为这将在焦点和响应性方面提供更大的灵活性。
3)然后我创建并初始化我的Swing计时器并启动它;
好的
execute 4),最后调用
方法。-
public void run(int pause, int delay)
{
...
try
{
screen_list = new ScreenListener();
tm = new Timer(delay, screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
worker.execute();
}
catch(Exception e)
{}
...
}同样,您得到了一个空的catch块。
你能告诉我们更多关于你的具体问题吗?我们看到零星的不相关的代码,对它的功能有模糊的描述,但实际上还没有一个完整的概念。你能给我们更详细的描述你的计划和它的问题吗?您是否正在尝试按照安德鲁的建议创建SSCCE?如果你可以创建并发布这篇文章,我们将能够更好地测试和修改你的程序,并帮助你找到解决方案。祝你好运
发布于 2011-05-16 06:40:56
我决定了我的问题:
1)现在FullScreen类从JFrame扩展而来:
public class SimpleFullScreen extends JFrame
{
...
private synchronized void init()
{
Window disp = null;
//customize my display
setFocusable(true);
setResizable(false);
setIgnoreRepaint(true);
setUndecorated(true);
setBackground(Color.CYAN);
setForeground(Color.WHITE);
addKeyListener((KeyListener)screen_list);
DisplayMode[] dms = gdev.getDisplayModes();
DisplayMode use_dm = null;
if(gdev.isFullScreenSupported())
gdev.setFullScreenWindow(this);
use_dm = getMatchMode(dms, def_dm);
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
createBufferStrategy(2);
}
}
catch(IllegalArgumentException ex)
{
ex.printStackTrace();
}
}
...
}2)在run方法中添加循环,检查计时器是否在运行:
public void run(int pause, int delay)
{
Window disp = null;
screen_list = new ScreenListener();
init();
try
{
//Initialize and start timer
...
while(tm.isRunning())
{
System.out.println("Run: timer running");
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
try
{
if(!tm.isRunning())
{
disp = gdev.getFullScreenWindow();
disp.setVisible(false);
disp.dispose();
gdev.setFullScreenWindow(null);
System.exit(0);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}3) init、actionPerfomed和KeyPressed成为同步的方法。
所以ActionListener和KeyListener工作得很好。
感谢您的回复!
https://stackoverflow.com/questions/5998083
复制相似问题