Java 大型JPanel上的拖绳在Linux上会变得凌乱,但在Windows上不会

Java 大型JPanel上的拖绳在Linux上会变得凌乱,但在Windows上不会,java,swing,graphics,java-2d,Java,Swing,Graphics,Java 2d,我在图形抽绳方法上遇到了一个问题。简单地说,我在Linux上观察到了drawString的意外行为,如果面板大小很大,字符串就会变得凌乱 举个例子。我已经修改了Oracle中的ScrollDemo2类,以便在绘图窗格上绘制字符串: import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.JCompone

我在
图形抽绳
方法上遇到了一个问题。简单地说,我在Linux上观察到了
drawString
的意外行为,如果面板大小很大,字符串就会变得凌乱

举个例子。我已经修改了Oracle中的ScrollDemo2类,以便在
绘图窗格上绘制字符串:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ScrollDemo2 extends JPanel
                          {
    private Dimension area; 
    private JPanel drawingPane;

    public ScrollDemo2() {
        super(new BorderLayout());

        area = new Dimension(100000,1000);

        drawingPane = new DrawingPane();
        drawingPane.setBackground(Color.white);
        drawingPane.setPreferredSize(area);
        drawingPane.revalidate();
        drawingPane.repaint();

        JScrollPane scroller = new JScrollPane(drawingPane);
        scroller.setPreferredSize(new Dimension(500,500));

        add(scroller, BorderLayout.CENTER);
    }

    public class DrawingPane extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // drawString gives correct results in Windows but gives messy strings in Linux; drawLine gives correct lines in both Windows and Linux
            for (int i = 0; i < 100000; i += 100)
                g.drawString("Mark " + i, i, 20);
            for (int i = 0; i < 100000; i += 100)
                g.drawLine(i, i % 1000 / 10 + 25, i, i % 1000 / 10 + 35);

        }

    }


    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ScrollDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent newContentPane = new ScrollDemo2();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
