如何使 JScrollPane(在 BorderLayout 中,包含 JPanel)顺利自动滚动 [英] How to make JScrollPane (In BorderLayout, containing JPanel) smoothly autoscroll

查看:32
本文介绍了如何使 JScrollPane(在 BorderLayout 中,包含 JPanel)顺利自动滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 JScrollPanel 内放置一个大小不一(可能比标准屏幕宽得多)的 JPanel.目前效果很好,我已经将滚动条配置为手动正常工作,但是我希望 JPanel 不断向左滚动",以便随着时间的推移显示整个内容.我找到的所有答案都特定于 JTextArea 并使用插入符号或使用 rectToVisible.这些都不起作用,因为我试图在内部滚动到单个 JPanel.

I'm trying to have a JPanel of varying size (potentially much wider than the standard screen) inside of a JScrollPanel. Currently it works out great, and I have configured the scrollbars to work fine manually, however I would like the JPanel to "scroll" constantly to the left, so that over time the whole thing is displayed. All of the answers I found are specific to JTextArea and use Carets, or use rectToVisible. Neither of these will work because I'm trying to scroll internally to a single JPanel.

我在下面包含了我认为是所有相关代码的内容.

I've included what I believe to be all of the relevant code below.

center 是 JPanel(其中 Grid 是一个子类,用于专门绘制具有某些特定单元格颜色的网格)和一个我想要自动滚动的 BorderLayout.

center is the JPanel (of which Grid is a subclass, used to paint specifically a grid with some specific cells colored) with a BorderLayout that I would like to autoscroll.

public GuiViewFrame(Song playMe) {
  String[][] songArray = playMe.to2DArray();

  this.displayPanel = new ConcreteGuiViewPanel(playMe);
  main = new JPanel();
  main.setLayout(new BorderLayout());
  displayPanel.setLayout(new BorderLayout());
  center = new Grid(playMe);
  labels = new Labels(playMe);
  horiz = new Horiz(playMe);
  center.setPreferredSize(new Dimension(10 * songArray.length, 10 * songArray[0].length));
  horiz.setPreferredSize(new Dimension(10 * songArray.length, 10));
  horiz.setVisible(true);

  main.add(center, BorderLayout.CENTER);
  main.add(horiz, BorderLayout.NORTH);

  scroll = new JScrollPane(main,
        JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
  add(scroll, BorderLayout.CENTER);
  labels.setPreferredSize(new Dimension(20, 10 * songArray[0].length));
  labels.setVisible(true);
  add(labels, BorderLayout.WEST);

  JScrollBar horiz = scroll.getHorizontalScrollBar();
  InputMap im = horiz.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
  im.put(KeyStroke.getKeyStroke("RIGHT"), "positiveUnitIncrement");
  im.put(KeyStroke.getKeyStroke("LEFT"), "negativeUnitIncrement");
  im.put(KeyStroke.getKeyStroke("HOME"), "minScroll");
  im.put(KeyStroke.getKeyStroke("END"), "maxScroll");

  this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
  this.pack();
}

整个项目是生成一个结合 MIDI 和 GUI 的音乐播放视图,但是现在一旦 MIDI 播放了足够多的歌曲,相关的音符就会在屏幕外.我想以与 MIDI 保持同步的速度滚动.

The project as a whole is to generate a view for playing music that combines MIDI and a GUI, but right now once MIDI plays enough of the song, the relevant notes are off screen. I would like to scroll at a rate to keep pace with MIDI.

推荐答案

可以设置水平滚动条的值来控制当前可见的内容:

You can set the value of the horizontal scrollbar to control what is currently visible:

JScrollBar horizontal = scroll.getHorizontalScrollBar();
horizontal.setValue( horizontal.getValue() + ??? );

您需要使用 Swing Timer 来安排以适当的间隔滚动.

You would need to use a Swing Timer to schedule the scrolling at an appropriate interval.

使用 Timer 滚动文本的简单示例:

Simple example of using a Timer to scroll text:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class TimerTest extends JPanel implements ActionListener
{
    JLabel timeLabel;
    JLabel scrollLabel;

    public TimerTest()
    {
        setLayout( new BorderLayout() );

        timeLabel = new JLabel( new Date().toString() );
        add(timeLabel, BorderLayout.NORTH);

        scrollLabel = new JLabel( "Some continuously scrolling text!!      " );
        add(scrollLabel, BorderLayout.SOUTH);

        int time = 1000;
        javax.swing.Timer timer = new javax.swing.Timer(time, this);
        timer.setInitialDelay(1);
        timer.start();
    }

    public void actionPerformed(ActionEvent e)
    {
        timeLabel.setText( new Date().toString() );
        String oldText = scrollLabel.getText();

        // Scroll right to left
        String newText = oldText.substring(1) + oldText.substring(0, 1);

        // Scroll left to right
//      int length = oldText.length();
//      String newText = oldText.substring(length-1, length)
//          + oldText.substring(0, length-1);

        scrollLabel.setText( newText );
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TimerTest() );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

这篇关于如何使 JScrollPane(在 BorderLayout 中,包含 JPanel)顺利自动滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