2013-07-20 60 views
1

我是trying to paint JFrame when music is played,这些形状是随机创建的,没有任何计算,当有some music played there pops up a JFrame and these shapes are painted there,问题是,当我运行此代码时,没有音乐声音和形状绘制,但只是一个框弹出,没有别的,Plase检查这个代码,并帮助我纠正它..Java:随机播放JFrame上的随机图形

public class MusicBeatsDrawing { 

    static JFrame frame; 
    DrawPanel dp =new DrawPanel(); 
    public static void main(String[] args) 
    { 
     MusicBeatsDrawing mbd= new MusicBeatsDrawing(); 
     mbd.go(); 

    } 
    public void SetGui(){ 

     frame= new JFrame("Simple frame ; "); 
     frame.setBounds(100, 100, 200, 200); 
     frame.setContentPane(dp); 
     frame.setVisible(true); 

    } 

    public void go() 
    { 
     SetGui(); 
     try 
     { 
      Sequencer sequencer = MidiSystem.getSequencer(); 
      sequencer.open(); 

      Sequence seq= new Sequence(Sequence.PPQ, 4); 
      sequencer.addControllerEventListener(dp,new int [] {127}); 
      Track track = seq.createTrack(); 
      int r = 0; 
      for (int i = 0; i < 60 ; i+= 4) { 

       r = (int) Math.random()*50; 
       track.add(MakeEvent(144,1,r,100,i)); 
       track.add(MakeEvent(176,1,127,0,i)); 
       track.add(MakeEvent(128,1,r,100,i)); 
      } 
      sequencer.setSequence(seq); 
      sequencer.start(); 
     } 

     catch(Exception e) 
     {e.printStackTrace(); } 
    } 

    public MidiEvent MakeEvent(int one , int two , int three , int four , int tick) 
    { 
     MidiEvent event= null; 
     try 
     {  
      ShortMessage sm= new ShortMessage(); 
      sm.setMessage(one,two, three, four); 
      event= new MidiEvent(sm , tick); 


     } catch (InvalidMidiDataException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return event; 
    } 
    class DrawPanel extends JPanel implements ControllerEventListener 
    {  
     boolean msg= false ; 


     public void paintComponent(Graphics g) 
     { 
      if(msg){ Graphics2D g2d= (Graphics2D) g; 

      int red= (int) (Math.random()*255); 
      int green= (int) (Math.random()*255) ; 
      int blue= (int) (Math.random()*255); 

      g.setColor(new Color(red, green , blue)); 

      int height= (int)Math.random()*255; 
      int width= (int)Math.random()*255; 
      int x= (int)Math.random()*255; 
      int y= (int)Math.random()*255; 
      g.fillRect(height, width, x, y);   
      msg = false; 
      } 
     } 
     @Override 
     public void controlChange(ShortMessage event) { 
      msg= true; 
      repaint();   
     }} 


} 
+0

1为[SSCCE](http://sscce.org/)。 – trashgod

回答

3

的Swing GUI对象应当建立并仅在event dispatch thread操纵。有了这个改变,你的程序就可以运行一个明显的症状是程序在调整帧大小时运行,这会导致系统反复调用repaint()

附录:一些额外的问题值得关注,

  • setVisible()最后

  • 序列器启动延迟可能值得移到背景。

  • 使用命名常量,例如ShortMessage.NOTE_ON,而不是magic numbers

  • 实例化Random供以后使用。

  • 遵循Java命名约定。

image

修订SSCCE:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.util.Random; 
import javax.sound.midi.ControllerEventListener; 
import javax.sound.midi.InvalidMidiDataException; 
import javax.sound.midi.MidiEvent; 
import javax.sound.midi.MidiSystem; 
import javax.sound.midi.MidiUnavailableException; 
import javax.sound.midi.Sequence; 
import javax.sound.midi.Sequencer; 
import javax.sound.midi.ShortMessage; 
import javax.sound.midi.Track; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* @see http://stackoverflow.com/a/17767350/230513 
*/ 
public class MidiDrawing { 

    private static final Random R = new Random(); 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new MidiDrawing()::display); 
    } 

    public void display() { 
     JFrame frame = new JFrame("Midi Drawing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     DrawPanel dp = new DrawPanel(); 
     frame.add(dp); 
     Sequencer sequencer = initSequencer(dp); 
     JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 
     p.add(new JButton(new AbstractAction("Start") { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       sequencer.setTickPosition(0); 
       sequencer.start(); 
      } 
     })); 
     frame.add(p, BorderLayout.SOUTH); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private Sequencer initSequencer(DrawPanel dp) { 
     try { 
      Sequencer sequencer = MidiSystem.getSequencer(); 
      Sequence seq = new Sequence(Sequence.PPQ, 3); 
      Track track = seq.createTrack(); 
      int n = 60; // middle C 
      for (int i = 0; i < 3 * 12; i += 3) { 
       track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, 0, 0, n), i)); 
       track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n, 127), i)); 
       track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n + 3, 127), i)); 
       track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n, 127), i + 3)); 
       track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n + 3, 127), i + 3)); 
       n++; 
      } 
      sequencer.open(); 
      sequencer.setSequence(seq); 
      sequencer.addControllerEventListener(dp, new int[]{0}); 
      return sequencer; 
     } catch (InvalidMidiDataException | MidiUnavailableException e) { 
      e.printStackTrace(System.err); 
     } 
     return null; 
    } 

    private static class DrawPanel extends JPanel implements ControllerEventListener { 

     private final Font font = this.getFont().deriveFont(24f); 
     private int data; 

     @Override 
     public void paintComponent(Graphics g) { 
      g.setColor(Color.getHSBColor(R.nextFloat(), 1, 1)); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      g.setFont(font); 
      g.setColor(Color.black); 
      g.drawString(String.valueOf(data), 8, g.getFontMetrics().getHeight()); 
     } 

     @Override 
     public void controlChange(ShortMessage event) { 
      data = event.getData2(); 
      repaint(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(256, 128); 
     } 
    } 
}