【问题标题】:Using addMouseListener() and paintComponent() for JPanel使用 JPanel 的 addMouseListener() 和 paintComponent()
【发布时间】:2012-08-25 20:55:35
【问题描述】:

这是我的previous 问题的后续。我已经尽可能地简化了事情,但它仍然不起作用!虽然我使用getGraphics() 得到了好处。

非常感谢您详细解释这里出了什么问题。我怀疑我在这里使用addMouseListener() 方法的方式有问题。

EDIT 完全重写了代码。虽然仍然无法正常工作。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class RunClass{

    static MainClass1 inst1 = new MainClass1();



    public static void main(String args[]){

        JFrame frame1 = new JFrame();
        frame1.add(inst1);
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame1.setTitle("NewPaintToolbox");
        frame1.setSize(200, 200);
        frame1.setLocationRelativeTo(null);     
        frame1.setVisible(true);                
    }
}

class MainClass1 extends JPanel implements MouseListener, MouseMotionListener{

    int xvar=30;
    int yvar=30;
    //static PaintClass22 inst1 = new PaintClass22();


    @Override
    public void mouseClicked(MouseEvent arg0) {
        // TODO Auto-generated method stub
        xvar = arg0.getX();
        yvar = arg0.getY();
        repaint(xvar,yvar,10,10);

    }   

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseDragged(MouseEvent arg0) {
        // TODO Auto-generated method stub
        xvar = arg0.getX();
        yvar = arg0.getY();
        repaint(xvar,yvar,10,10);

    }

    @Override
    public void mouseMoved(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public void paintComponent(Graphics g){

        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(xvar, yvar, 10, 10);     

    }



}

【问题讨论】:

    标签: java swing awt jpanel actionlistener


    【解决方案1】:

    首先,PaintClass11 从未使用过...

    其次,即使是这样,您也要创建两个单独的 PaintClass22 实例,一个放置在框架上,一个您尝试更新...因此屏幕上永远不会发生更新。

    您不需要两个单独的类。将 PaintClass11PaintClass22 合并到一个类中并将其添加到您的框架中

    【讨论】:

    • 我听从了你的建议,请看代码。 paintComponent 在初始化时工作一次,但显然 MouseListener 有问题。
    【解决方案2】:

    注意你方法中的错字:

    public void paintComponent(Graphics g){
    
        super.paintComponents(g);
        g.setColor(Color.RED);
        g.fillRect(varx, vary, 10, 10);     
    
    }
    

    当您调用super.paintComponents(复数)时,您的方法名为paintComponent。如果你重写了一个方法(我强烈建议添加一个@Override 标记以避免由于拼写错误而实际上你没有重写任何东西),比如paintComponent,请确保调用super 方法(相同的方法,而不是另一个)。

    【讨论】:

      【解决方案3】:

