Java:在播放音乐的JFrame上绘制随机形状

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

 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(); }} } 

应该在事件派发线程上构造和操作Swing GUI对象。 通过此更改,您的程序可以正常运行 一个明显的症状是,当您调整帧大小时程序会运行,这会导致系统重复调用repaint()

附录:一些其他问题值得关注,

  • 最后使setVisible()

  • 定序器启动延迟可能值得转移到后台。

  • 使用命名常量,例如ShortMessage.NOTE_ON ,而不是幻数 。

  • 实例化Random以供以后使用。

  • 遵循Java命名约定。

图片

修订的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); } } }