【问题标题】:what is Alternative of Paint and repaint function?什么是 Paint 和 repaint 功能的替代方案?
【发布时间】:2015-02-27 08:21:09
【问题描述】:

在java中有没有可以用paint()repaint()替换的函数。

我有一个场景。

有一个三角形(三角形1)。当用户点击三角形时,另一个三角形 (Triangle 2) 将出现,第一个 (Triangle 1) 将从屏幕上移除。 (使用JFramepaint()repaint() 编码)

到目前为止,我已经实现了。但问题是当我用鼠标最小化或更改窗口大小时,它只是再次绘制 Triangle 1 而不是 Triangle 2如果我调用g2d.clearRect(0, 0, 1000, 1000);
triangle.reset();
,则清除整个屏幕

注意:这两个功能都是删除前一个三角形(三角形1)。

是否有任何函数在最小化或窗口大小更改时不应更改状态?

或者我们可以根据场景覆盖repaint() 或任何有帮助的东西。

这是工作代码。执行它,单击三角形然后最小化并再次查看。您会更清楚地了解问题。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Triangle_shape extends JFrame implements ActionListener {

    public static JButton btnSubmit = new JButton("Submit");

    public Triangle_shape() {
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setLayout(new BorderLayout());
        frame.add(new TrianglePanel(), BorderLayout.CENTER);
        frame.add(btnSubmit, BorderLayout.PAGE_END);
        frame.pack();
        frame.repaint();
        frame.setTitle("A Test Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public static class TrianglePanel extends JPanel implements MouseListener {

        private Polygon triangle, triangle2;

        public TrianglePanel() {
            //Create triangle
            triangle = new Polygon();
            triangle.addPoint(400, 550);        //left   
            triangle.addPoint(600, 550); //right
            triangle.addPoint(500, 350); //top

            //Add mouse Listener
            addMouseListener(this);

            //Set size to make sure that the whole triangle is shown
            setPreferredSize(new Dimension(300, 300));
        }

        /**
         * Draws the triangle as this frame's painting
         */
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.draw(triangle);
        }

        //Required methods for MouseListener, though the only one you care about is click
        public void mousePressed(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }

        /**
         * Called whenever the mouse clicks. Could be replaced with setting the
         * value of a JLabel, etc.
         */
        public void mouseClicked(MouseEvent e) {
            Graphics2D g2d = (Graphics2D) this.getGraphics();
            Point p = e.getPoint();
            if (triangle.contains(p)) {
                System.out.println("1");

                g2d.clearRect(0, 0, 1000, 1000);
                triangle.reset();
                g2d.setColor(Color.MAGENTA);
                triangle2 = new Polygon();
                triangle2.addPoint(600, 550);  // left
                triangle2.addPoint(700, 350); //top
                triangle2.addPoint(800, 550);  //right
                g2d.draw(triangle2);
            } else {
                System.out.println("Triangle dont have point");
            }
        }
    }
}

【问题讨论】:

  • 简短的回答是否定的,不要尝试。在 API 范围内工作,你就会有头发。
  • 工作代码已更新,请再次查看谢谢
  • 我无法确定这一点。 paint()repaint() 方法没有替代品,它们也不是等价物或替代品。

标签: java swing graphics jframe awt


【解决方案1】:

paint()repaint() 可以正常工作,但您没有使用它们,因为它们是为使用而设计的。窗口系统不会保留组件外观的持久图像。它希望您的组件能够按需重绘其整个外观(例如在调整窗口大小或未最小化时)。

如果您使用getGraphics() 抓取一个 Graphics 对象并在组件上绘制一些东西,那么如果/当整个组件需要重新绘制时,您绘制的东西确实会丢失。因此,您不应该这样做,而是确保您的 paintComponent 方法具有完全重绘组件所需的所有信息。


如果您只希望一次在屏幕上显示一个三角形,请不要创建单独的变量triangle2。只需通过更改鼠标单击处理程序来替换您拥有的一个三角形,如下所示:

public void mouseClicked(MouseEvent e) {
    Point p = e.getPoint();
    if (triangle.contains(p)) {
        triangle = new Polygon();
        triangle.addPoint(600, 550); // left
        triangle.addPoint(700, 350); //top
        triangle.addPoint(800, 550); //right
        repaint();
    } else {
        System.out.println("Point not in triangle");
    }
}

您的paintComponent 方法应调用super.paintComponent 以确保绘制背景,否则您无需更改它:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.draw(triangle);
}

