簡體   English   中英

JScrollPane內部的JPanel在滾動時出現圖形故障

[英]JPanel inside JScrollPane with graphics glitches while scrolling

因此,我制作了一個簡單的圖形GUI,其中最重要的部分是內部帶有JPanel(畫布)的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);
    }
}

在此先感謝節日快樂

首先,您要覆蓋錯誤的繪畫方法。 您不應覆蓋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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM