简体   繁体   English

JScrollPane和Graphics2D

[英]JScrollPane & Graphics2D

I am trying to draw graphics that is bigger than the JFrame and use JScrollPane to scroll the entire graphics. 我试图绘制比JFrame大的图形,并使用JScrollPane滚动整个图形。 I created a simple example with two lines. 我创建了一个包含两行的简单示例。 The scroll bars appear but the graphics do not show. 出现滚动条,但不显示图形。

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test extends JPanel{

public static void main(String... args) {
    Test test = new Test();
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    panel.add(test);
    JScrollPane scrollPane = new JScrollPane(panel);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setBounds(0, 0, 1350, 700);
    JPanel contentPane = new JPanel(null);
    contentPane.setPreferredSize(new Dimension(1400, 700));
    contentPane.add(scrollPane);
    frame.setContentPane(contentPane);
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setVisible(true);
}

@Override
protected void paintComponent(Graphics g) 
{
    Graphics2D g2 = (Graphics2D)g;

    g2.drawLine(30,30,30,3000);
    g2.drawLine(30, 400, 500, 3000);
}
}

Welcome to a wonderful example of why null layouts suck... 欢迎来到一个精彩的示例,说明为什么null布局很烂...

Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. 避免使用null布局,像素完美布局是现代ui设计中的一种幻觉。 There are too many factors which affect the individual size of components, none of which you can control. 有太多因素会影响组件的单个大小,您无法控制。 Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify Swing旨在与布局经理为核心一起工作,舍弃这些问题不会导致问题和问题的终结,您将花费越来越多的时间来尝试纠正

Also see Why is it frowned upon to use a null layout in SWING? 另请参见为什么在SWING中使用空布局会让人皱眉? for more details... 更多细节...

The basic problem is, the JScrollPane , has a JViewport , which actually contains your component. 基本问题是JScrollPane有一个JViewport ,它实际上包含您的组件。 The JViewport uses your components sizing hints to make determinations about how big it should be and the JScrollPane uses the decisions the JViewport makes to make determinations about whether it needs to display the scrollbars or not. JViewport使用组件大小调整提示来确定其JViewport ,而JScrollPane使用JViewport做出的决定来确定是否需要显示滚动条。

The JViewport is taking a look at your component and has decided, because you've not told it otherwise, that it should be 0x0 in size. JViewport正在查看您的组件,并已决定(因为没有另行通知)它的大小应为0x0

You can prove this by adding a LineBorder to your component, setBorder(new LineBorder(Color.RED)); 您可以通过将LineBorder添加到组件setBorder(new LineBorder(Color.RED));来证明这一点setBorder(new LineBorder(Color.RED)); , you won't see it either (or if you do, it will be a little red square) ,您也不会看到它(或者,如果看到的话,它将是一个红色的小方块)

Start by overriding the getPrefferedSize method of the Test panel and return some appropriate size 首先覆盖“ Test面板的getPrefferedSize方法,然后返回一些合适的大小

Next, call super.paintComponent before you perform any custom painting, otherwise you'll end up with some awesome, but annoying, paint artifacts... 接下来,在执行任何自定义绘画之前,请调用super.paintComponent ,否则您将得到一些令人敬畏但令人讨厌的绘画工件...

滚动窗格

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test extends JPanel {

    public static void main(String... args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                Test test = new Test();
                JFrame frame = new JFrame();
                JScrollPane scrollPane = new JScrollPane(test);
                frame.add(scrollPane);
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(3000, 3000);
    }



    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        g2.drawLine(30, 30, 30, 3000);
        g2.drawLine(30, 400, 500, 3000);
    }
}

You'll probably want to take a look at the Scrollable interface next, so you can control the default size of the JViewport , so it won't try and fill the entire screen. 接下来,您可能需要看一下Scrollable interface ,以便可以控制JViewport的默认大小,因此它不会尝试填充整个屏幕。

Take a look at Implementing a Scrolling-Savvy Client for more details 有关更多详细信息,请参阅实现精通滚动客户端

The problem comes from the lines 问题出在线路上

JPanel panel = new JPanel();
panel.add(test);
JScrollPane scrollPane = new JScrollPane(panel);

You are adding test to panel which uses FlowLayout by default. 您正在将test添加到默认情况下使用FlowLayoutpanel中。 This layout does not strech the components in it, so test on which you draw has dimensions 0x0 and what you see in the scroll pane is the empty panel . 此布局不会拉伸其中的组件,因此在其上进行绘制的test尺寸为0x0,在滚动窗格中看到的是空panel

To fix this you can set panel to use BorderLayout which stretches the center component: 要解决此问题,您可以将panel设置为使用BorderLayout来拉伸中心组件:

JPanel panel = new JPanel(new BorderLayout());
panel.add(test);
JScrollPane scrollPane = new JScrollPane(panel);

or add test directly to the scroll pane: 或直接将test添加到滚动窗格:

JScrollPane scrollPane = new JScrollPane(test);

Additionally: 另外:

  • Always call super.paintComponent(g) as the first line when overriding paintComponent . 覆盖paintComponent时,始终将super.paintComponent(g)作为第一行。
  • Don't use null layouts (and consequently don't set bounds on components). 不要使用空布局(因此不要在组件上设置边界)。
  • When you use setPreferredSize remember that if the dimensions are too large they will "flow off" the screen. 使用setPreferredSize请记住,如果尺寸太大,它们将“流出”屏幕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM