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


}

Ответ 1

Объекты GUI Swing должны создаваться и обрабатываться только в потоке отправки событий. С этим изменением ваша программа работает. Типичным симптомом является то, что программа запускается при изменении размера кадра, что заставляет систему вызывать repaint() несколько раз.

Добавление: некоторые дополнительные вопросы заслуживают внимания,

  • Сделайте setVisible() последним.

  • Задержка запуска секвенсора может стоить переместиться на задний план.

  • Используйте именованные константы, например. ShortMessage.NOTE_ON, а не магические числа.

  • Мгновенный запуск 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);
        }
    }
}