我正在尝试使用java模拟调试游标的移动。我有问题将JScrollPane的可视区域放到正确的位置。
我想只在我想要跳过它的行不可见时滚动。使用这些常量在面板上绘制使用CodeDrowingPanel.NUMBER_OF_LINES
和CodeDrowingPanel.FONT_SIZE
完成帮助的计算。
如果我必须跳,我必须跳的线应该在底部。
我必须记住,可见区域取决于屏幕分辨率。应用程序最大化,无法调整大小。
修改
public void setCursorToLine(int line, JScrollPane codeArea)
{
if(line*CodeDrowingPanel.FONT_SIZE > this.getHeight()+43)
this.cursorPosition = this.getHeight()+43;
else
this.cursorPosition = line * CodeDrowingPanel.FONT_SIZE;
JViewport viewPort = (JViewport) SwingUtilities.getAncestorOfClass(JViewport.class, codeArea);
if (viewPort != null)
{
Rectangle view = viewPort.getViewRect();
view.y += line - previousLine;
codeArea.scrollRectToVisible(view);
}
this.repaint();
}
这就是我现在尝试修改的方法。但它不起作用。我尝试从第一条评论中跟随你的第二个例子。我不知道如何使用第二条评论中的方法。
答案 0 :(得分:2)
这是一个简单的示例,使用JList
和JScrollPane
rowHeader
支持。
魔法基本上发生在这里......
int index = list.getSelectedIndex();
index++;
if (index >= list.getModel().getSize()) {
index = 0;
}
list.setSelectedIndex(index);
Rectangle cellBounds = list.getCellBounds(index, index);
list.scrollRectToVisible(cellBounds);
基本上,我们要求视图计算由所选索引表示的Rectangle
,并简单地要求组件滚动以便矩形可见
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JList list;
public TestPane() {
setLayout(new BorderLayout());
DefaultListModel model = new DefaultListModel();
try (BufferedReader br = new BufferedReader(new FileReader(new File("src/test/Test.java")))) {
String text = null;
while ((text = br.readLine()) != null) {
model.addElement(text);
}
} catch (IOException exp) {
exp.printStackTrace();
}
list = new JList(model);
list.setSelectedIndex(0);
JScrollPane sp = new JScrollPane(list);
sp.setRowHeaderView(new Header(list));
add(sp);
JButton next = new JButton("Next");
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int index = list.getSelectedIndex();
index++;
if (index >= list.getModel().getSize()) {
index = 0;
}
list.setSelectedIndex(index);
Rectangle cellBounds = list.getCellBounds(index, index);
list.scrollRectToVisible(cellBounds);
}
});
add(next, BorderLayout.SOUTH);
}
}
protected class Header extends JPanel {
private JList list;
public Header(JList list) {
this.list = list;
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Container parent = list.getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport) parent;
Graphics2D g2d = (Graphics2D) g.create();
int selectedRow = list.getSelectedIndex();
if (selectedRow >= 0) {
Rectangle cellBounds = list.getCellBounds(selectedRow, selectedRow);
cellBounds.y -= viewport.getViewPosition().y;
g2d.setColor(Color.RED);
g2d.fillRect(0, cellBounds.y, getWidth(), cellBounds.height);
}
g2d.dispose();
}
}
}
}
答案 1 :(得分:2)
我不认为行号应该是文本的一部分。例如,您有一个水平滚动条。如果向右滚动,则会丢失行号。
相反,您应该使用行标题来显示行号。
见Text Component Line Number。它包含一个为您自定义绘制行号的类。您可以使用将此组件添加到行标题。
该类中的绘制代码将突出显示当前行号。如果要添加箭头,则需要修改绘制代码。在paintComponent(...)
方法中,您可以添加以下内容:
g.drawString(lineNumber, x, y);
// Code to paint an arrow
if (isCurrentLine(rowStartOffset))
{
int height = fontMetrics.getAscent() - fontMetrics.getDescent();
Polygon triangle = new Polygon();
triangle.addPoint(borderGap, y);
triangle.addPoint(borderGap, y - height);
triangle.addPoint(borderGap + 10, y - height / 2);
Graphics2D g2d = (Graphics2D)g.create();
g2d.fill( triangle );
g2d.dispose();
}
要做的另一个改变。由于我们现在正在绘制箭头,我们需要增加组件的宽度。因此,在setPreferredWidth(...)
方法中,您需要进行以下更改:
//int preferredWidth = insets.left + insets.right + width;
int preferredWidth = insets.left + insets.right + width + 15;
我想只在我想要跳过它的行不可见时滚动。
以下是一些代码:
public static void gotoStartOfLine(JTextComponent component, int line)
{
Element root = component.getDocument().getDefaultRootElement();
line = Math.max(line, 1);
line = Math.min(line, root.getElementCount());
int startOfLineOffset = root.getElement( line - 1 ).getStartOffset();
component.setCaretPosition( startOfLineOffset );
}
我从Text Utilities获取了上述代码,其中可能有其他感兴趣的方法(如果不是现在,将来)。
如果要在文本窗格中突出显示整行,也可以使用Line Painter。