2011-08-27 28 views
6

Tôi có một JFrame chứa 2 phân lớp JPanel và 2 JLabel trong BorderLayout. Một trong những JPanel chứa JButtons và cái kia được sử dụng để hiển thị đồ họa. Các JLabels ở phía bắc và phía nam, nút JPanel ở phía tây và màn hình hiển thị JPanel ở giữa.JPanel repaint issue

Màn hình JPanel yêu cầu làm mới liên tục, vì vậy tôi gọi phương thức repaint() của nó thông qua sự kiện hành động được tạo bởi bộ hẹn giờ xoay. Tôi cũng ghi đè lên phương thức paintComponent() của nó để vẽ các bản vẽ của tôi.

Thay vì hiển thị những gì tôi đã vẽ, "nội dung của JFrame" đang được vẽ lên màn hình hiển thị JPanel. Tôi biết rằng tôi có thể chỉ đơn giản là "xóa" hiển thị JPanel bằng cách sử dụng g.fillRect() hoặc super.paintComponent() trước khi thực hiện các bản vẽ của tôi.

Tôi chỉ tò mò tại sao điều này xảy ra.

Tôi đang sử dụng jdk 1.6u27. dưới đây là mã của tôi:

package test; 

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

public class Main { 

public static void main(String[] args) { 
    Simulation sim = new Simulation(); 

    } 
} 

class Simulation extends JFrame { 

    public JLabel state; 
    private JLabel id; 
    private ButtonPanel control; 
    private Display display; 

    public Simulation() { 
     id = new JLabel("Test"); 
     state = new JLabel("Test"); 
     control = new ButtonPanel(); 
     display = new Display(this); 

     this.setLayout(new BorderLayout()); 
     this.add(id, BorderLayout.NORTH); 
     this.add(control, BorderLayout.WEST); 
     this.add(display, BorderLayout.CENTER); 
     this.add(state, BorderLayout.SOUTH); 

     this.setSize(500, 600); 
     this.setVisible(true); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    } 

    public ButtonPanel getControl() { 
     return this.control; 
    } 
} 

class ButtonPanel extends JPanel implements ActionListener { 

    public JButton b[] = new JButton[8]; 
    public boolean bp[] = new boolean[8]; 

    public ButtonPanel() { 
     this.setLayout(new GridLayout(8, 1)); 

     for (int i = 0; i < b.length; i++) { 
      b[i] = new JButton(""+i); 
      b[i].addActionListener(this); 
      bp[i] = false; 
      this.add(b[i]); 
     } 
    } 

    public void actionPerformed(ActionEvent e) { 
     //do something 
    } 
} 

class Display extends JPanel implements ActionListener { 

    private Timer tm; 
    private int yco; 
    private Simulation sim; 

    public Display(Simulation sim) { 
     tm = new Timer(100, this); 
     tm.start(); 

     yco = 0; 

     this.sim = sim; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     //draw something 
     g.drawLine(0, yco, 100, 100); 
    } 

    public void actionPerformed(ActionEvent e) { 
     yco ++; 
     this.repaint(); 
    } 
} 

screenshot

+0

+1 cho [sscce] (http://sscce.org/). – trashgod

Trả lời

9

Without super.paintComponent(g), kết quả phụ thuộc vào mặc định của nền tảng của bạn cho opacity tài sản của các đại biểu JPanel UI, PanelUI. Mỏ xảy ra là true, nhưng bạn có thể thử nghiệm trên nền tảng của mình, như được đề xuất bên dưới.

Hợp đồng bổ sung: "Nếu bạn không tôn trọng opaque property, bạn có thể sẽ thấy hình ảnh artifacts." - paintComponent(). Các artifact bạn quan sát sẽ thay đổi theo nền tảng, nhưng nó không phải là điển hình. Trong thực tế, bạn đang phá vỡ lời hứa để vẽ từng pixel, và bạn thấy bất cứ thứ gì còn sót lại trong một số bộ đệm.

Main

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.*; 

public class Main { 

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

      @Override 
      public void run() { 
       Simulation sim = new Simulation(); 
      } 
     }); 
    } 
} 

class Simulation extends JFrame { 

    public JCheckBox state; 
    private JLabel id; 
    private ButtonPanel control; 
    private Display display; 

    public Simulation() { 
     id = new JLabel("Test"); 
     state = new JCheckBox("Opaque"); 
     control = new ButtonPanel(); 
     display = new Display(this); 

     this.setLayout(new BorderLayout()); 
     this.add(id, BorderLayout.NORTH); 
     this.add(control, BorderLayout.WEST); 
     this.add(display, BorderLayout.CENTER); 
     this.add(state, BorderLayout.SOUTH); 
     state.addItemListener(new ItemListener() { 

      @Override 
      public void itemStateChanged(ItemEvent e) { 
       display.setOpaque(e.getStateChange() == ItemEvent.SELECTED); 
      } 
     }); 
     state.setSelected(true); 

     this.pack(); 
     this.setVisible(true); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    public ButtonPanel getControl() { 
     return this.control; 
    } 
} 

class ButtonPanel extends JPanel { 

    private static final int N = 8; 
    private List<JToggleButton> list = new ArrayList<JToggleButton>(N); 

    public ButtonPanel() { 
     this.setLayout(new GridLayout(0, 1)); 
     for (int i = 0; i < N; i++) { 
      final JToggleButton b = new JToggleButton(String.valueOf(i)); 
      b.addActionListener(new ActionListener() { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        //System.out.println(b.isSelected()); 
       } 
      }); 
      list.add(b); 
      this.add(b); 
     } 
    } 
} 

class Display extends JPanel { 

    private Simulation sim; 
    private Timer tm; 
    private int yco; 

    public Display(Simulation sim) { 
     this.setPreferredSize(new Dimension(320, 320)); 
     this.setOpaque(true); 
     this.sim = sim; 
     tm = new Timer(100, new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       yco++; 
       repaint(); 
      } 
     }); 
     tm.start(); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     //super.paintComponent(g); 
     g.drawLine(0, yco, getWidth()/2, getHeight()/2); 
    } 
} 
+1

Nói chung, bạn nên gọi 'super.paintComponent (g)' hoặc "con cháu nhẹ của container sẽ không hiển thị." – trashgod

+2

Xem thêm [Chủ đề chính so với Giao diện người dùng trong Java] (http://stackoverflow.com/questions/7156949/main-thread-vs-ui-thread-in-java/7158505#7158505). – trashgod

+0

Tôi thấy, tôi không biết rằng có một lựa chọn như vậy, cảm ơn cho lời giải thích. Nhưng vấn đề của tôi thực sự là nội dung của JFrame đang được rút ra trên màn hình hiển thị JPanel. Ví dụ: nhãn trên cùng và các nút bên cạnh được vẽ lên màn hình hiển thị JPanel, cùng với các đường màu đen đó. –