Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The right way to add Graphics to a JPanel in a music notation software

I have been working on a music notation software that I want to use to train my music students on sight-reading.

I want to know whether I am taking the right approach or if there is a better way.

I have managed to make the clef, notes and staff objects using unicodes and fonts that support music notation using code like this:

public static void spaceStaff(Graphics g){
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Font font = new Font("Bravura", Font.PLAIN, 32);
    g2.setFont(font);
    g2.drawString("\uD834\uDD1A", note.spacing-2, staffDistance);
    note.spacing = note.spacing + 16;
}

I then have a class called Surface that paints the notes onto a JPanel:

public class Surface extends JPanel {
@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    staff.spaceStaff(g);
    clef.drawGclef(g);//not given in example code above
    note.drawCrotchet(g, note.B1);//not given in example code above
   }
}

I am using this code to start the application and display the music notes:

public class SightreadHelper extends JFrame {

public SightreadHelper(){
    initUI();
}

private void initUI() {

    JButton button = new JButton("add notes"); //explanation for this button below
    button.setSize(150, 75);
    button.setVisible(true);
    add( button );

    button.addActionListener( new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            repaint();//this doesn't work as I expect: explanation below
        }
    });

    Surface srf = new Surface();
    add(new Surface());
    setSize(700, 1000);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            SightreadHelper srh = new SightreadHelper();
            srh.setVisible(true);
        }
    });
  }

}

The button is supposed to add the notes at the end of the existing notes, but it doesn't. This image explains what happens after I click the button.

Am I using the right procedure for doing what I want to do? Thanks a lot for your help. I saw this question but it didnt help me: Repaint Applets in JAVA without losing previous contents

like image 490
Josiah Avatar asked Feb 06 '23 05:02

Josiah


1 Answers

in general your approach may work, but it is way to simple structured to work correctly, if you tend to push it to an application. You are lacking a data model here. Your software paints the notes directly without a model that represents the internal state.

You should have a look at Model View Controller abstraction pattern. and develop a datamodel first, that has nothing to do with rendering the notes.

Then you start develop a visualisation for the single elements e.g. the notes. You will compose the components in a panel depended on what the data model tells you and render them. Thats what you should do in the doPaintComponent Method.

When you hit the button add note, the following steps should happen:

  1. add a note to your model

  2. your model creates a ui event that results calling the repaint method and maybe even the layout method repainting your ui, ideally repainting only the parts that need to be repainted.

If you are not seeing something during rendering, make sure to first check the following things:

  1. is your rendering code called by the awt - thread?
  2. is your component visible?
  3. is the position you are trying to paint correct?

You should perhaps read one ore more tutorials on developing custom swing components like Oracle Tutorial Custom Swing component.

I know the answer is probably not really helping you in the short run, but I believe it is better to understand the concepts of UI development before trying to make your code somehow run.

like image 111
Melv_80 Avatar answered May 01 '23 06:05

Melv_80