或者,如果您尝试在屏幕上保留多个三角形,例如,每次单击时添加一个新三角形,您应该将它们添加到形状的list 中,当组件需要重新绘制时,该形状将被绘制:

private final List<Shape> shapes = new ArrayList<>();

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    for (Shape s : shapes)
        g2d.draw(s);
}

然后控制屏幕上的一组形状,操作列表的内容,然后调用repaint();

例如,向屏幕上的形状添加新形状:

Polygon triangle = new Polygon();
triangle.addPoint(200, 300);
triangle.addPoint(200, 200);
triangle.addPoint(300, 200);
shapes.add(triangle);
repaint();

从屏幕上删除所有形状:

shapes.clear();
repaint();

您还应该确保在程序开始时切换到 Swing 线程,因为从主线程与 Swing 组件交互是不安全的。在main:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame();
            .
            .
            .
            frame.setVisible(true);
        }
    });
}

【讨论】:

  • public void paintComponent(Graphics g) { .. 应该是public void paintComponent(Graphics g) { super.paintComponent(g); ..
  • @AndrewThompson 听起来 OP 想要绘制组件的整个外观,而不是在其上绘制任何默认文本,因此不调用 super.paintComponent 是没有用的。
  • “听起来像..” 他们是否“听起来像”他们不想要该组件上的边框,或者明确的(而不是偶然的)BG填充?最好不要假设这些事情..
  • 工作代码已更新,请再次查看谢谢
  • @Boann 您不负责绘制子组件或边框,最佳做法是覆盖paintComponent。如果 OP 想要自定义绘制边框的方式,那么他们应该实现 Border 并应用它。
【解决方案2】:

您的mouseClicked 方法不应创建新的Triangle 对象。重置triangle 后,只需添加新点即可。也不要在这个方法中绘制而是调用repaint

   public void mouseClicked(MouseEvent e) {
        Point p = e.getPoint();
        if (triangle.contains(p)) {
            System.out.println("1");
            triangle.reset();            // change the current triangle
            triangle.addPoint(600, 550); // new left
            triangle.addPoint(700, 350); // new top
            triangle.addPoint(800, 550); // new right
            repaint();                   // force repainting
        } else {
            System.out.println("Triangle dont have point");
        }
    }

现在如果你想要很多三角形,你应该有一个Polygons 的集合。像这样:

public static class TrianglePanel extends JPanel implements MouseListener {
    private Vector<Polygon> triangles;

    public TrianglePanel() {
        n = 0;
        // Create an empty collection
        triangles = new Vector<Polygon>();

        //Create first triangle
        Polygon triangle = new Polygon();
        triangle.addPoint(400, 550); //left   
        triangle.addPoint(600, 550); //right
        triangle.addPoint(500, 350); //top

        // Add the triangle to the collection
        triangles.add(triangle);

        //Add mouse Listener
        addMouseListener(this);

        //Set size to make sure that the whole triangle is shown
        setPreferredSize(new Dimension(300, 300));
    }

    /**
     * Draws the triangles as this frame's painting
     */
    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        for (Polygon p : triangles) // Draw all triangles in the collection
            g2d.draw(p);
    }

    //Required methods for MouseListener, though the only one you care about is click
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}

    /**
     * Called whenever the mouse clicks. Could be replaced with setting the
     * value of a JLabel, etc.
     */
    public void mouseClicked(MouseEvent e) {
        Graphics2D g2d = (Graphics2D) this.getGraphics();
        Point p = e.getPoint();
        // Do what you want with p and the collection
        // For example : remove all triangles that contain the point p
        ListIterator<Polygon> li = triangles.listIterator();
        while (li.hasNext()) {
            if (li.next().contains℗) li.remove();
        }
        // Do what you want to update the list
        // For example: Add a new triangle...
        Polygon triangle = new Polygon();
        triangle.addPoint(600+n, 550);  // left
        triangle.addPoint(700+n, 350);  //top
        triangle.addPoint(800+n, 550);  //right
        triangles.add(triangle); // add the new triangle to the list
        n += 10; // next new triangle will be "moved" right
        repaint();
    }
    private int n;
}

【讨论】:

  • 这可能适用于 1 比 1 的三角形。但是如果必须做 1 到很多怎么办? 1 删除并绘制 3 ?
  • 我尝试了代码。当最小化然后取消最小化屏幕。三角形消失了..这意味着它和我之前遇到的问题一样。
猜你喜欢
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 2012-06-01
  • 2021-11-13
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多