Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我的Swing应用程序可能不是线程安全的——但不知道为什么_Java_Multithreading_Swing - Fatal编程技术网

Java 我的Swing应用程序可能不是线程安全的——但不知道为什么

Java 我的Swing应用程序可能不是线程安全的——但不知道为什么,java,multithreading,swing,Java,Multithreading,Swing,应评论员的要求进行编辑。我希望这是合规的 第一个帖子!试图理解为什么我的Swing应用程序不能从一个面板前进到下一个面板。以下是代码的一般流程: public class MainWindow { JFrame mainFrame; ChangeablePanel currentScreen; // abstract and extends JPanel, has getters & setters for a Timer (swing timer), a String (nextSc

应评论员的要求进行编辑。我希望这是合规的

第一个帖子!试图理解为什么我的Swing应用程序不能从一个面板前进到下一个面板。以下是代码的一般流程:

public class MainWindow {

JFrame mainFrame;
ChangeablePanel currentScreen; // abstract and extends JPanel, has getters &
setters for a Timer (swing timer), a String (nextScreen), and an Image 
(background image).  also has a close(AWTEvent e) method that simply calls 
"this.setVisible(false);"

public MainWindow() {
    mainFrame = new JFrame("New Arcana");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
    setTitleFrame();
} // MainFrame constructor

public void changeFrame(String frameType, String frameName) {               
    switch (frameType) {
        case "Title":
            setTitleFrame();
            break;
        case "Town":
            setTownFrame(frameName);
            break;
        case "Movie":
            setMovieFrame(frameName);               
            break;
        default:
            break;
    } // switch     
} // changeFrame

private void setTitleFrame() {      
    currentScreen = new TitlePanel();
    currentScreen.addComponentListener(new ScreenChangeListener());
    ...             
    mainFrame.setContentPane(currentScreen);
    mainFrame.setSize(titleScreenLength, titleScreenHeight); // put constants here if you want
    mainFrame.setLocationRelativeTo(null);
    mainFrame.setVisible(true);
} // setTitleFrame

private void setTownFrame(String townName) {        
    currentScreen = new TownPanel(townName);
    currentScreen.addComponentListener(new ScreenChangeListener());
    ...     
    mainFrame.setContentPane(currentScreen);        
    mainFrame.setSize(townScreenLength, townScreenHeight); // put constants here if you want
    mainFrame.setVisible(true);     
} // setTownFrame

private void setMovieFrame(String movieName) {      
    currentScreen = new MoviePanel(movieName);
    currentScreen.addComponentListener(new ScreenChangeListener());
    ...
    mainFrame.setContentPane(currentScreen);
    mainFrame.setSize(titleScreenLength, titleScreenHeight); // put constants here if you want      
    mainFrame.setVisible(true);     
} // setMovieFrame

private class ScreenChangeListener implements ComponentListener {
    @Override
    public void componentHidden(ComponentEvent e) {
        gotoNextScreen(e);
    }

    public void componentMoved(ComponentEvent e) {}

    public void componentResized(ComponentEvent e) {}

    public void componentShown(ComponentEvent e) {}     
} // ScreenChangeListener

public void gotoNextScreen(ComponentEvent e) {        
    changeFrame(currentScreen.getNextScreen(), null);   
}
} // MainWindow

public class Start {
...
public static void main(String[] args) {
    initialize();   

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new MainWindow();
        }
    });   
} // main
...
} // Start

public class TitlePanel extends ChangeablePanel implements ActionListener {

JButton newGame, continueGame;

public TitlePanel() {       
    setFocusable(true);     
    ...

    newGame = new JButton("New Game");
    continueGame = new JButton("Continue");     

    newGame.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            setNextScreen("Movie");
            close(e);               
        }       
    });

    add(newGame);
    add(continueGame);

    createTimer(10, this);
    getTimer().start();
} // TitlePanel constructor

@Override
public void actionPerformed(ActionEvent e) {
    repaint();      
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;        
    drawTitleScreen(g2d);       
} // paintComponent

