Проблема рисования в Java - PullRequest
       72

Проблема рисования в Java

3 голосов
/ 06 апреля 2011

Я новичок в Java, и мне нужно реализовать приложение рисования, и я немного застрял в начале, мне удалось нарисовать линии на JPanel, который я добавил в JFrame, но каждая нарисованная линия сбрасываетвесь рисунок, а в области рисования остается только последняя нарисованная линия.Я надеюсь, что я понял, вот его код:

class Shapes extends JFrame {

    public JFrame mf = new JFrame("Paint");
    DrawArea da = new DrawArea();

        JToggleButton lineButton = new JToggleButton(new ImageIcon("line.gif"));
        JToggleButton brushButton = new JToggleButton();
        JToggleButton pencilButton = new JToggleButton();
        JToggleButton eraserButton = new JToggleButton(new ImageIcon("eraser_icon.png"));
        JToggleButton rectangleButton = new JToggleButton();
        JToggleButton ovalButton = new JToggleButton();

    Shapes() {


        da.setBounds(120, 50, 500, 350);
        da.setBackground(Color.YELLOW);
        mf.setSize(700, 500);
        mf.setLayout(null);

        lineButton.setBounds(0, 50, 40, 40);
        brushButton.setBounds(40, 50, 40, 40);
        eraserButton.setBounds(0, 90, 40, 40);
        pencilButton.setBounds(40, 90, 40, 40);
        rectangleButton.setBounds(0, 130, 40, 40);
        ovalButton.setBounds(40, 130, 40, 40);

        mf.setBackground(Color.red);
        mf.add(lineButton);
        mf.add(brushButton);
        mf.add(pencilButton);
        mf.add(eraserButton);
        mf.add(rectangleButton);
        mf.add(ovalButton);
        mf.add(da);
        mf.show();
        mf.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        mf.addMouseListener(new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                System.out.println("x:" + e.getX() + "y:" + e.getY() + "\n" + "x2:" + e.getXOnScreen() + "y2:" + e.getYOnScreen());
            }
        });
        eraserButton.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e)
            {
            eraserButton.setSelectedIcon(new ImageIcon("eraser_icon_selected.png"));
        }
        });
        lineButton.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e)
            {
              lineButton.setSelectedIcon(new ImageIcon("line_selected.png"));
        }
        });
        da.addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent e) {
                da.setXvalue(e.getX());
                da.setYvalue(e.getY());



            }

            public void mouseReleased(MouseEvent e) {

                da.setX2value(e.getX());
                da.setY2value(e.getY());
                da.repaint();
            }
        });
        da.addMouseMotionListener(new MouseAdapter() {

            public void mouseDragged(MouseEvent e) {
                da.repaint();
                da.setX2value(e.getX());
                da.setY2value(e.getY());

            }
        });

    }
}



public class DrawArea extends JPanel {
    int x1value,y1value,x2value,y2value;

    public int getX2value() {
        return x2value;
    }

    public void setX2value(int x2value) {
        this.x2value = x2value;
    }

    public int getY2value() {
        return y2value;
    }

    public void setY2value(int y2value) {
        this.y2value = y2value;
    }
    public JPanel dra=new JPanel();

    public int getXvalue() {
        return x1value;
    }

    public void setXvalue(int xvalue) {
        this.x1value = xvalue;
    }

    public int getYvalue() {
        return y1value;
    }

    public void setYvalue(int yvalue) {
        this.y1value = yvalue;
    }

    public void paint(Graphics g)
    {
      super.paint(g);
      g.setColor(Color.red);
      g.drawLine(getXvalue(),getYvalue(),getX2value(),getY2value());

}
}

    class Paint extends JPanel

{ 

    public static void main(String args[])
            {
               Shapes s=new Shapes();

            }

}

Ответы [ 5 ]

3 голосов
/ 06 апреля 2011

См. Индивидуальные подходы к рисованию для двух решений.Примеры рисуют прямоугольники, но концепция для линий одинакова.

1 голос
/ 06 апреля 2011

Переопределить paintComponent () , а не paint () . Прочитайте этот учебник . Когда необходимо перерисовать панель, вы вызываете метод Panel перерисовка ().

0 голосов
/ 06 апреля 2011

Немного не по теме, но у меня было несколько неудобных минут, потому что я использовал update () вместо repaint ().Я советую всем, кто работает с SWING, потратить некоторое время на проверку того, какие методы должны обрабатываться как потокобезопасные, а какие должны быть в EDT (потоке диспетчера событий), чтобы избежать неожиданных ошибок. Это хорошая статья об этом.

Кроме того, вначале продумайте, хотите ли вы иметь систему отмены / возврата в вашем приложении ... Если так, то сколько шаговВы хотите разрешить быть снятым.Если вы хотите разрешить эту функцию, вы не можете просто нарисовать и забыть о том, что рисовали в прошлый раз.Также было бы не эффективно использовать память для хранения всех изображений, которые вы рисуете.Я не эксперт, и я не говорю, что это лучшая практика, но я бы пошел по этому пути:

Я бы сделал два списка.

  1. Один из них будет хранить примененные действия рисования ,
  2. другие будут содержать отмененные действия рисования .

действие рисования будетбыть интерфейсом, и некоторый класс будет реализовывать его для каждого конкретного типа действия рисования (LineDrawAction, CirceDrawAction ...).

Когда вы рисуете новую линию или что-либо еще, вы очищаете список отмененных действий и добавляете его в список прикладных действий .Когда кто-то отменяет последнее действие, я просто удаляю последние действия рисования из примененного списка и добавляю в отозванный список (и т. Д.).В зависимости от того, хотите ли вы, чтобы только последнее действие x было отменено, когда список достигает этого ограничения x, я бы удалил первое действие рисования из списка или очереди и, наконец, обратился бы к изображению - это означает постоянное рисование, и это не может бытьотменить.

Надеюсь, это понятно и полезно, даже если не прямой ответ на ваш вопрос.

0 голосов
/ 06 апреля 2011

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

Ожидается paintComponent и т. П., Так как ваша реализация будет рисовать КАЖДЫЙ графический элемент, который вы хотите отображать, каждый раз, когда он вызывается.

Вместо хранения x1, y1, x2, y2, вы должны создать класс LineSegment или аналогичный, который хранит эти значения. Затем, когда вы рисуете, вы вызываете g.drawLine() для каждого LineSegment объекта, который вы сохранили (предположительно в ArrayList или подобном). Затем, когда компонент перерисовывается, все ваши отрезки должны появиться на экране.

0 голосов
/ 06 апреля 2011

Paint вызывается оконным менеджером каждый раз, когда он считает эту область «не обновленной». Если вы делаете это так, как вы делаете это прямо сейчас, вы будете каждый раз рисовать последнюю нарисованную линию.

Правильный способ сделать это - создать BufferedImage в памяти и использовать его. Затем, в методе рисования, стряхните BufferedImage на поверхность. Это также упрощает прокрутку и масштабирование.

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

...