      您必须将 mouseListener 添加到面板。默认情况下,这不会像您预期的那样发生;-)

      MainClass1() {
          addMouseListener(this);
      }
      

      顺便说一句:不建议公开仅供内部使用的公共 api。因此,不要让面板实现 MouseListener(强制公开曝光),而是让面板创建和使用 MouseListener:

      private MouseListener mouseListener;
      MainClass1() {
         mouseListener = createMouseListener();
         addMouseListener(mouseListener);
      }
      
      protected MouseListener createMouseListener() {
          MouseListener l = new MouseListener() {
      
          }
         return l;
      }
      

      顺便说一句 2:在有限区域调用重绘并不是您想要的 (?) - 它 暂时 将正方形添加到绘画中,每当重绘整个面板时它们就会丢失 (与 getGraphics 的效果相同)。取决于你真正想要什么,

      • 在最近点击的位置绘制一个正方形:调用 repaint()
      • 在曾经点击过的所有位置绘制方块:将位置存储在列表中并实施重绘以循环遍历该列表。在这里你可以调用带参数的重绘,但是为什么要麻烦呢?

      【讨论】:

      • 好的,谢谢,这行得通。是的,如果添加了更改(例如调整窗口大小),我需要保留用户的输入。在MouseActionListener 实现之前是否可以避免运行paintComponent
      【解决方案4】:

      这不是您问题的直接答案,但知道(或至少怀疑)您希望提供什么(一个简单的绘画程序),我建议从基于 BufferedImage 的这种方法开始作为绘画表面..

      import java.awt.*;
      import java.awt.RenderingHints.Key;
      import java.awt.event.*;
      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.Map;
      
      import javax.imageio.ImageIO;
      import javax.swing.*;
      import javax.swing.border.*;
      import javax.swing.event.ChangeEvent;
      import javax.swing.event.ChangeListener;
      import javax.swing.filechooser.FileFilter;
      import javax.swing.filechooser.FileNameExtensionFilter;
      
      public class BasicPaint {
      
          /** Reference to the original image. */
          private BufferedImage originalImage;
          /** Image used to make changes. */
          private BufferedImage canvasImage;
          /** The main GUI that might be added to a frame or applet. */
          private JPanel gui;
          /** The color to use when calling clear, text or other 
           * drawing functionality. */
          private Color color = Color.WHITE;
          /** General user messages. */
          private JLabel output = new JLabel("You DooDoodle!");
      
          private BufferedImage colorSample = new BufferedImage(
                  16,16,BufferedImage.TYPE_INT_RGB);
          private JLabel imageLabel;
          private int activeTool;
          public static final int SELECTION_TOOL = 0;
          public static final int DRAW_TOOL = 1;
          public static final int TEXT_TOOL = 2;
      
          private Point selectionStart; 
          private Rectangle selection;
          private boolean dirty = false;
          private Stroke stroke = new BasicStroke(
                  3,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND,1.7f);
          private RenderingHints renderingHints;
      
          public JComponent getGui() {
              if (gui==null) {
                  Map<Key, Object> hintsMap = new HashMap<RenderingHints.Key,Object>();
                  hintsMap.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                  hintsMap.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                  hintsMap.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                  renderingHints = new RenderingHints(hintsMap); 
      
                  setImage(new BufferedImage(320,240,BufferedImage.TYPE_INT_RGB));
                  gui = new JPanel(new BorderLayout(4,4));
                  gui.setBorder(new EmptyBorder(5,3,5,3));
      
                  JPanel imageView = new JPanel(new GridBagLayout());
                  imageView.setPreferredSize(new Dimension(480,320));
                  imageLabel = new JLabel(new ImageIcon(canvasImage));
                  JScrollPane imageScroll = new JScrollPane(imageView);
                  imageView.add(imageLabel);
                  imageLabel.addMouseMotionListener(new ImageMouseMotionListener());
                  imageLabel.addMouseListener(new ImageMouseListener());
                  gui.add(imageScroll,BorderLayout.CENTER);
      
                  JToolBar tb = new JToolBar();
                  tb.setFloatable(false);
                  JButton colorButton = new JButton("Color");
                  colorButton.setMnemonic('o');
                  colorButton.setToolTipText("Choose a Color");
                  ActionListener colorListener = new ActionListener() {
                      public void actionPerformed(ActionEvent arg0) {
                          Color c = JColorChooser.showDialog(
                                  gui, "Choose a color", color);
                          if (c!=null) {
                              setColor(c);
                          }
                      }
                  };
                  colorButton.addActionListener(colorListener);
                  colorButton.setIcon(new ImageIcon(colorSample));
                  tb.add(colorButton);
      
                  setColor(color);
      
                  final SpinnerNumberModel strokeModel = 
                          new SpinnerNumberModel(3,1,16,1);
                  JSpinner strokeSize = new JSpinner(strokeModel);
                  ChangeListener strokeListener = new ChangeListener() {
                      @Override
                      public void stateChanged(ChangeEvent arg0) {
                          Object o = strokeModel.getValue();
                          Integer i = (Integer)o; 
                          stroke = new BasicStroke(
                                  i.intValue(),
                                  BasicStroke.CAP_ROUND,
                                  BasicStroke.JOIN_ROUND,
                                  1.7f);
                      }
                  };
                  strokeSize.addChangeListener(strokeListener);
                  strokeSize.setMaximumSize(strokeSize.getPreferredSize());
                  JLabel strokeLabel = new JLabel("Stroke");
                  strokeLabel.setLabelFor(strokeSize);
                  strokeLabel.setDisplayedMnemonic('t');
                  tb.add(strokeLabel);
                  tb.add(strokeSize);
      
                  tb.addSeparator();
      
                  ActionListener clearListener = new ActionListener() {
                      public void actionPerformed(ActionEvent arg0) {
                          int result = JOptionPane.OK_OPTION;
                          if (dirty) {
                              result = JOptionPane.showConfirmDialog(
                                      gui, "Erase the current painting?");
                          }
                          if (result==JOptionPane.OK_OPTION) {
                              clear(canvasImage);
                          }
                      }
                  };
                  JButton clearButton = new JButton("Clear");
                  tb.add(clearButton);
                  clearButton.addActionListener(clearListener);
      
                  gui.add(tb, BorderLayout.PAGE_START);
      
                  JToolBar tools = new JToolBar(JToolBar.VERTICAL);
                  tools.setFloatable(false);
                  JButton crop = new JButton("Crop");
                  final JRadioButton select = new JRadioButton("Select", true);
                  final JRadioButton draw = new JRadioButton("Draw");
                  final JRadioButton text = new JRadioButton("Text");
      
                  tools.add(crop);            
                  tools.add(select);          
                  tools.add(draw);            
                  tools.add(text);
      
                  ButtonGroup bg = new ButtonGroup();
                  bg.add(select);
                  bg.add(text);
                  bg.add(draw);
                  ActionListener toolGroupListener = new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent ae) {
                          if (ae.getSource()==select) {
                              activeTool = SELECTION_TOOL;
                          } else if (ae.getSource()==draw) {
                              activeTool = DRAW_TOOL;
                          } else if (ae.getSource()==text) {
                              activeTool = TEXT_TOOL;
                          }
                      }
                  };
                  select.addActionListener(toolGroupListener);
                  draw.addActionListener(toolGroupListener);
                  text.addActionListener(toolGroupListener);
      
                  gui.add(tools, BorderLayout.LINE_END);
      
                  gui.add(output,BorderLayout.PAGE_END);
                  clear(colorSample);
                  clear(canvasImage);
              }
      
              return gui;
          }
      
          /** Clears the entire image area by painting it with the current color. */
          public void clear(BufferedImage bi) {
              Graphics2D g = bi.createGraphics();
              g.setRenderingHints(renderingHints);
              g.setColor(color);
              g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
      
              g.dispose();
              imageLabel.repaint();
          }
      
          public void setImage(BufferedImage image) {
              this.originalImage = image;
              int w = image.getWidth();
              int h = image.getHeight();
              canvasImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
      
              Graphics2D g = this.canvasImage.createGraphics();
              g.setRenderingHints(renderingHints);
              g.drawImage(image, 0, 0, gui);
              g.dispose();
      
              selection = new Rectangle(0,0,w,h); 
              if (this.imageLabel!=null) {
                  imageLabel.setIcon(new ImageIcon(canvasImage));
                  this.imageLabel.repaint();
              }
              if (gui!=null) {
                  gui.invalidate();
              }
          }
      
          /** Set the current painting color and refresh any elements needed. */
          public void setColor(Color color) {
              this.color = color;
              clear(colorSample);
          }
      
          private JMenu getFileMenu(boolean webstart){
              JMenu file = new JMenu("File");
              file.setMnemonic('f');
      
              JMenuItem newImageItem = new JMenuItem("New");
              newImageItem.setMnemonic('n');
              ActionListener newImage = new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent arg0) {
                      BufferedImage bi = new BufferedImage(
                              360, 300, BufferedImage.TYPE_INT_ARGB);
                      clear(bi);
                      setImage(bi);
                  }
              };
              newImageItem.addActionListener(newImage);
              file.add(newImageItem);
      
              if (webstart) {
                  //TODO Add open/save functionality using JNLP API
              } else {
                  //TODO Add save functionality using J2SE API
                  file.addSeparator();
                  ActionListener openListener = new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent arg0) {
                          if (!dirty) {
                              JFileChooser ch = getFileChooser();
                              int result = ch.showOpenDialog(gui);
                              if (result==JFileChooser.APPROVE_OPTION ) {
                                  try {
                                      BufferedImage bi = ImageIO.read(
                                              ch.getSelectedFile());
                                      setImage(bi);
                                  } catch (IOException e) {
                                      showError(e);
                                      e.printStackTrace();
                                  }
                              }
                          } else {
                              // TODO
                              JOptionPane.showMessageDialog(
                                      gui, "TODO - prompt save image..");
                          }
                      }
                  };
                  JMenuItem openItem = new JMenuItem("Open");
                  openItem.setMnemonic('o');
                  openItem.addActionListener(openListener);
                  file.add(openItem);
      
                  ActionListener saveListener = new ActionListener() {
      
                      @Override
                      public void actionPerformed(ActionEvent e) {
                          JFileChooser ch = getFileChooser();
                          int result = ch.showSaveDialog(gui);
                          if (result==JFileChooser.APPROVE_OPTION ) {
                              try {
                                  File f = ch.getSelectedFile();
                                  ImageIO.write(BasicPaint.this.canvasImage, "png", f);
                                  BasicPaint.this.originalImage = BasicPaint.this.canvasImage;
                                  dirty = false;
                              } catch (IOException ioe) {
                                  showError(ioe);
                                  ioe.printStackTrace();
                              }
                          }
                      }
                  };
                  JMenuItem saveItem = new JMenuItem("Save");
                  saveItem.addActionListener(saveListener);
                  saveItem.setMnemonic('s');
                  file.add(saveItem);
              }
      
              if (canExit()) {
                  ActionListener exit = new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent arg0) {
                          // TODO Auto-generated method stub
                          System.exit(0);
                      }
                  };
                  JMenuItem exitItem = new JMenuItem("Exit");
                  exitItem.setMnemonic('x');
                  file.addSeparator();
                  exitItem.addActionListener(exit);
                  file.add(exitItem);
              }
      
              return file;
          }
      
          private void showError(Throwable t) {
              JOptionPane.showMessageDialog(
                      gui, 
                      t.getMessage(), 
                      t.toString(), 
                      JOptionPane.ERROR_MESSAGE);
          }
      
          JFileChooser chooser = null;
      
          public JFileChooser getFileChooser() {
              if (chooser==null) {
                  chooser = new JFileChooser();
                  FileFilter ff = new FileNameExtensionFilter("Image files", ImageIO.getReaderFileSuffixes());
                  chooser.setFileFilter(ff);
              }
              return chooser;
      
          }
      
          public boolean canExit() {
              boolean canExit = false;
              SecurityManager sm = System.getSecurityManager();
              if (sm==null) {
                  canExit = true;
              } else {
                  try {
                      sm.checkExit(0);
                      canExit = true; 
                  } catch(Exception stayFalse) {
                  }
              }
      
              return canExit;
          }
      
          public JMenuBar getMenuBar(boolean webstart){
              JMenuBar mb = new JMenuBar();
              mb.add(this.getFileMenu(webstart));
              return mb;
          }
      
          public static void main(String[] args) {
              Runnable r = new Runnable() {
                  @Override
                  public void run() {
                      try {
                          UIManager.setLookAndFeel(
                                  UIManager.getSystemLookAndFeelClassName());
                      } catch (Exception e) {
                          // use default
                      }
                      BasicPaint bp = new BasicPaint();
      
                      JFrame f = new JFrame("DooDoodle!");
                      f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                      f.setLocationByPlatform(true);
      
                      f.setContentPane(bp.getGui());
                      f.setJMenuBar(bp.getMenuBar(false));
      
                      f.pack();
                      f.setMinimumSize(f.getSize());
                      f.setVisible(true);
                  }
              };
              SwingUtilities.invokeLater(r);
          }
      
          public void text(Point point) {
              String text = JOptionPane.showInputDialog(gui, "Text to add", "Text");
              if (text!=null) {
                  Graphics2D g = this.canvasImage.createGraphics();
                  g.setRenderingHints(renderingHints);
                  g.setColor(this.color);
                  g.setStroke(stroke);
                  int n = 0;
                  g.drawString(text,point.x,point.y);
                  g.dispose();
                  this.imageLabel.repaint();
              }
          }
      
          public void draw(Point point) {
              Graphics2D g = this.canvasImage.createGraphics();
              g.setRenderingHints(renderingHints);
              g.setColor(this.color);
              g.setStroke(stroke);
              int n = 0;
              g.drawLine(point.x, point.y, point.x+n, point.y+n);
              g.dispose();
              this.imageLabel.repaint();
          }
      
          class ImageMouseListener extends MouseAdapter {
      
              @Override
              public void mousePressed(MouseEvent arg0) {
                  // TODO Auto-generated method stub
                  if (activeTool==BasicPaint.SELECTION_TOOL) {
                      selectionStart = arg0.getPoint();
                  } else if (activeTool==BasicPaint.DRAW_TOOL) {
                      // TODO
                      draw(arg0.getPoint());
                  } else if (activeTool==BasicPaint.TEXT_TOOL) {
                      // TODO
                      text(arg0.getPoint());
                  } else {
                      JOptionPane.showMessageDialog(
                              gui, 
                              "Application error.  :(", 
                              "Error!", 
                              JOptionPane.ERROR_MESSAGE);
                  }
              }
      
              @Override
              public void mouseReleased(MouseEvent arg0) {
                  if (activeTool==BasicPaint.SELECTION_TOOL) {
                      selection = new Rectangle(
                              selectionStart.x,
                              selectionStart.y,
                              arg0.getPoint().x,
                              arg0.getPoint().y);
                  }
              }
          }
      
          class ImageMouseMotionListener implements MouseMotionListener {
      
              @Override
              public void mouseDragged(MouseEvent arg0) {
                  reportPositionAndColor(arg0);
                  if (activeTool==BasicPaint.SELECTION_TOOL) {
                      selection = new Rectangle(
                              selectionStart.x,
                              selectionStart.y,
                              arg0.getPoint().x-selectionStart.x,
                              arg0.getPoint().y-selectionStart.y);
                  } else if (activeTool==BasicPaint.DRAW_TOOL) {
                      draw(arg0.getPoint());
                  }
              }
      
              @Override
              public void mouseMoved(MouseEvent arg0) {
                  reportPositionAndColor(arg0);
              }
      
          }
      
          private void reportPositionAndColor(MouseEvent me) {
              String text = "";
              if (activeTool==BasicPaint.SELECTION_TOOL) {
                  text += "Selection (X,Y:WxH): " + 
                          (int)selection.getX() +
                          "," +
                          (int)selection.getY() +
                          ":" +
                          (int)selection.getWidth() +
                          "x" +
                          (int)selection.getHeight();
              } else {
                  text += "X,Y: " + (me.getPoint().x+1) + "," + (me.getPoint().y+1);
              }
              output.setText(text);
          }
      }
      

      这个来源非常不完整。

      • 它有很多部分带有// TODO
      • dirty 属性已声明,但从未以任何有意义的方式使用。 ..

      这只是我今天一起破解的东西,并认为应该在它达到发布限制之前显示出来。

      哦,不要去寻找任何'OO设计',因为我没有放入任何东西。如果有的话,那只是偶然。这段代码旨在演示什么是可能的以及如何开始做。

      【讨论】:

      • 除了两个版本(两个版本的代码都很棒!!!),我正在等待超过 5 个投票,奇怪......我的帽子下来
      • 哇,太棒了!你花了多长时间完成它?很遗憾我不能接受两个答案。
      • 我一整天都在工作,时不时地。我一直打算提供一个小的“绘画应用程序”。很长一段时间了。正是你的问题启发了我去 DooDoodle .. :) 至于“勾号”,它在 kleopatra 的答案中很好。虽然我的回答很好(IMO),但它不是您提出的问题的答案。公认的答案是。当然,我希望让你远离为这幅画扩展面板。所以,关于下一个问题.. ;)
      • 谢谢,这确实是一个很棒的答案,因为它比我想要的要多得多:我接下来要问关于保存图像的问题。但我们会看到...
      • +1 非常漂亮的 paint 风格程序,与 this object drawing 程序对比。
      猜你喜欢
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多