如何使一个JScrollPane连接到两个组件?,解决方法

时间:2014-01-24 12:01:27

标签: java swing jscrollpane jtextarea rowheader

我知道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所以即使在我到达面板底部之后我也能看到每行的数字?

如果您知道更好的方法,请告诉我我对任何想法持开放态度。

我试图将两个组件放在一个面板中,然后将滚动窗格放到它上面,但是没有工作。在那之后,我甚至看不到面板中心的任何内容。不知道我做错了什么,芽并没有被视为一种很好的方法。

1 个答案:

答案 0 :(得分:3)

使用rowHeader视图。

enter image description here

jsp.setRowHeaderView(textArea);