为JPanel使用addMouseListener()和paintComponent()

这是我上一个问题的后续行动。 我尽可能地简化了事情,但它仍然不起作用! 虽然我使用getGraphics()获得了好处。

关于这里出了什么问题的详细解释非常受欢迎。 我怀疑这里使用addMouseListener()方法的方式有问题。

编辑完全重写了代码。 但仍然无法正常工作。

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

您必须将mouseListener添加到面板。 默认情况下这不会发生,如您所料;-)

 MainClass1() { addMouseListener(this); } 

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

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

BTW 2:在有限区域调用重绘不是你想要的(?) – 它会暂时将这些方块添加到绘画中,只要整个面板重新绘制它们就会丢失(与getGraphics相同的效果)。 取决于你真正想要的,

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

这不是你的问题的直接答案,但知道(或至少怀疑)你想提供什么(一个简单的绘画程序),我建议从这种方法开始,基于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 hintsMap = new HashMap(); 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设计’因为我没有放入任何东西。如果有的话,那只是偶然的。 此代码旨在演示可能的内容以及如何开始执行此操作。

请注意方法中的拼写错误:

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

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

首先,从未使用过PaintClass11 ……

其次,即使它是,你创建两个独立的PaintClass22实例,一个放在框架上,另一个放在你试图更新…所以屏幕上不会发生任何更新。

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