Java如何在鼠标点击时绘制矩形

时间:2013-02-07 01:30:23

标签: java swing drawrect graphics2d

正如标题所说,我很难在JApplet中绘制一些矩形(填充)。 确切的目标是拥有一个50x50的表格,当你点击一个目标单元格时,填充它(可能通过绘制一个填充的矩形来完成)。我已经完成了关于起点坐标的数学计算,但出于某种原因我无法在MouseClicked方法中绘制新的矩形。有什么建议吗?

public class Main extends JApplet {

public static final int DIMX = 800;
public static final int DIMY = 800;
public static final int ratio = 16;
Graphics g;
boolean drawing;
public int cX;
public int cY;

public Main() {
    JPanel MainFrame = new JPanel();
    MainFrame.setPreferredSize(new Dimension(400, 800));
    MainFrame.setBackground(Color.LIGHT_GRAY);
    JPanel Table = new JPanel();
    Table.setPreferredSize(new Dimension(800, 800));
    Table.setBackground(Color.LIGHT_GRAY);
    add(MainFrame, BorderLayout.EAST);
    add(Table, BorderLayout.WEST);
    addMouseListener(new clicked());
}



public void paint(Graphics g) {
    super.paintComponents(g);
    g.setColor(Color.black);
    for (int i = 0; i <= 800; i += 16) {
        g.drawLine(0, i, 800, i);
        g.drawLine(i, 0, i, 800);
//            g.fillRect(cX, cY, 16, 16);
    }
}

public static void main(String[] args) {
    JFrame win = new JFrame("Retarded Bullshit");
    win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    win.setPreferredSize(new Dimension(1216, 840));
    win.setContentPane(new Main());
    win.pack();
    win.setVisible(true);

}

public class clicked extends JApplet implements MouseListener {

public int cX;
public int cY;
Graphics g;

@Override
public void mouseClicked(MouseEvent e) {
//            Point a = e.getLocationOnScreen();
    int cellX = e.getX();
    int cellY = e.getY();
    if (cellX < 800 && cellX > 0 && cellY < 800 && cellY > 0) {
        cX = cellX / 16 + 1;
        cY = cellY / 16 + 1;

        JOptionPane.showMessageDialog(null, "" + cX + " " + cY);
    }

2 个答案:

答案 0 :(得分:5)

这是一个相对简单的概念(没有冒犯)。

首先,请勿将代码与JAppletJFrame混合使用。如果要在这两种介质中使用应用程序,请将逻辑分成单独的组件(如JPanel),您可以轻松地将其添加到其中。你真的不应该将顶级容器添加到另一个顶级容器(将一个applet添加到一个框架) - 它很麻烦。

避免覆盖顶级容器的paint方法(例如JApplet),而是使用自定义组件(例如JPanel)并覆盖它的paintComponent方法。

在您的示例中,您应该调用super.paint而不是super.paintComponentspaint执行重要工作,您不想跳过它 - 但您应该使用JComponent#paintComponent

MouseListener应添加到您有兴趣管理鼠标事件的组件中。因为永远不会将clicked添加到任何容器中,所以它永远不会收到鼠标事件。

看看

enter image description here

public class SimplePaint03 {

    public static void main(String[] args) {
        new SimplePaint03();
    }

    public SimplePaint03() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new PaintPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PaintPane extends JPanel {

        private List<Shape> grid;
        private List<Shape> fill;

        public PaintPane() {
            grid = new ArrayList<>(5);
            fill = new ArrayList<>(5);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    for (Shape shape : grid) {
                        if (shape.contains(e.getPoint())) {
                            if (fill.contains(shape)) {
                                fill.remove(shape);
                            } else {
                                fill.add(shape);
                            }
                        }
                    }
                    repaint();
                }
            });

            int colWidth = 200 / 50;
            int rowHeight = 200 / 50;

            for (int row = 0; row < 50; row++) {
                for (int col = 0; col < 50; col++) {
                    grid.add(new Rectangle(colWidth * col, rowHeight * row, colWidth, rowHeight));
                }
            }

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.RED);
            for (Shape cell : fill) {
                g2d.fill(cell);
            }
            g2d.setColor(Color.BLACK);
            for (Shape cell : grid) {
                g2d.draw(cell);
            }
        }

    }

}

其他

不保持从一个涂料循环到另一个涂料循环的信息。您需要完全按照希望的方式重新绘制组件。这意味着您需要维护一个可以随时重新绘制的点击列表。

答案 1 :(得分:2)

首先阅读Custom Painting上的Swing教程。

自定义绘制是通过覆盖JPanel或JComponent()的paintComponent()方法完成的。然后将面板添加到JApplet。

如果您只想绘制某些正方形,那么您将需要一个List来跟踪要绘制的单元格。然后每次重新绘制组件时,都需要遍历List并绘制单元格。

您的MouseListener不会扩展JApplet。当您单击单元格时,您将从上面更新列表以指示需要绘制单元格。然后你将调用面板上的repaint(),以便调用你的绘画代码。

您可能还需要查看Custom Painting Approaches,根据您的具体要求,它提供了两种不同的方式来进行此类绘画。