2016-01-19 11 views
5

काम नहीं कर रहा है मैंने कभी भी Timer एस के साथ काम नहीं किया है, इसलिए मेरी समस्या शायद वास्तव में बेवकूफ है। मेरा प्रोग्राम एक सर्कल खींचता है जो लाल होता है और यादृच्छिक सेकंड के बाद सर्कल को अपना रंग हरे रंग में बदलना चाहिए। मैंने बस एक स्विंग टाइमर बनाया है जैसा कि आप कोड में नीचे देख सकते हैं। और यह actionPerformed() विधि में प्रवेश करता है लेकिन यह रंग नहीं बदलता है। क्या आप मेरी मदद किसी भी तरह बदलते रंगों के साथ मेरी समस्या को ठीक करने में मदद कर सकते हैं?स्विंग टाइमर के अंदर चित्रकारी

मेरे कोड:

package igrica; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Random; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 


public class ChangingCircle implements ActionListener{ 

JFrame frame; 

Timer timer; 
Random r; 

public static void main(String[] args) { 
    ChangingCircle gui = new ChangingCircle(); 
    gui.go(); 
} 

public void go() { 
    frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    MyPanel panel = new MyPanel(); 

    frame.getContentPane().add(BorderLayout.CENTER, panel); 
    frame.setSize(300, 300); 
    frame.setVisible(true); 
} 

public void actionPerformed(ActionEvent event) { 
    frame.repaint(); 
} 

class MyPanel extends JPanel { 
    public void paintComponent(Graphics g) { 


     g.setColor(Color.red); 
     g.fillOval(100, 100, 100, 100); 

     Random r = new Random(); 

     Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 
      public void actionPerformed(ActionEvent ev) { 
       System.out.println("Timer out"); 
       g.setColor(Color.green); 
       g.fillOval(100, 100, 100, 100); 
      } 
     }); 
     timer.start(); 
    } 
} 
} 
+0

अंग्रेजी युक्ति: "वाक्य" के साथ हर वाक्य शुरू न करें, आप एक कहानी नहीं कह रहे हैं। – user1803551

+0

मुझे पता है कि मुझे नहीं करना चाहिए, लेकिन मुझे नहीं पता कि कौन सा शब्द वाक्य शुरू करता है। xD –

+0

बस "तो" को हटा दें और वाक्य ठीक है जैसा कि है। – user1803551

उत्तर

8

आपके कोड में काफी गड़बड़ है। इस प्रयास करें:

public class ChangingCircle { 

    Color color = Color.RED; 
    MyPanel panel = new MyPanel(); 

    public static void main(String[] args) { 

     SwingUtilities.invokeLater(() -> { 
      ChangingCircle gui = new ChangingCircle(); 
      gui.go(); 
     }); 
    } 

    public void go() { 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     frame.getContentPane().add(panel, BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible(true); 

     Random r = new Random(); 
     Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 

      public void actionPerformed(ActionEvent ev) { 

       System.out.println("Timer"); 
       color = Color.GREEN; 
       panel.repaint(); 
      } 
     }); 
     timer.setRepeats(false); 
     timer.start(); 
    } 

    class MyPanel extends JPanel { 

     private int size = 100, loc = 100; 

     @Override 
     public void paintComponent(Graphics g) { 

      super.paintComponent(g); 
      g.setColor(color); 
      g.fillOval(loc, loc, size, size); 
     } 

     @Override 
     public Dimension getPreferredSize() { 

      return new Dimension(size + loc, size + loc); 
     } 
    } 
} 

विचार है कि टाइमर केवल आकार तैयार हो की संपत्ति में परिवर्तन और उसके बाद repaint() कॉल परिवर्तन को दिखाने के लिए है। paintComponent को जब भी इसकी आवश्यकता होती है, तब भी कहा जाता है, यहां तक ​​कि जल्दी उत्तराधिकार में और जल्दी वापस आना चाहिए।

विशिष्ट नोट्स:

  • Start Swing from the EDT
  • paintComponent के बाहर से टाइमर बनाएं और शुरू करें क्योंकि इसे कई बार कहा जाता है और यह कई टाइमर बनाएगा और शुरू करेगा।
  • आपको शायद टाइमर को दोहराने के लिए सेट करना चाहिए।
  • पर कॉल करें paintComponent के अंदर पहली चीज़ के रूप में।
  • आपको लगता है कि ActionListener है जो कुछ भी नहीं करता है।

