1

我知道 JViewport 是一个单子容器,而且我不能将多个组件添加到一个 jscrollpane。

但是我可以跟踪滚动窗格的位置并根据它修改另一个组件的视图吗?为了展示我在这里尝试做的是一张图片:

http://i.imgur.com/X9GW3VO.png

这是我的代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;

public class XMLSettingsPage extends JPanel {

    private int lines;
    private LinePanel linePanel;
    private JPanel southButtP;
    private JButton saveBtn = new JButton("Save");
    private JButton resetBtn = new JButton("Reset");
    private JScrollPane jsp;
    private JTextArea textArea;
    private JPanel panel;

    public XMLSettingsPage() {

        setBackground(Color.BLACK);
        setLayout(new BorderLayout());

        panel = new JPanel();
        add(panel, BorderLayout.CENTER);
        panel.setLayout(new BorderLayout(0, 0));

        linePanel = new LinePanel();
        panel.add(linePanel, BorderLayout.WEST);
        linePanel.setForeground(Color.GRAY);
        linePanel.setFont(new Font("Tahoma", Font.PLAIN, 13));
        linePanel.setBackground(SystemColor.inactiveCaptionBorder);

        textArea = new JTextArea();
        textArea.setCaretColor(Color.BLACK);
        textArea.setFont(new Font("Tahoma", Font.PLAIN, 13));
        textArea.setForeground(Color.BLACK);
        textArea.setBackground(UIManager.getColor("menu"));

        textArea.addKeyListener(new LinePanel() {
            @Override
            public void keyPressed(KeyEvent e) {
                linePanel.setLine(getLines());

            }
        });

        textArea.addFocusListener(new FocusListener() {

            @Override
            public void focusLost(FocusEvent e) {
                southButtP.setVisible(false);
            }

            @Override
            public void focusGained(FocusEvent e) {
                southButtP.setVisible(true);
            }
        });

        LinePainter painter = new LinePainter(textArea);
        painter.setColor(Color.WHITE);

        jsp = new JScrollPane(textArea);
        panel.add(jsp, BorderLayout.CENTER);
        jsp.setBackground(Color.BLACK);
        jsp.setBorder(null);

        southButtP = new JPanel();
        add(southButtP, BorderLayout.SOUTH);
        southButtP.setBorder(new MatteBorder(1, 0, 0, 0, (Color) Color.WHITE));
        southButtP.add(resetBtn);
        southButtP.add(saveBtn);
        southButtP.setBackground(SystemColor.scrollbar);

        southButtP.setVisible(false);

        resetBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                reset();
            }

        });
        resetBtn.setBackground(resetBtn.getParent().getBackground());
        saveBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                save();

            }
        });
        saveBtn.setBackground(resetBtn.getParent().getBackground());

    }

    private int getLines() {
        int totalCharacters = textArea.getText().length();
        int lineCount = (totalCharacters == 0) ? 1 : 0;

        try {
            int offset = totalCharacters;
            while (offset > 0) {
                offset = Utilities.getRowStart(textArea, offset) - 1;
                lineCount++;
            }
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
        return lineCount;
    }

    private void reset() {
        textArea.setText(getXMLSettingsData());
    }

    private void save() {
        // write to xml file settings.
    }

    private String getXMLSettingsData() {
        return null;
    }

    public static void setXMLSettingsData() {
        // sets xml data on change
    }

}

// Line Panel.
class LinePanel extends JTextArea implements KeyListener {

    private int lineNumber = 1;
    private StringBuilder sb;
    final private String END_STRING = " \n";

    public LinePanel() {
        sb = new StringBuilder();
        setBackground(Color.BLACK);
        setFont(new Font("Tahoma", Font.PLAIN, 13));
        setEditable(false);

    }

    public void printNumbers(String s) {
        setText(s);
    }

    private void numberFactory(int l) {

        sb.delete(0, sb.length());
        for (int i = 0, a = 1; i < l; i++, a++) {
            sb.append(" " + a + END_STRING);
        }
        printNumbers(sb.toString());
    }

    public void setLine(int line) {
        if (lineNumber != line) {
            lineNumber = line;
            numberFactory(line);

        } else {
        }
    }

    public int getLine() {
        return lineNumber;
    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

}

当我到达窗口底部时,我看不到另一个行号,原因很明显(它不是自动向下滚动也不是手动向下滚动)。

有什么方法可以将我的 JScrollPane 连接到东 JTextArea,这样即使在我到达面板底部后我也可以看到每行的数字?

如果您知道任何更好的方法来做到这一点,请让我知道我对任何想法持开放态度。

我试图将两个组件放入一个面板中,然后将滚动面板放到它上面,但它不起作用。在那之后我什至看不到面板中心的任何东西。不知道我做错了什么,芽并没有被视为这样做的好方法。

4

1 回答 1

3

使用rowHeader视图。

在此处输入图像描述

jsp.setRowHeaderView(textArea);
于 2014-01-24T12:04:15.793 回答