0

我一直在寻找一个解决方案,我认为这是非常常见的问题,Java Swing,但找不到具体的答案。

我有这个顶部JPanel可滚动的 Swing,显示文档的图像。JPanel

下面有更多的 Swing 组件,例如在另一个面板中的 aJTable和一些文本框、JButton控件等。(同一个中有更多的面板JWindow。)

当用户在下面的框中编辑数据等时,这些当然会获得应有的关注。现在,当用户想要滚动文档中的某些特定数据时,他/她需要先在此设置焦点(使用鼠标/标签),然后再滚动。

因此,用户希望在不离开他正在使用的其他组件的焦点的情况下使用例如向上/向下箭头键盘。

我试图设置键盘处理程序,但如果不将焦点移到顶部就无法让它工作。

如果没有这个组件(和另一个)有焦点,就没有办法滚动一个可滚动的 Swing 组件吗?

4

2 回答 2

1

如果没有这个组件(和另一个)有焦点,就没有办法滚动一个可滚动的 Swing 组件吗?

然后一般的解决方案是使用Key Bindings

但是,问题是每个组件都可以为 up/down 事件实现 Key Bindings 本身,在这种情况下,Action调用该组件的相关项。

本教程演示了如何从组件中删除键绑定。

一个 JTable 和一些文本框

所以这些是实现向上/向下键绑定的组件示例。

JButton 控件

是没有默认向上/向下键绑定的组件示例。

因此,您可以添加自己的代码,如下所示:

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

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        setLayout( new BorderLayout() );

        JPanel top = new JPanel();
        top.add( new JTextField(10) );
        top.add( new JButton("Button") );
        add(top, BorderLayout.PAGE_START);

        JLabel label = new JLabel( new ImageIcon("mong.jpg") );
        JScrollPane scrollPane = new JScrollPane( label );
        add(scrollPane, BorderLayout.CENTER);

        JScrollBar scrollBar = scrollPane.getVerticalScrollBar();

        InputMap im = getInputMap(JScrollBar.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        ActionMap am = getActionMap();
        im.put(KeyStroke.getKeyStroke("pressed UP"), "up");
        am.put("up", new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                scrollBar.setValue(scrollBar.getValue() - scrollBar.getUnitIncrement(-1));
            }
        });

        im.put(KeyStroke.getKeyStroke("pressed DOWN"), "down");
        am.put("down", new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                scrollBar.setValue(scrollBar.getValue() + scrollBar.getUnitIncrement(1));
            }
        });

    }

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

    public static void main(String[] args) throws Exception
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}

在上面的示例中,当焦点位于按钮上而不是文本字段时,图像将滚动。

于 2021-03-07T17:01:36.447 回答
1

Page Down如果组件是滚动窗格中的文本字段,那么如果(第一个,至少)文本字段被聚焦,它似乎有效。这是运行此类代码并点击Page Down几次的结果。

在此处输入图像描述

如果在聚焦滚动窗格之外的组件时需要此行为,则可以查看key bindings

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class KeyboardScroll {

    private JComponent ui = null;

    KeyboardScroll() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        JPanel textPanel = new JPanel(new GridLayout(0, 1));
        for (int ii = 1; ii < 101; ii++) {
            textPanel.add(new JTextField("Field " + ii, 30));
        }
        JScrollPane scrollPane = new JScrollPane(textPanel,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        ui.add(scrollPane);
        Dimension d = textPanel.getPreferredSize();
        scrollPane.getViewport().setPreferredSize(
                new Dimension((int)d.getWidth(),100));
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(
                            UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                KeyboardScroll o = new KeyboardScroll();

                JFrame f = new JFrame("Use 'Page Down'");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
于 2021-03-07T10:51:30.453 回答