2016-12-11 55 views
0

所以我做一个简单的图形的GUI,其中分辩部分与里面一个JPanel(画布)(mainGUI类)一个JScrollPane。当我尝试绘制一些盒子(使用Box类)并运行它时,当滚动时,我得到这个重复的WindowsXP图形错误,其中盒子渲染太慢或某种东西,有点难以解释。如何在滚动后获得统一的非毛刺图纸?是否有渲染选项或其他?的JPanel内部JScrollPane的带图形的毛刺而滚动

代码:

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


public class Grafin{ 
    public static void main(String args[]){ 
     mainGUI gui = new mainGUI(); 
    } 
} 

class mainGUI{ 
    private JFrame mainFrame; 
    private JPanel toolsPanel; 
    private JPanel canvasPanel; 

    public mainGUI(){ 
     try{ 
      UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); 
     }catch(Exception e){ 
      System.out.println(e.getMessage()); 
     } 

     mainFrame = new JFrame("Grafin | untitled"); 
     mainFrame.setLayout(new GridBagLayout()); 
     mainFrame.setSize(920, 580); 
     mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mainFrame.setLocationRelativeTo(null); 
     mainFrame.setVisible(true);  

     loadGUI(); 
    } 

    public void loadGUI(){ 
     GridBagConstraints c = new GridBagConstraints(); 

     //toolsPanel (izq) y canvasPanel (der) dentro de mainFrame 
     toolsPanel = new JPanel(new GridBagLayout()); 
     toolsPanel.setPreferredSize(new Dimension(250,580)); 

     c.gridx = 0; 
     c.gridy = 0; 
     c.weightx = 0.1; 
     c.weighty = 1; 
     c.fill = GridBagConstraints.BOTH; 
     mainFrame.add(toolsPanel, c); 


     canvasPanel = new JPanel(new GridBagLayout()); 
     canvasPanel.setBackground(Color.white); 
     canvasPanel.setPreferredSize(new Dimension(1500,1000)); 

     JScrollPane canvasScroll = new JScrollPane(canvasPanel); 
     canvasScroll.setPreferredSize(new Dimension(670,580)); 

     c.gridx = 1; 
     c.gridy = 0; 
     c.weightx = 0.9; 
     mainFrame.add(canvasScroll, c); 
     canvasScroll.setSize(canvasScroll.getPreferredSize()); 
     canvasScroll.setBackground(Color.white); 

     //CanvasPanel: 
     c.gridx = 0; 
     c.gridy = 0; 
     c.weightx = 1; 
     c.weighty = 1; 

     Box b1 = new Box(10, 200, 30, 128); 
     Box b2 = new Box(200, 10, 120, 40); 
     canvasPanel.add(b1, c); 
     canvasPanel.add(b2, c); 
     mainFrame.pack(); 
    } 
} 

    class Box extends JPanel{ 
    private Color borderColor; 
    private Color fillColor; 
    public int x; 
    public int y; 
    public int width; 
    public int height; 

    public Box(){ 
     borderColor = Color.black; 
     fillColor = new Color(242, 242, 242); 
     x = y = 1; 
     width = height = 30; 
    } 

    public Box(int px, int py, int w, int h){ 
     x = px; 
     y = py; 
     borderColor = Color.black; 
     fillColor = new Color(242, 242, 242); 
     width = w; 
     height = h; 
    } 

    public void changeFillColor(Color c){ 
     fillColor = c; 
    } 

    public void changeBorderColor(Color c){ 
     borderColor = c; 
    } 

    public void paint(Graphics g){ 
     g.setColor(fillColor); 
     g.fillRect(x, y, width, height); 
     g.setColor(borderColor); 
     g.drawRect(x, y, width, height); 
    } 
} 

在此先感谢 节日快乐

回答

4

首先,您要替换错误的画法。你不应该重写JPanel的paint方法,而是重写它的paintComponent方法,因为这是一个更具体的绘画方法,默认情况下有双缓冲,当做动画的时候是加号(你用滚动的方式)。

更重要的是,如果覆盖paintComponent,则不会调用超级绘画方法,如果(错误地)覆盖绘画,则不调用超级绘画方法,super.paintComponent(g)super.paint(g)。这可以防止您的JPanel清除脏像素。

其他问题:您要添加两种成分的使用GridBagLayout的成分,但使用同样的GridBagConstraints两个,东西,你不应该做的事情。

此外,您的Box类应该是逻辑类,而不是组件类。换句话说,它不应该扩展任何Swing GUI组件,并且应该在canvasPanel中绘制。

例如:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class Grafin2 extends JPanel { 
    private static final int PREF_W = 920; 
    private static final int PREF_H = 580; 
    private static final Dimension TOOLS_SIZE = new Dimension(250, PREF_H); 
    private static final Dimension CANVAS_SIZE = new Dimension(1500, 1000); 
    private JPanel toolsPanel = new JPanel(); 
    private CanvasPanel canvasPanel = new CanvasPanel(); 

    public Grafin2() { 
     MyBox box1 = new MyBox(10, 200, 30, 128); 
     MyBox box2 = new MyBox(200, 10, 120, 40); 

     box1.changeFillColor(new Color(255, 120, 120)); 
     box2.changeFillColor(new Color(220, 220, 255)); 

     canvasPanel.addMyBox(box1); 
     canvasPanel.addMyBox(box2); 

     toolsPanel.setPreferredSize(TOOLS_SIZE); 
     canvasPanel.setBackground(Color.white); 
     canvasPanel.setPreferredSize(CANVAS_SIZE); 
     JScrollPane canvasScroll = new JScrollPane(canvasPanel); 

     setLayout(new BorderLayout()); 
     add(toolsPanel, BorderLayout.LINE_START); 
     add(canvasScroll, BorderLayout.CENTER); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class CanvasPanel extends JPanel { 
     // a collection to hold all the boxes 
     private List<MyBox> boxes = new ArrayList<>(); 

     public void addMyBox(MyBox myBox) { 
      boxes.add(myBox); 
     } 

     @Override // again, this is the proper painting method 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); // never forget this! 
      for (MyBox myBox : boxes) { 
       myBox.draw(g); // draw all the boxes that we hold 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     Grafin2 mainPanel = new Grafin2(); 

     JFrame frame = new JFrame("Grafin2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

// this is a logical class, **not** a component class. 
class MyBox { 
    private Color borderColor; 
    private Color fillColor; 
    public int x; 
    public int y; 
    public int width; 
    public int height; 

    public MyBox() { 
     borderColor = Color.black; 
     fillColor = new Color(242, 242, 242); 
     x = y = 1; 
     width = height = 30; 
    } 

    public MyBox(int px, int py, int w, int h) { 
     x = px; 
     y = py; 
     borderColor = Color.black; 
     fillColor = new Color(242, 242, 242); 
     width = w; 
     height = h; 
    } 

    public void changeFillColor(Color c) { 
     fillColor = c; 
    } 

    public void changeBorderColor(Color c) { 
     borderColor = c; 
    } 

    public void draw(Graphics g) { 
     // no need to call a super method 
     // because there is none for this class 
     g.setColor(fillColor); 
     g.fillRect(x, y, width, height); 
     g.setColor(borderColor); 
     g.drawRect(x, y, width, height); 
    } 
} 
+0

对不起,我迟到的反应,一直忙于决赛。非常感谢你的答案,试试看看它是否有效。 –

+0

更新:它按我的意思工作。再次谢谢你。 –

+0

@Luis_V:谢谢你回复我,并很高兴它正在工作。 –