सामान्य टिप्स:

  • जब लागू @Override एनोटेशन का प्रयोग करें।
  • अपने आकार को मैन्युअल रूप से सेट करने के बजाय फ्रेम पर pack() पर कॉल करें और @OverridegetPreferredSize आपके द्वारा पेंट किए गए घटक की विधि।जो भी आप आकर्षित करते हैं उसके आधार पर एक सार्थक आकार दें।
  • add(component, location) का उपयोग करें और दूसरी तरफ (बहिष्कृत) नहीं।
  • फ़ील्ड का उपयोग न करें जब स्थानीय चर (Random r उदाहरण के लिए)।
  • Color.red के बजाय अपरकेस निरंतर नाम (Color.RED) का उपयोग करें।
+0

धन्यवाद आपने इसे इतना विस्तार से वर्णित किया है! –

6

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

उदा।

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Random; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

public class ChangingCircle { 
    JFrame frame; 

    public static void main(String[] args) { 
     ChangingCircle gui = new ChangingCircle(); 
     gui.go(); 
    } 

    public void go() { 
     frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     MyPanel panel = new MyPanel(); 

     frame.getContentPane().add(BorderLayout.CENTER, panel); 
     frame.setSize(300, 300); 
     frame.setVisible(true); 
    } 

    public void actionPerformed(ActionEvent event) { 
     frame.repaint(); 
    } 

    class MyPanel extends JPanel { 
     private Random r = new Random(); 
     private boolean draw = false; 

     public MyPanel() { 
      Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { 
       public void actionPerformed(ActionEvent ev) { 
        draw = true; 
        repaint(); 
       } 
      }); 
      timer.setRepeats(false); 
      timer.start(); 
     } 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (draw) { 
       g.setColor(Color.red); 
       g.fillOval(100, 100, 100, 100); 
      } 
     } 
    } 
} 

इसके अलावा, सुपर ओवर पेंट कॉम्पोनेंट विधि को अपने ओवरराइड से कॉल करना न भूलें।

यदि आपको रंग बदलने की ज़रूरत है, तो जेपीनेल को रंगीन फ़ील्ड दें, जिसे color कहा जाता है और टाइमर के भीतर से इसका मान बदलें, और फिर repaint() पर कॉल करें। फिर पेंट कॉम्पोनेंट के भीतर, अंडाकार को आकर्षित करने के लिए उस फ़ील्ड के मान का उपयोग करें। इसके अलावा, इस स्थिति में, टाइमर दोहराना चाहिए, इसलिए उस स्थिति में timer.setRepeats(false) से छुटकारा पाएं।

+0

लेकिन अगर पूर्व में रंग लगातार बदलना होगा तो क्या करना है। लाल से हरा और फिर हरा से लाल, क्या वह भी काम करेगा? –

+0

@ डोमागोज साबोलिक: फिर टाइमर में रंगीन रंग की स्थिति बदलती है और पेंट कॉम्पोनेंट विधि में इसका उपयोग करें। –

+0

@DomagojSabolic: उत्तर देने के लिए संपादन देखें। –

0

टाइमर एसिंक्रोनस और paintComponent टाइमर के काम को पूरा करने से पहले समाप्त होता है।

+0

लेकिन मेरा System.out.println प्रत्येक बार टाइमर खत्म करता है और प्रिंट करता है –

+0

इस नमूने में आपके पास एक जेफ्रेम और एक जेपीनल है, यदि आप बहुत सारे घटक जोड़ते हैं तो यह कार्यान्वयन अपवाद फेंक देगा क्योंकि जब आपका टाइमर जी में परिवर्तन करने का प्रयास करता है , उसी समय एक और घटक –

+0

को पुनर्निर्मित करने के लिए जी के उसी उदाहरण का उपयोग करेगा, मुझे नहीं लगता कि यह प्रश्न का उत्तर कैसे देता है। 'पेंटकंपोनेंट' * टाइमर शुरू होने या उसकी क्रिया करने से पहले * समाप्त/कर सकते हैं। एसिंक्रोनिज्म का मुद्दा अप्रासंगिक है। – user1803551

संबंधित मुद्दे