Что такое альтернатива функции рисования и перекраски?

1

Есть ли какая-либо функция, которую можно заменить paint() и repaint() в java.

У меня сценарий.

Существует треугольник (треугольник 1). когда пользователь щелкнет треугольником, появится другой треугольник (Треугольник 2), а 1-й (Треугольник 1) будет удален с экрана. (кодируется с использованием JFrame, paint() и repaint())

Я до сих пор этого добился. но проблема заключается в том, когда я минимизирую или изменяю размер окна с помощью мыши в окне вывода, он просто рисует снова Треугольник 1, а не Треугольник 2. ИЛИ Очистите весь экран, если я вызываю g2d.clearRect(0, 0, 1000, 1000);
triangle.reset();
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 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");
            }
        }
    }
}
  • 1
    Краткий ответ - НЕТ, и НЕ ПЫТАЙТЕСЬ. Работа в рамках API - это то, что у вас будут волосы.
  • 1
    Рабочий код обновлен, пожалуйста, посмотрите еще раз Спасибо
Показать ещё 1 комментарий
Теги:
graphics
swing
awt
jframe

2 ответа

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

Теперь, если вам нужно много треугольников, у вас должна быть коллекция Polygon s. Как это:

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 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;
}
  • 0
    Это может быть верно для 1 к 1 треугольнику. но что, если придется сделать 1 ко многим? 1 снять и нарисовать 3?
  • 0
    Позвольте мне изменить ответ соответственно ...
Показать ещё 2 комментария
2

paint() и repaint() работают нормально, но вы не используете их, поскольку они предназначены для использования. В оконной системе не сохраняется постоянное изображение того, как выглядит компонент. Он ожидает, что ваш компонент сможет перекрасить весь внешний вид по требованию (например, когда размер окна изменяется или не минимизируется).

Если вы захватите объект Graphics с помощью getGraphics() и нарисуете что-то на компоненте, то материал, который вы рисуете, действительно будет потерян, если/когда весь компонент должен быть перекрашен. Поэтому вы не должны этого делать, но вместо этого убедитесь, что ваш метод 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);
}

В качестве альтернативы, если вы пытаетесь сохранить несколько треугольников на экране, например, чтобы добавить новый за каждый щелчок, вы должны добавить их в список фигур, который будет отображаться всякий раз, когда компонент должен быть перекрашен:

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);
        }
    });
}
  • 0
    public void paintComponent(Graphics g) { .. должен быть public void paintComponent(Graphics g) { super.paintComponent(g); ..
  • 0
    @AndrewThompson Похоже, что OP хочет нарисовать весь внешний вид компонента, а не рисовать поверх текста по умолчанию, поэтому бесполезно не вызывать super.paintComponent.
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню