issues with paintComponent Java - Swing



im试图编写一个swing gui,在那里我可以通过按下两个不同的JMenuItems(圆形和矩形)在随机位置绘制形状。我用了

Graphics2D gg = (Graphics2D) canvas.getGraphics();

有人建议我使用并覆盖paintComponent()。所以我几个小时前就开始尝试了:D我知道有很多关于这方面的问题,但我真的读了很多,试过了,找过了,但我忍不住了。。

请看一下我的RandomDrawer类,我发现我必须在那里实现paintComponent()(我希望至少如此)。在下一个方法中

public void actionPerformed(ActionEvent e)

我开始知道发生了什么动作,我能告诉他吗?或者我怎么告诉他以后画画?还是我的整个方法有缺陷?

这是我的密码。

谢谢你对我的宽容,非常感谢。

package plotterpackage;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.border.BevelBorder;
import javax.swing.text.JTextComponent;

public class PlotterApp implements ComponentListener  {
private JFrame frame;
private JPanel canvas;
private JPanel statusBar;
private JTextField status;
/**
 * Public default constructor.    
 */
public PlotterApp() {
    initialize();
}
/**
 * Start of the application.
 * @param args command line arguments
 */
public static void main(String[] args) {
    PlotterApp app = new PlotterApp();
    app.start();
}
/**
 * Initialize the application.
 */
protected void initialize() {
    frame = new JFrame("Main");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setBounds(50,50, 50+640, 50+480);
    frame.setBackground(Color.GREEN);
    frame.setJMenuBar(createMenuBar());
    frame.getContentPane().add(createContent(), BorderLayout.CENTER);
    frame.getContentPane().add(createStatusBar(),BorderLayout.SOUTH);        
}
/**
 * Start the graphical user interface.
 */
public void start() {
    // show the GUI
    frame.setVisible(true);
    status.setText("Application started");
}
/**-*
 * Internal helper to create the main content.
 * @return component with application content.
 */
protected JComponent createContent() {
    canvas = new JPanel();
    canvas.addMouseListener(new Painter());
    canvas.addMouseMotionListener(new Painter());
    canvas.addComponentListener(this);
    canvas.setBackground(new Color(128,218,255));
    canvas.setForeground(Color.RED);
    canvas.setBorder(new BevelBorder(BevelBorder.LOWERED));
    return canvas;
}
/**
 * Internal helper to create the statusbar and -fields.
 * @return component with status/bar.
 */    
protected JComponent createStatusBar() {
    FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
    layout.setHgap(5);
    statusBar = new JPanel(layout);
    statusBar.add(new JLabel("Status: "));
    status = new JTextField();
    status.setPreferredSize(new Dimension(400,25));
    status.setEditable(false);
status.setBorder(newBevelBorder(BevelBorder.RAISED,Color.MAGENTA,Color.LIGHT_GRAY));
    status.getInsets().set(2, 10, 2, 10);
    statusBar.add(status);
    return statusBar;
}
/**
 * Internal helper to create the frames menubar.
 * @return menu bar 
 */
protected JMenuBar createMenuBar() {
    JMenuBar mb = new JMenuBar();
    JMenuItem item;
    JMenu menu;
    // Action menu
    menu = new JMenu("Actions");
    mb.add(menu);
    item = new JMenuItem("Draw RandomCircle");
    item.addActionListener(new RandomDrawer());
    menu.add(item);
    item = new JMenuItem("Draw RandomRectangle");
    item.addActionListener(new RandomDrawer());
    menu.add(item);
    menu.addSeparator();
    item = new JMenuItem("Exit");
    item.addActionListener(new AppCloser());
    menu.add(item);
    // Color menu not used so far
    menu = new JMenu("Colors");        
    mb.add(menu);
    // Help menu not used so far
    menu = new JMenu("Help");        
    mb.add(menu);
    return mb;
}
class AppCloser implements ActionListener {
    /* (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("application finished, bye-bye... ");
        frame.setVisible(false);
        frame.dispose();
        System.exit(0);
    }        
}
class RandomDrawer extends JPanel implements ActionListener {
    /* (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */ 
    @Override
    protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setColor(Color.BLACK);
          g2.drawOval(100, 100, 100, 100);  
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        Random generator = new Random();
        int x = generator.nextInt(100)+100;
        int y = generator.nextInt(100)+100;
        int w;
        if (e.getActionCommand()==("Draw RandomCircle")) {
            System.out.printf("x = %d y = %dn", x, y);
            //status.setText(String.format("rnd draw x:  y: "));
            //gg.setColor(Color.BLACK);
            //gg.drawOval(x, y, generator.nextInt(x), generator.nextInt(y));    
        }
        else if (e.getActionCommand()==("Draw RandomRectangle")) {
            System.out.printf("x = %d y = %dn", x, y);
            //status.setText(String.format("rnd draw x:  y: "));
            //Graphics2D gg = (Graphics2D) canvas.getGraphics();
            //gg.setColor(Color.BLACK);
            //gg.drawRect(x, y, generator.nextInt(x), generator.nextInt(y));    
        }
    }
}

class Painter extends MouseAdapter implements MouseMotionListener {
  Point start, end;
  int startX, startY, oldX, oldY, oldWidth, oldHeight;
  public void mousePressed(MouseEvent e) {
    start = e.getPoint();
    oldX = startX;
    oldY = startY;
    startX = e.getX();
    startY = e.getY();
    status.setText(String.format("Mouse start: " + start));
  }
  public void mouseDragged(MouseEvent e) {
    Graphics2D gc = (Graphics2D)canvas.getGraphics();
    gc.setColor(new Color(128, 218, 255));
    gc.drawOval(oldX, oldY, oldWidth, oldHeight);
    System.out.printf("oldWidth ist = %3d, oldHeight ist = %3dn", oldWidth, oldHeight);
    oldWidth = e.getX();
    oldHeight = e.getY();
    gc.setColor(Color.BLACK);
    gc.drawOval(startX, startY, e.getX(), e.getY());
  }
  public void mouseReleased(MouseEvent e) {
    end = e.getPoint();
    status.setText(String.format("Mouse end: " + end));
  }
}

@Override
public void componentHidden(ComponentEvent e) {
    // TODO Auto-generated method stub
}
@Override
public void componentMoved(ComponentEvent e) {
    // TODO Auto-generated method stub
}
@Override
public void componentResized(ComponentEvent e) {
    // TODO Auto-generated method stub
}
@Override
public void componentShown(ComponentEvent e) {
    // TODO Auto-generated method stub
}
}

不要做…

Graphics2D gg = (Graphics2D) canvas.getGraphics();

这不是自定义绘画应该做的。Swing将询问您何时需要绘制某些内容,并且您需要重新绘制组件的当前状态。

首先看一下AWT和Swing中的绘画和执行自定义绘画,了解更多细节

基本上,您需要重写JPanelpaintComponent方法(确保首先调用super.paintComponent),并绘制组件的当前状态。

您需要将状态存储为对您的最有用的任何形式(List或自定义对象,甚至Image

当您更改状态时,您可以通过调用repaint请求API更新UI

您可以将形状放置在某种容器中,如ArrayList。在paintComponent(Graphics g)中,您应该绘制该列表中的每个形状,在actionPerformed(ActionEvent e

最新更新