3

コメント投稿者の依頼により編集。これが準拠していることを願っています。

最初の投稿!Swingアプリケーションが1つのパネルから次のパネルに進まない理由を理解しようとしています。コードの一般的なフローは次のとおりです。

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

MainFrameには、ユーザー入力に基づいてアプリケーションが進むにつれて、より多くのフレームが入力されます(現在、MoviePanelとTownPanelのみがコーディングされています)。これらのコードは、これとかなり類似しています。MoviePanelも貼り付けました。

上記のKeyAdapterベースのリスナーの後で実行が中断します。ただし、ブレークポイントを使用してEclipseでデバッグモードでアプリケーションを実行すると、これは実際に本来の動作を実行し、MoviePanelからTownPanelに進みます。このため、ここではスレッディングが原因であると思われます。上記のコードブロックでSwingUtilities.invokeLater()テクニックのさまざまな組み合わせを試しましたが、何も変更されなかったことに注意してください。どんな助けでもいただければ幸いです。ありがとう!

4

1 に答える 1

1

以下をせよ:

  • GUIイベントディスパッチスレッドで作成するためのinvokeLater
  • 構築中にrepaint()はありません
  • setVisible last

特にイベントリスナーでは、ボタンなどをレスポンシブにするために再び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);

ChangeablePanel.close確認してtimer.stop()ください。

MainWindow使用中invokeLater

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);
}
于 2012-06-16T20:01:02.357 に答える