【问题标题】:JScrollPane & Graphics2DJScrollPane & Graphics2D
【发布时间】:2014-12-12 11:55:09
【问题描述】:

我正在尝试绘制大于 JFrame 的图形并使用 JScrollPane 滚动整个图形。我用两行创建了一个简单的示例。出现滚动条,但不显示图形。

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);
}
}

【问题讨论】:

    标签: java swing jpanel jscrollpane graphics2d


    【解决方案1】:

    欢迎来看一个很好的例子,说明为什么 null 布局很糟糕......

    避免使用null 布局,像素完美的布局是现代用户界面设计中的一种错觉。影响组件单个尺寸的因素太多,您无法控制。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正

    另请参阅Why is it frowned upon to use a null layout in SWING? 了解更多详情...

    基本问题是,JScrollPane 有一个JViewport,它实际上包含您的组件。 JViewport 使用您的组件大小提示来确定它应该有多大,JScrollPane 使用JViewport 做出的决定来确定它是否需要显示滚动条。

    JViewport 正在查看您的组件并决定,因为您没有另外告诉它,它的大小应该是 0x0

    你可以通过在你的组件中添加一个LineBorder 来证明这一点,setBorder(new LineBorder(Color.RED));,你也不会看到它(或者如果你看到了,它会是一个红色的小方块)

    首先重写Test 面板的getPrefferedSize 方法并返回一些适当的大小

    接下来,在您执行任何自定义绘画之前,请致电 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);
        }
    }
    

    接下来你可能想看看Scrollable interface,这样你就可以控制JViewport 的默认大小,这样它就不会尝试填满整个屏幕。

    查看Implementing a Scrolling-Savvy Client了解更多详情

    【讨论】:

    • 你又打败了我。
    • @user1803551 只需 10 分钟 ;)
    • 非常感谢,这很有帮助。
    【解决方案2】:

    问题出在台词

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

    您将test 添加到默认使用FlowLayoutpanel。此布局不会拉伸其中的组件,因此您在其上绘制的 test 的尺寸为 0x0,您在滚动窗格中看到的是空的 panel

    要解决此问题,您可以将panel 设置为使用拉伸中心组件的BorderLayout

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

    或将test 直接添加到滚动窗格中:

    JScrollPane scrollPane = new JScrollPane(test);
    

    另外:

    • 在覆盖paintComponent 时,始终将super.paintComponent(g) 作为第一行调用。
    • 不要使用空布局(因此不要在组件上设置边界)。
    • 当您使用setPreferredSize 时请记住,如果尺寸太大,它们会“溢出”屏幕。

    【讨论】:

      猜你喜欢
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 2012-02-02
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多