我想TextArea用一個側邊欄來實作一個顯示換行文本每一行中最左邊字符的索引。這是通過JScrollPane使用RowHeader顯示JTextPane數字和Viewport顯示JTextArea序列來實作的。
除了水平調整大小時RowHeader和Viewport不同步之外,一切都很好。在下面的 SSCCE 中,它也發生在啟動時。
圖片說明了這一點: 的游標JTextArea在第一個位置,而顯示的下端JTextPane。
我知道這與JTextPane動態更改其內容有關,因為它適用于靜態內容。
是否有可能防止這種奇怪的行為?

package main;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collections;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;
public class SequenceAreaExample {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(150, 200);
SequenceArea sequenceArea = new SequenceArea();
frame.add(sequenceArea);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
sequenceArea.setText(String.join("", Collections.nCopies(200, "a")));
}
}
class SequenceArea extends JScrollPane implements ComponentListener {
private static final long serialVersionUID = 1L;
private JTextArea text;
private JTextPane numbers;
// FIXME text and numbers are out of sync when resizing horizontally
SequenceArea() {
text = new JTextArea();
text.setLineWrap(true);
text.setEnabled(true);
text.addComponentListener(this);
numbers = new JTextPane();
numbers.setEnabled(false);
setViewportView(text);
setRowHeaderView(numbers);
}
void updateNumbers() {
StringBuilder newNumbers = new StringBuilder();
int length = text.getText().length();
int index = 0;
while (index < length) {
try {
int start = Utilities.getRowStart(text, index);
int end = Utilities.getRowEnd(text, index);
newNumbers.append(start);
newNumbers.append('\n');
index = end 1;
} catch (BadLocationException e) {
break;
}
}
numbers.setText(newNumbers.toString());
}
void setText(String t) {
text.setText(t);
}
@Override
public void componentResized(ComponentEvent e) {
updateNumbers();
}
@Override
public void componentMoved(ComponentEvent e) {}
@Override
public void componentShown(ComponentEvent e) {}
@Override
public void componentHidden(ComponentEvent e) {}
}
uj5u.com熱心網友回復:
根據我的評論,我嘗試構建一個替代解決方案,其中行標題是視口的一部分,到目前為止它似乎作業正常。(順便說一句,在開始時添加 SSCCE 的榮譽)
JPanel panel = new ScrollablePanel();
panel.setLayout(new GridBagLayout());
//can be reused as constraints are only read when adding components
GridBagConstraints constraints = new GridBagConstraints();
//components should take all vertical space if possible.
constraints.weighty = 1.0;
//components should expand even if it doesn't need more space
constraints.fill = GridBagConstraints.BOTH;
//add the numbers component
panel.add(numbers, constraints );
//add specific constraints for the text component
//text takes as much of the width as it can get
constraints.weightx = 1.0;
//numbers component seems to have some insets so add 2px at the top to get better alignment - could be done differently as well
constraints.insets = new Insets(2, 0, 0, 0);
panel.add(text, constraints);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
setViewportView(panel);
為了使其正常作業,您還需要使用一個知道滾動并能夠將其尺寸調整到視口的面板:
class ScrollablePanel extends JPanel implements Scrollable {
public Dimension getPreferredScrollableViewportSize() {
//the panel prefers to take as much height as possible
return new Dimension(getPreferredSize().width, Integer.MAX_VALUE);
}
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 1;
}
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 1;
}
public boolean getScrollableTracksViewportWidth() {
return true;
}
public boolean getScrollableTracksViewportHeight() {
return true;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/323044.html
上一篇:JavaJFrame內部大小
