0

I am trying to add several pictures (using PictureBox) of music notes to a Music Staff Form.

In a certain Mouse Event (MouseUp), a Music Note is created, and a music note should appear on the screen. However, only when the first note is created does the image appear on the screen. For every other note created after the first one, the image does not show up.

In the below method, the Music Note is created:

private void Key_MouseUp(object sender, MouseEventArgs e)
    {
        foreach (MusKey mk in panel1.Controls)
        {
            if (sender == mk) //true for the specific key pressed on the Music Keyboard
            {
                if (e.Button == MouseButtons.Left)
                {
                    timer1.Enabled = false;
                    sp.Stop();
                    string bNoteShape = null;

                    // ticks -> milliseconds
                    if (count >= 16)
                    {
                        bNoteShape = "SemiBreve";
                        duration = 1024;
                    }
                    else if (count >= 8 && count <= 15)
                    {
                        bNoteShape = "DotMinim";
                        duration = 768;
                    }
                    else if (count >= 4 && count <= 7)
                    {
                        bNoteShape = "Crotchet";
                        duration = 384;
                    }
                    else if (count >= 2 && count <= 3)
                    {
                        bNoteShape = "Quaver";
                        duration = 128;
                    }
                    else
                    {
                        bNoteShape = "Semi-Quaver";
                        duration = 90; //63 is too short
                    }

                    MusicNote mn = new MusicNote(mk.getMusicNote(), duration, bNoteShape, mk.getNote());
                    Notes.Add(mn);
                    mn.picturebox1.Location = new Point(xLoc1, yLoc1);

                    panel2.Controls.Add(mn.picturebox1); //adding MusicNote component to MusicStaff (panel2) collection

                }
            }
        }
    }

When the Note is created, it is sent to the MusicNote constructor:

public MusicNote(int iNotepitch, int iDuration, String iBnoteShape, String iNote)
    {
        notepitch = iNotepitch;
        noteduration = iDuration;
        noteshape = iBnoteShape;
        note = iNote;

        picturebox1.ImageLocation = NoteImage_path + noteshape + ".bmp";
        picturebox1.BackColor = Color.Transparent;

        picturebox1.Location = new Point(xLoc, yLoc);
        xLoc = xLoc + 15;
    }

I have tried initializing the location (and incrementing xLoc) both through the constructor, and also in the form itself in method Key_MouseUp, but neither seems to make a difference.

The logic seems to be correct, as the picture of the first music note always loads, but I cannot understand why every other note after the first does not show up on my screen.

Any help will be appreciated, thanks!

Edit: perhaps maybe there is another alternative to PictureBox that I could use to store the music notes?

Luke Xuereb
  • 73
  • 12
  • 1
    Please show the declaration of `picturebox1`. – Richardissimo Jan 02 '19 at 19:53
  • Wrong approach. A single picture box can only hold 1 picture so it won't work as soon as you have a second picture. You might be able to get the picture move or change but first note would be lost. Using multiple picture controls would not be appropriate either (assuming that you want to display more than a few notes) as it waste ressource. You really need to draw notes yourself in a canvas. – Phil1970 Jan 02 '19 at 19:57
  • I am not sure that creating a picture box object or adding to the list of control is actually enough to create it. At least, you probably need to make it visible so the actual control get created. – Phil1970 Jan 02 '19 at 20:06
  • There are many things that could be wrong with your code but you don't provide all relevant code. For example, depending where and how `xLoc` is declared, you might get the expected location or a newly initialized location at 0. – Phil1970 Jan 02 '19 at 20:16
  • @Phil1970 static int xLoc = 0; - Located in the MusicNote class – Luke Xuereb Jan 02 '19 at 21:00
  • @Phil1970 the picturebox is being created. The first music note always appears, the problem is the preceeding notes. – Luke Xuereb Jan 02 '19 at 21:01
  • @LukeXuereb Try to use **Spy++** to validate if controls are created, visible and at expected location (and that the panel is big enough). Also provide a MCVE (https://stackoverflow.com/help/mcve). – Phil1970 Jan 02 '19 at 21:43
  • My suggestion, if you want to use PictureBoxes as container for an Image, is to transform you `MusicNote` class in a class that is derived from `PictureBox` (`public class MusicNote : PictureBox { }`) and ditch the `picturebox1` control. So you'll actually return a `PictureBox` object when you `new` your class. – Jimi Jan 03 '19 at 01:08
  • @Jimi is there another option aside from PictureBox that I could use to store the images of the Music Notes? – Luke Xuereb Jan 03 '19 at 10:08
  • Many options. But *store* and *show* are different concept that may require different tools. I would use a custom class that stores a List of `Note` sub-class objects, where the sub-class could have a Bitmap type member that stores a specific Image of a Note, the Note type and other details that may define it. The main class would manage a *Grid* where all `Note` class objects are displayed, coupling the `Note` object with a Rectagle element that defines the position of each `Note` in the Grid. – Jimi Jan 03 '19 at 18:42
  • Something like [this](https://stackoverflow.com/a/50513149/7444103), but using Bitmaps objects instead of Color objects (that code is VB.Net, but it's the concept that matter). – Jimi Jan 03 '19 at 18:42

1 Answers1

0

well it looks like your not initializing a new "picturebox1"

    picturebox1 = new PictureBox(); //Add this
    picturebox1.ImageLocation = NoteImage_path + noteshape + ".bmp";

edit: Ok in general we need a few things to add a control to a form.

  1. the new Control (look like you have that) 2

  2. Adding it to the parent control (looks like you have that)

    panel2.Controls.Add(mn.picturebox1); //adding MusicNote component to MusicStaff (panel2) collection

  3. redraw the control -- this can happen automatically when you resize the form or you can call refresh(on the panel) after the new control is added to the panel.

    panel2.Controls.Add(mn.picturebox1); 
    panel2.Refresh();
    
Zobo
  • 76
  • 4
  • While it might work to create additional controls, it won't be efficient except for trivial music sheet. – Phil1970 Jan 02 '19 at 20:00
  • It is initialized in the MusicNote class: public PictureBox picturebox1 = new PictureBox(); – Luke Xuereb Jan 02 '19 at 20:05
  • 1
    that's fair if the picturebox1 is part of the MusicNote. but given the name it looks like a tool box doped auto_name. – Zobo Jan 02 '19 at 20:06
  • @Zobo in what part of the code am I to include panel.Refresh()? Is it something that must occur each time a MusicNote is created? – Luke Xuereb Jan 02 '19 at 21:02