将JScrollPane的可见区域移动到特定位置

我试图使用java模拟调试光标的移动。 我有问题将JScrollPane的可视区域放到正确的位置。

这是我想要拍摄的照片: 所需的布局

我只想滚动我想跳的线是不可见的。 计算是否有帮助可以通过使用CodeDrowingPanel.NUMBER_OF_LINESCodeDrowingPanel.FONT_SIZE完成,使用这些常量在面板上绘制线条。

如果我必须跳,我必须跳的线应该在底部。

我必须记住,可见区域取决于屏幕分辨率。 应用程序最大化,无法resize。

编辑:

 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(); } 

这就是我现在尝试修改的方法。 但它不起作用。 我尝试从第一条评论中跟随你的第二个例子。 我不知道如何使用第二条评论中的方法。

在此处输入图像描述

我不认为行号应该是文本的一部分。 例如,您有一个水平滚动条。 如果向右滚动,则会丢失行号。

相反,您应该使用行标题来显示行号。

请参见文本组件行号 。 它包含一个为您自定义绘制行号的类。 您可以使用将此组件添加到行标题。

该类中的绘制代码将突出显示当前行号。 如果要添加箭头,则需要修改绘画代码。 在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获取了上述代码,其中可能有其他感兴趣的方法(如果不是现在,将来)。

如果要在文本窗格中突出显示整行,也可以使用“ 线条画笔” 。

这是一个简单的例子,使用JListJScrollPanerowHeader支持。

滚动矩形到可见

魔法基本上发生在这里……

 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(); } } } }