【问题标题】:How to get JPanel to remember user-drawn graphics when panel is resized?调整面板大小时如何让 JPanel 记住用户绘制的图形?
【发布时间】:2014-02-25 21:27:35
【问题描述】:

我正在尝试制作一个程序,允许用户将音符放在五线谱上。有一个名为 SheetMusicPane 的类扩展了 JPanel,它以一堆从上到下绘制的五线谱开始。通过单击顶部工具栏中的按钮,用户可以选择要绘制的注释。工具栏上还有一个按钮,允许用户增加可用乐谱的数量(SheetMusicPane 设置在 JScrollPane 内)。当用户调整 SheetMusicPane 的大小时,我不知道如何复制音符。然而,最初的工作人员留在原地。

我尝试了 JPanel.repaint() 方法;没用。

调整大小非常简单:

JButton moreMusicButton = new JButton("Get More Sheet Music");
    tb.add(moreMusicButton);
    moreMusicButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
           smp.setPreferredSize(new Dimension(scrollSize.width, smp.getHeight() +     moreMusicAmount));
           smp.repaint();
        }
    });

如上所述,repaint() 没有做任何事情。

提前致谢!

添加笔记代码:

每个画笔记的按钮都调用这个方法(得到String“note” 来自按钮的 ActionCommand):

  public void getShape(final Graphics g, final String note) {
     MouseListener[] listeners = this.getMouseListeners();
     for (MouseListener ml : listeners) {
        this.removeMouseListener(ml);  //makes graphics stop drawing previous note
     }
     this.addMouseListener(new MouseListener() {
        public void mousePressed(MouseEvent e) {
        }
        public void mouseReleased(MouseEvent e) {
        }
        public void mouseEntered(MouseEvent e) {
        }
        public void mouseExited(MouseEvent e) {
        }
        public void mouseClicked(MouseEvent e) {
           Point p = MouseInfo.getPointerInfo().getLocation();
           addShape(g, p.x, p.y, note);
           int pitch = 12;
           piano.playNote(pitch);
           advance(1.0, piano);
           try { addToFile(pitch, note);}
           catch(FileNotFoundException fnfe) {}
           catch(IOException ioe) {}
        }
     });
  }

下面是面板本身的创建方式。它包含一组私有嵌套类,并开始显示简单、无音符的乐谱。

私有类 SheetMusicPane 扩展 JPanel {

  public SheetMusicPane() {
     final Graphics g = this.getGraphics();  
  } 

  //paints staffs
  public void paint(Graphics g) {
     super.paintComponent(g);
     for (int i = 0; (i - 1)*staffWidth < scrollSize.height + 100; i++) {
        int y = paddingNorth + i*staffWidth;
        Staff staff = new Staff(g, y, "treble");
     }
  }

  public void paintComponent(Graphics g) {
     super.paintComponent(g);
     for (String note : noteList) {
        addShape(g, 100, 200, note); 
     }
  }

  //takes in mouse info and calls addShape to draw notes on clicks
  public void getShape(final Graphics g, final String note) {  ... } //as shown above

  //draws a note
  private void addShape(Graphics g, int x, int y, String note) { ... }

  private void addToFile(int pitch, String note) throws FileNotFoundException, IOException { ...//adds note info to a file }

//此时只做五线谱表 私教人员{

  private Graphics g;
  private int y;
  private int[] pitches;

  public Staff(Graphics g, int y, String cleff) {  ...//draws the lines }

}

【问题讨论】:

  • 你是怎么画它们的?
  • 使用在 SheetMusicPane 上等待的鼠标侦听器。用户点击面板,点击发生的地方会出现注释
  • 刚刚添加了笔记代码
  • 哇,我想我从来没有见过这么不连贯的问题。请把自己放在我们的位置上:你认为我们怎么能在这么少信息的情况下想象你的代码出了什么问题?我的意思是,您的代码中有大约 1000 个问题,并且可能存在一百万个问题。请将此缩短为SSCCE,它实际上可以让我们看到问题(我怀疑它实际上是“许多问题”)
  • 您想用 SheetMusicPane 调整笔记的大小,还是只是不显示?

标签: java swing graphics jpanel


【解决方案1】:

您需要覆盖 Panel 的 paintComponent 方法。 您将要绘制的所有内容保存在一个数组(或列表)中,然后paintComponent 方法将它们绘制出来。 (每次重绘时)。

如果您在单击时绘制它们,则下次调用 repaint() 时,Panel 将被清除并使用 paintComponent 方法重新绘制。只要不调用 reapaint(),您的绘图就在面板上。

【讨论】:

  • 谢谢!我试试看
  • 好的,现在有了数组的想法,这里会发生什么:屏幕变黑,笔记被绘制,然后如果我向下滚动,五线谱出现,然后我无法向上滚动查看笔记了。显然,首先绘制笔记,然后调整面板的大小并使用五线谱重新绘制,即使我先在面板上调用 setPreferredSize() 然后重新绘制笔记(我通过覆盖 paintComponent 并在 resize 方法中调用它来做到这一点)。我会尝试添加更多代码来澄清事情。
  • 如果您使用 JScrollPane (docs.oracle.com/javase/tutorial/uiswing/components/…) 进行滚动,您应该没有问题
  • 现在可以使用了。我同时覆盖了paint() 和paintComponent(),它一定是先做paintComponent()(对于笔记),然后是paint()(用空白的工作人员覆盖它们)。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2018-10-23
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多