2012-08-07 46 views
6

स्विंगवर्कर का उपयोग करने वाले कुछ वास्तविक समय सिमुलेशन कोड का परीक्षण करते हुए मैंने देखा कि मेरा जीयूआई हमेशा 30 एफपीएस पर चल रहा है, और नहीं, कम नहीं। जब भी उपयोगकर्ता एप्लिकेशन के साथ इंटरैक्ट करता है (जैसे माउस मूव) या जब स्विंगवर्कर की प्रक्रिया() विधि को कॉल किया जाता है तो मैं जीयूआई अपडेट करता हूं। स्विंगवर्कर अभी कुछ भी नहीं करता है, यह सिर्फ जीयूआई से माउस स्थान पकड़ता है और इसे प्रकाशित() और प्रक्रिया() विधियों के माध्यम से क्लोन के रूप में वापस भेजता है (मैं यह देखने के लिए कर रहा हूं कि मैं क्या कर सकता हूं और कर सकता हूं थ्रेड के बीच संचार करते समय नहीं करते क्योंकि मल्टीथ्रेडिंग अभी भी मेरे लिए बिल्कुल नया है)। मेरे पास कहीं भी कोई टाइमर नहीं है, स्विंगवर्कर की प्रक्रिया() विधि जीयूआई पर repaint() कॉल करती है, इसलिए मैं सोच रहा था कि जीयूआई 30 एफपीएस पर अपडेट करने का क्या कारण बनता है? क्या डिफ़ॉल्ट रूप से जीयूआई में सक्रिय बनाम एक बनाम की तरह हो सकता है या क्या यह स्विंगवर्कर में प्रक्रिया() विधि का कुछ व्यवहार है? और आखिरकार: क्या उच्च फ्रेमरेट प्राप्त करने का कोई तरीका है?जीयूआई 30 एफपीएस पर चल रहा है?

यहाँ एक sscce जो यह व्यवहार दिखाता है:

public class SimGameTest implements Runnable { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new SimGameTest()); 
    } 

    @Override 
    public void run() { 
     MainWindow mainWindow = new MainWindow(new Game()); 

     mainWindow.setLocationRelativeTo(null); 
     mainWindow.setVisible(true); 
    } 
} 

public class MainWindow extends JFrame { 
    private Game  game; 
    private GamePanel gamePanel; 

    public MainWindow(Game game) { 
     this.game = game; 

     createAndShowGUI(); 

     startGame(); 
    } 

    private void startGame() { 
     GameSim gameSim = new GameSim(game, gamePanel); 
     gameSim.execute(); 
    } 

    private void createAndShowGUI() { 
     setTitle("Sim game test"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(false); 

     JPanel contentPane = new JPanel(new GridBagLayout()); 

     gamePanel = new GamePanel(game); 
     contentPane.add(gamePanel); 

     add(contentPane); 
     pack(); 
    } 
} 

public class Game { 
    public Point   mouseLocation  = new Point(); 
    public Point   clonedMouseLocation = new Point(); 
} 

public class GameSim extends SwingWorker<Point, Point> { 
    private Game    game; 
    private GamePanel   gamePanel; 

    public GameSim(Game game, GamePanel gamePanel) { 
     this.game = game; 
     this.gamePanel = gamePanel; 
    } 

    @Override 
    protected Point doInBackground() throws Exception { 
     while (true) { 
      publish((Point) game.mouseLocation.clone()); 
     } 
    } 

    @Override 
    protected void process(List<Point> pointList) { 
     game.clonedMouseLocation = pointList.get(pointList.size() - 1); 
     gamePanel.repaint(); 
    } 
} 

public class GamePanel extends JPanel { 
    private Game    game; 
    private long    lastTime; 

    public GamePanel(Game game) { 
     this.game = game; 
     setPreferredSize(new Dimension(512, 512)); 
    addMouseMotionListener(new GamePanelListener();); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     // draw background 
     g.setColor(new Color(0, 0, 32)); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     g.setColor(new Color(192, 192, 255)); 
     g.drawString(game.clonedMouseLocation.x + ", " + game.clonedMouseLocation.y, 10, 502); 

     long now = System.nanoTime(); 
     long timePassed = now - lastTime; 
     lastTime = now; 
     double fps = ((double) 1000000000/timePassed); 
     g.drawString("fps: " + fps, 10, 482); 
    } 

    private class GamePanelListener extends MouseInputAdapter { 
     @Override 
     public void mouseMoved(MouseEvent e) { 
      if (contains(e.getPoint())) { 
       game.mouseLocation = e.getPoint(); 
      } 
     } 
    } 
} 

मैं एक और संस्करण जहां मैं सिर्फ बार जीयूआई रंगा गया था की संख्या की गणना और स्क्रीन पर गिनती दिखाने बनाया है, और ऐसा लगता है एक में वृद्धि होना प्रति सेकंड 30 की दर, तो मुझे लगता है कि एफपीएस गणना समस्या नहीं है।

+2

कृपया एक प्रश्न [एसएससीई] (http://sscce.org/) शामिल करने के लिए अपना प्रश्न संपादित करें जो आपके द्वारा वर्णित दर प्रदर्शित करता है। – trashgod

+2

आप फ्रेम दर कैसे प्राप्त कर रहे हैं? –

+0

क्षमा करें, एक एसएससी – FinalArt2005

उत्तर

10

यह EventQueue को पता चला है Runnable की SwingWorker पदों उदाहरणों बिल्कुल DELAY के साथ एक javax.swing.Timer का उपयोग कर।

private static class DoSubmitAccumulativeRunnable 
     extends AccumulativeRunnable<Runnable> implements ActionListener { 
    private final static int DELAY = (int) (1000/30); 
    ... 
} 

आप उच्च फ्रेम दर प्राप्त कर सकते हैं, लेकिन javax.swing.SwingWorker के साथ नहीं। आप source से SwingWorker बना सकते हैं, लेकिन अंत में आप Runnable के उदाहरणों के साथ थ्रेड को संतृप्त कर सकते हैं। एक विकल्प मॉडल को फ्लैट आउट करना और इसे समय-समय पर नमूना देना है, जैसा कि here दिखाया गया है।

+0

मैंने 'javax.swing.SwingWorker' के बारे में 'javax.swing.Timer' का उपयोग करके _not_ नहीं किया था। – trashgod

+1

अब हम सब करते हैं - धन्यवाद! –

+0

मैंने पाया कि कल [इस सवाल] का जवाब देते हुए (http://stackoverflow.com/questions/11825281/java-swing-running-on-edt) – Robin