公共类ScrollDemo2扩展了JPanel
{
私人区域;
私人JPanel绘图窗格;
公共文件2(){
超级(新边框布局());
面积=新尺寸(100001000);
drawingPane=新的drawingPane();
绘图窗格。背景(颜色。白色);
drawingPane.setPreferredSize(面积);
drawingPane.revalidate();
drawingPane.repaint();
JScrollPane scroller=新的JScrollPane(drawingPane);
scroller.setPreferredSize(新尺寸(500500));
添加(滚动条,BorderLayout.CENTER);
}
公共类DrawingPane扩展了JPanel{
@凌驾
受保护组件(图形g){
超级组件(g);
//drawString在Windows中给出正确的结果,但在Linux中给出混乱的字符串;drawLine在Windows和Linux中都给出正确的行
对于(int i=0;i<100000;i+=100)
g、 抽绳(“标记”+i,i,20);
对于(int i=0;i<100000;i+=100)
g、 抽绳(i,i%1000/10+25,i,i%1000/10+35);
}
}
私有静态void createAndShowGUI(){
JFrame=新的JFrame(“ScrollDemo2”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane=new ScrollDemo2();
newContentPane.set不透明(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
程序在Windows7上运行

该程序在Windows 7上显示正确的字符串

程序在Linux 14.04上运行

该程序在Linux上显示凌乱的字符串

除了
drawString
方法之外,还添加了
drawsline
方法,并且
drawsline
方法在Windows和Linux中都能正常工作


为什么?我应该如何重写代码以解决Linux上的问题?

如注释中所述,如果绘制静态(稳定不变的背景图像),请使用BuffereImage。例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ScrollDemo2B extends JPanel
                          {
    private static final int IMG_W = 100000;
    private static final int IMG_H = 1000;
    // private Dimension area; 
    private JPanel drawingPane;
    private BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);

    public ScrollDemo2B() {
        super(new BorderLayout());

        Graphics2D g2 = img.createGraphics();
        g2.setColor(Color.BLACK);
        for (int i = 0; i < 100000; i += 100) {
            g2.drawString("Mark " + i, i, 20);
        }
        for (int i = 0; i < 100000; i += 100) {
            g2.drawLine(i, i % 1000 / 10 + 25, i, i % 1000 / 10 + 35);
        }
        g2.dispose();

        drawingPane = new DrawingPane();
        drawingPane.setBackground(Color.white);
        drawingPane.revalidate();
        drawingPane.repaint();

        JScrollPane scroller = new JScrollPane(drawingPane);
        scroller.setPreferredSize(new Dimension(500,500));

        add(scroller, BorderLayout.CENTER);
    }

    public class DrawingPane extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                g.drawImage(img, 0, 0, this);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet() || img == null) {
                return super.getPreferredSize();
            }
            int w = img.getWidth();
            int h = img.getHeight();
            return new Dimension(w, h);
        }

    }


    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ScrollDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent newContentPane = new ScrollDemo2B();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.image.buffereImage;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
公共类ScrollDemo2B扩展了JPanel
{
专用静态最终int IMG_W=100000;
专用静态最终int IMG_H=1000;
//私人区域;
私人JPanel绘图窗格;
private BufferedImage img=新的BufferedImage(img_W,img_H,BufferedImage.TYPE_INT_ARGB);
公共图书馆2b(){
超级(新边框布局());
Graphics2D g2=img.createGraphics();
g2.设置颜色(颜色为黑色);
对于(int i=0;i<100000;i+=100){
g2.抽绳(“标记”+i,i,20);
}
对于(int i=0;i<100000;i+=100){
g2.抽绳(i,i%1000/10+25,i,i%1000/10+35);
}
g2.dispose();
drawingPane=新的drawingPane();
绘图窗格。背景(颜色。白色);
drawingPane.revalidate();
drawingPane.repaint();
JScrollPane scroller=新的JScrollPane(drawingPane);
scroller.setPreferredSize(新尺寸(500500));
添加(滚动条,BorderLayout.CENTER);
}
公共类DrawingPane扩展了JPanel{
@凌驾
受保护组件(图形g){
超级组件(g);
如果(img!=null){
g、 drawImage(img,0,0,this);
}
}
@凌驾
公共维度getPreferredSize(){
if(isPreferredSizeSet()| | img==null){
返回super.getPreferredSize();
}
int w=img.getWidth();
inth=img.getHeight();
返回新尺寸(w,h);
}
}
私有静态void createAndShowGUI(){
JFrame=新的JFrame(“ScrollDemo2”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane=new ScrollDemo2B();
newContentPane.set不透明(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}

然后,如果您有移动精灵或动态图像,您可以使用paintComponent方法绘制它们。

如注释所述,如果绘制静态(稳定不变的背景图像),请使用BuffereImage。例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ScrollDemo2B extends JPanel
                          {
    private static final int IMG_W = 100000;
    private static final int IMG_H = 1000;
    // private Dimension area; 
    private JPanel drawingPane;
    private BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);

    public ScrollDemo2B() {
        super(new BorderLayout());

        Graphics2D g2 = img.createGraphics();
        g2.setColor(Color.BLACK);
        for (int i = 0; i < 100000; i += 100) {
            g2.drawString("Mark " + i, i, 20);
        }
        for (int i = 0; i < 100000; i += 100) {
            g2.drawLine(i, i % 1000 / 10 + 25, i, i % 1000 / 10 + 35);
        }
        g2.dispose();

        drawingPane = new DrawingPane();
        drawingPane.setBackground(Color.white);
        drawingPane.revalidate();
        drawingPane.repaint();

        JScrollPane scroller = new JScrollPane(drawingPane);
        scroller.setPreferredSize(new Dimension(500,500));

        add(scroller, BorderLayout.CENTER);
    }

    public class DrawingPane extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                g.drawImage(img, 0, 0, this);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet() || img == null) {
                return super.getPreferredSize();
            }
            int w = img.getWidth();
            int h = img.getHeight();
            return new Dimension(w, h);
        }

    }


    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ScrollDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent newContentPane = new ScrollDemo2B();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.image.buffereImage;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
公共类ScrollDemo2B扩展了JPanel
{
普里瓦特