所以我做了一个简单的图形GUI,其中rigth部分是一个内部有JPanel(canvas)的JScrollPane(mainGUI类)。当我尝试绘制一些框(使用Box类)并运行它时,滚动时我得到这个重复的windowsXP图形错误,其中框的渲染太慢或某种东西,有点难以解释。滚动后如何获得统一的无毛刺图?是否有渲染选项?
代码:
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);
}
}
提前致谢 节日快乐
答案 0 :(得分:4)
首先,你要重写错误的绘画方法。你不应该重写JPanel的paint方法,而应该覆盖它的paintComponent方法,因为这是一个更具体的绘画方法,默认情况下有双缓冲,做动画时有一个加号(你对你的做法很有用)滚动)。
更重要的是,你没有在覆盖中调用超级绘画方法,super.paintComponent(g)
如果覆盖paintComponent,或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);
}
}