2015-05-14 3 views
3

Я создаю своеобразное приложение для рисования. Пользователь может перемещать круг в JPanel, нажимая/перетаскивая мышь.Как предотвратить обновление JPanel?

У меня есть JCheckBoxMenuItem в одном из моих JMenu с:

JCheckBoxMenuItem checkitem = new JCheckBoxMenuItem("Draw mode",false); 
  • Когда она не активирована, то круг можно перемещать только (путем перетаскивания/клавиши) и предыдущий круг будет стерта.
  • Когда она включена, то круг может быть перемещен только, но предыдущий круг не будет удален при перемещении/нажатии мышей (Это работает так же, как программа для рисования)

укороченной версию моих код:

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

class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener, ItemListener 
{ 
    JPanel mainPan, colorPan; 
    Color color = Color.BLACK; 
    JCheckBoxMenuItem checkitem; 
    boolean clear = true; 

    public GUI(String header) 
    { 
     maker(); 

     mainPan.addMouseListener(this); 
     mainPan.addMouseMotionListener(this); 

     add(mainPan , BorderLayout.CENTER); 
     add(colorPan, BorderLayout.PAGE_END); 
    } 

    public void maker() 
    { 
     colorPan = new JPanel(); 
     colorPan.setLayout(new GridLayout(1, 0)); 

     mainPan = new JPanel(){ 
      @Override 
      public void paintComponent(Graphics g) 
      { 
       //g.setColor(Color.WHITE); 
       //g.fillRect(0,0,getWidth(),getHeight()); 
       if(clear) 
        super.paintComponent(g); //Do the same thing as above(Clear JPanel) 

       g.setColor(color); 
       g.fillOval(x,y,50,50); //x and y are integer variables that I use in my full program 
      } 
     }; 

     checkitem = new JCheckBoxMenuItem("Draw mode",false); 
     //After adding this to a JMenu, 
     checkitem.addItemListener(this); 
    } 

    public void itemStateChanged(ItemEvent e) 
    { 
     if(e.getStateChange() == ItemEvent.SELECTED) 
     { 
      clear = false; 
     } 
     else 
     { 
      clear = true; 
     } 
    } 
} 

в приведенной ниже скриншоте показан результат моей полной программе:

SCREENSHOT

colorPan - это JPanel, полный JButtons разных цветов. Верх его mainPan.

Прямо сейчас, режим рисования не работает должным образом. Я всегда думал, что super.paintComponent(g); был тем, который очищает/сбрасывает экран, когда вызывается repaint(). Но я удалил это и был очень удивлен, увидев, что программа ведет себя одинаково.

В принципе, моя проблема здесь:

if(clear) 
    super.paintComponent(g); 

Мне нужно, чтобы предотвратить все от очищаются, когда repaint() называется. Как я могу достичь того, чего хочу?

+0

Полный пример цитируется [здесь] (http://stackoverflow.com/a/11944233/230513). – trashgod

+0

Я этого не понимаю. Не могли бы вы разместить здесь ответ? –

+0

Возможный дубликат: [Запретить Java перерисовывать содержимое JPanel при обновлении] (http://stackoverflow.com/questions/4065456/prevent-java-from-repainting-the-content-of-a-jpanel-while- обновление) – user3261344

ответ

1

Вы не можете "предотвратить обновление JPanel;" paintComponent() будет называться асинхронно, как того требует система. Вместо этого, атрибуты состояния вашего класса представления таким образом, чтобы ваша реализация paintComponent() отображала все всякий раз, когда называется.

В приведенном ниже примере цвет переднего плана изменяется с каждым щелчком мыши, а paintComponent() использует измененную настройку. В более подробном примере, приведенном в качестве примера here, ClearAction, удаляются List<Node> и List<Edge>, которые определяют модель графа.При отсутствии звонка на номер super.paintComponent(g), в противном случае требуется для компонента opaque, звонок fillRect() в paintComponent() очищает любые оставшиеся артефакты выбора.

public void actionPerformed(ActionEvent e) { 
    nodes.clear(); 
    edges.clear(); 
    repaint(); 
} 

image

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** @see https://stackoverflow.com/a/5312702/230513 */ 
public class MouseDragTest extends JPanel { 

    private static final String TITLE = "Drag me!"; 
    private static final Random r = new Random(); 
    private static final int W = 640; 
    private static final int H = 480; 
    private Point textPt = new Point(W/2, H/2); 
    private Point mousePt; 
    private Color color = Color.black; 

    public MouseDragTest() { 
     this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32)); 
     this.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mousePressed(MouseEvent e) { 
       mousePt = e.getPoint(); 
       setColor(Color.getHSBColor(r.nextFloat(), 1, 1)); 
       repaint(); 
      } 
     }); 
     this.addMouseMotionListener(new MouseMotionAdapter() { 

      @Override 
      public void mouseDragged(MouseEvent e) { 
       int dx = e.getX() - mousePt.x; 
       int dy = e.getY() - mousePt.y; 
       textPt.setLocation(textPt.x + dx, textPt.y + dy); 
       mousePt = e.getPoint(); 
       repaint(); 
      } 
     }); 
    } 

    public void setColor(Color color) { 
     this.color = color; 
    } 

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

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.setColor(color); 
     int w2 = g.getFontMetrics().stringWidth(TITLE)/2; 
     g.drawString(TITLE, textPt.x - w2, textPt.y); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame f = new JFrame(TITLE); 
       f.add(new MouseDragTest()); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.pack(); 
       f.setLocationRelativeTo(null); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Хорошо. Я буду изучать образец программы. Спасибо, что ответили. –

3

В этом коде не должны быть внесены изменения. И это не метод краски, который следует изменить. Краска краски всякий раз, когда требуется ваша или по системе. Когда окно изменяется или перемещается или частично покрывается, он снова использует краску для рисования рисунка. Вы должны действительно прекратить обновление координат для вашего окрашенного овала. Это можно сделать в приемнике мыши или в координаторе или, лучше, в контрольной части, которая управляет этими координатами. Ваш флажок должен контролировать способность изменять вашу модель. Он не должен контролировать живопись. Обычно используется шаблон Model-View-Controller - посмотрите на него. Возможно, он может выглядеть как излишний для такого небольшого приложения, но даже сам Swing построен на этом шаблоне, поэтому вы уже следуете за ним. Проблемы возникают, когда вы пытаетесь его сломать. Так что - не надо.

+0

«* То, что вы действительно должны сделать, это прекратить обновление координат для вашего окрашенного овала *». Круг должен быть обновлен независимо от того, включен ли флажок. Когда он активирован, предыдущие рисунки круга не должны быть удалены. И когда он не активирован, предыдущие рисунки кругов должны быть удалены (это происходит сейчас, даже если флажок активирован) –

+0

Не рассматривайте paint() как краску один раз. Это вызвано много. Чтобы увидеть это - перетащите другое окно над своим приложением. Это заставит краску рисовать много раз, и вы это увидите. – Alex

+0

Хм. В этом есть смысл. –

Смежные вопросы