MultiThreading Swing Event Dispatcher Thread

Вече имам публикация, свързана с проблема с многопоточността, но имам някои нови въпроси + код. Имам проект за игра с много топки и той изисква да анализирам XML файл, за да получа информация за топката (като размер, скорост, начална позиция и т.н.). Сега исках да създам различна нишка за анализ на XML файла, но не мога да намеря начин да го направя. Ето моят код:

main() започва тук:

public class BounceBallApp extends JFrame{

    public BounceBallApp()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("BounceBallApp");          
        setSize(300,300);       
        setVisible(true);
        add(new BallWorld());
        validate();
    }

    public static void main(String[] args) 
    {
        /*Create main GUI in the Event Dispatch Thread*/
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new BounceBallApp(); //main frame
            }
        });

    }
}

В рамките на конструктора за BallWorld() имам вътрешен клас BallContainer(), който съдържа бутон Старт:

jbtStart.addActionListener(new ActionListener()
            {public void actionPerformed(ActionEvent e)
            {
                //Populate the ballList arraylist
                if(filePathField.getText().equals(" "))
                {
                    JOptionPane.showMessageDialog(null, "Please input the XML file","Information", JOptionPane.INFORMATION_MESSAGE);        
                }
                else
                {
                    XMLFilePath = filePathField.getText();

                    ballList = new BallList(XMLFilePath);//I want to put this in a thread
                    JOptionPane.showMessageDialog(null,"Game started!","Bouncing Balls",JOptionPane.INFORMATION_MESSAGE);
                    for(Ball ball:ballList.ballsArrayList) 
                    {
                        timer.setDelay(1000/ball.getSpeed()); //change the delay of the timer to the ball's speed
                        timer.start(); //start the timer
                        bTimer = true; //timer is now on                    
                    }
                }

            }
            });

        }

Сега проблемът е, че ако поставя процеса на анализиране в друга нишка, тогава трябва да изчакам ballsArrayList да се запълни, преди да мога да продължа с приложението. Мислех да използвам invokeAndWait(), но прочетох, че този метод не може да бъде извикан от нишката за изпращане на събития. И така, как мога да постигна това? Или дори си струва? Освен това исках да преместя изчислението за преместване на топката (изчисляване на координатите x,y) към нишка, но отново не знам как да го приложа.

for(Ball ball:ballList.ballsArrayList) 
            {
                ball.draw(g);                   
                ball.move(ballContainerWidth,ballContainerHeight,buttonPanel.getHeight());                  
            }

public void move(int ballContainerWidth,int ballContainerHeight,int buttonPanelHeight)
 {

     if((this.getX()+this.getsize()+this.getDx()) > ballContainerWidth) 
        {
            this.setDx(-Math.abs(this.getDx()));
        }

        //the height/depth to which the balls can bounce is the (main ball container height) minus (button panel height)
        if((this.getY()+this.getsize()+this.getDy()) > ballContainerHeight-buttonPanelHeight) 
        {
            this.setDy(-Math.abs(this.getDy()));
        }

        if((this.getX()-this.getsize()) < 0 )
        {
            this.setDx(Math.abs(this.getDx()));
        }

        if((this.getY()-this.getsize()) < 0 )
        {
            this.setDy(Math.abs(this.getDy()));
        }


        int newX = (int)Math.round((this.getX()+this.getDx()));
        int newY = (int)Math.round((this.getY()+this.getDy()));
        this.setX(newX);
        this.setY(newY);
 }

Съжалявам за дългия пост, но многонишковостта е нещо ново за мен. Малко съм объркан за това.


person user1719821    schedule 03.11.2012    source източник


Отговори (1)


Първоначално зареждане на файлове

Аз лично бих избрал един от следните подходи

  • Увеличете времето за стартиране на вашата програма, като анализирате всички файлове по време на стартиране. За няколко XML файла това натоварване може да е много малко. Ако отнеме твърде много време, можете да помислите за показване на начален екран
  • Заредете XML файловете при натискане на бутона за стартиране, но покажете лента за напредъка, докато зареждането приключи. Започнете играта след това. SwingWorker може да ви помогне с това. Примери могат да бъдат намерени в документацията на Swing или тук на SO.

Актуализиране на позицията на топката

Ако изчислението е толкова лесно, колкото показаното тук, просто бих използвал javax.swing.Timer, за да актуализирам позицията на редовни интервали от време, и ще направя изчислението в нишката за изпращане на събития.

Ако искате да направите изчислението на фонова нишка само за упражнението, аз все пак бих избрал изчисление на позицията на фонова нишка. Изчислението трябва да използва локални променливи, които са известни само на тази фонова нишка. След като новата позиция бъде изчислена, актуализирайте позицията на топката в нишката за изпращане на събития, като използвате SwingUtilities#invokeLater. Това ви позволява да получите достъп до позицията по време на операцията paint, без да се налага да се притеснявате за проблеми с нишката. Вероятно по-лесно, отколкото да се забърквате с брави.

person Robin    schedule 03.11.2012