private void drawTitleScreen(Graphics2D g2d) {
    g2d.drawImage(getBGImage(), 0, 0, null);
    newGame.setLocation(170, 550);
    continueGame.setLocation(605, 550);
} // drawTitleScreen
} // TitlePanel

public class MoviePanel extends ChangeablePanel implements ActionListener { 

public MoviePanel(String movieName) {       
    setFocusable(true); 

    addKeyListener(new AnyKeyActionListener());
    ...
    createTimer(10, this);
    getTimer().start();
} // TitlePanel constructor

@Override
public void actionPerformed(ActionEvent e) {
    repaint();
}

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;        
    drawMovie(g2d);     
} // paintComponent 

private void drawMovie(Graphics2D g2d) {
    g2d.drawImage(getBGImage(), 0, 0, null);        
} // drawTitleScreen    

private class AnyKeyActionListener extends KeyAdapter {     
    public void keyTyped(KeyEvent e) {
        setNextScreen("Town");
        close(e);
    } // keyPressed     
} // listener to check for keystrokes   
} // MoviePanel
随着应用程序基于用户输入(目前,只有MoviePanel和TownPanel被编码)的发展,大型机将填充更多的帧,它们的代码与此相当类似——我也粘贴了MoviePanel

执行在上面基于KeyAdapter的侦听器之后中断。然而,当我在Eclipse中以带断点的调试模式运行我的应用程序时,这确实完成了它应该做的事情,并从MoviePanel前进到TownPanel。正因为如此,我怀疑线程是罪魁祸首。注意,我在上面的代码块上尝试了许多不同的SwingUtilities.invokeLater()技术组合,但没有改变任何东西。任何帮助都将不胜感激;谢谢

执行以下操作:

  • 用于在GUI事件调度线程上创建的invokeLater
  • 在构造期间不重新绘制()
  • 最后可见
特别是在事件侦听器上,再次使用invokeLater,让按钮等响应,然后也使用响应执行操作

public static void main(String[] args) {
    ...
    SwingUtilities.invokeLater() {
        @Override()
        new Runnable() {
            new MainFrame().setVisible(true);
        }
    };        
}

代码审查

TitlePanel.TitlePanel
中,最好使用绝对布局(即null),而不是在绘制代码中使用
setLocation

    setLayout(null);
    newGame = new JButton("New Game");
    continueGame = new JButton("Continue");
    newGame.setBounds(170, 550, 120, 24);
    continueGame.setBounds(605, 550, 120, 24);
可更改面板中。关闭
同时确保
计时器.stop()

主窗口中
使用
调用器

public void gotoNextScreen(ComponentEvent e) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            changeFrame(currentScreen.getNextScreen(), null);
        }
    });   
}
MoviePanel
中,我看不到
addKeyListener
能够正常工作;也许是遗漏的代码?或者这就是你看到的错误? 此外,我发现一个简单的
repaint()
是可疑的;我本以为会发生这样的事情:

public void actionPerformed(ActionEvent e) {
    invalidate();
    repaint(10L);
}

changeFrame()方法在哪里?1)不要扩展框架或面板2)在EDT上启动GUI。3)考虑秋千。4) 为了更快地获得更好的帮助,请发布一个。查看您的
setTitleFrame()
方法,它不会在
EDT
上调用,因此这不是一个线程安全的方法。在
Swing
中。像
pack()/setVisible(true/false)这样的调用必须在
EDT-Event Dispatcher线程中`Billy M-SSCCE并不意味着“发布更少的代码”。它的实际含义是,通过去除无关的东西,将您的问题简化为一个小而完整的工作程序。你发布的不是SSCCE,因为1)它不是可运行的代码,2)包含了一堆无关的东西,3)遗漏了一些重要的东西。谢谢大家的反馈,因为这是我的第一篇stackoverflow文章,我将在标准方面提供任何帮助@Stephen C,很难说什么是无关的,什么不是,因为我的问题是线程安全——任何事情都可能很重要。无论如何,我现在粘贴了更多的代码。谢谢,谢谢,乔普,不幸的是,同样的问题。用最新代码更新了主要问题。再次感谢Joop,请参阅上述解决方案以获得解决方案。我感谢所有这些帮助。