[英]Scroll to focused textfield
所以,我在滾動窗格中有一堆文本字段。 當用戶聚焦底部的最后一個文本字段時,會添加更多文本字段。 我的問題是,如何使滾動窗格滾動到聚焦的文本字段? 我的意思是,用戶將按 TAB 或 ENTER 鍵跳轉到下一個文本字段,但如果不滾動自己將無法看到它。 當最后一個文本字段具有焦點時,我可以模擬按下向下箭頭或 PageDown,但這會很難看,即使它會做我需要的。
我通過搜索找到了類似的東西,但我無法讓它發揮作用。
public void focusGained(FocusEvent e) {
currentview = t1;
int cons = i - 1;
Rectangle r = new Rectangle(t1.getX(), t1.getY(), 1, 1);
jScrollPane1.scrollRectToVisible(r);
if (t1.getName().equals("prod" + cons)) {
newproduct();
};
}
出現兩件事。
首先, JTextField#scrollRectToVisible
已被覆蓋,並且與其他組件有些不同……令人討厭。
其次,您需要轉換相對於其父級的字段位置,然后使用父級的scrollRectToVisible
方法,例如...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScrollFocusedField {
public static void main(String[] args) {
new ScrollFocusedField();
}
public ScrollFocusedField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
FocusAdapter fh = new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
JComponent comp = (JComponent) e.getComponent();
System.out.println("FocusGained");
Rectangle bounds = comp.getBounds();
bounds.setLocation(SwingUtilities.convertPoint(comp, bounds.getLocation(), comp.getParent()));
JComponent parent = (JComponent) comp.getParent();
parent.scrollRectToVisible(comp.getBounds());
}
};
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int index = 0; index < 100; index++) {
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0;
gbc.gridx = 0;
gbc.gridy = index;
panel.add(new JLabel(Integer.toString(index)), gbc);
JTextField field = new JTextField();
field.addFocusListener(fh);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridx = 1;
panel.add(field, gbc);
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(panel));
frame.setSize(200, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
檢出FormScroller 。 這是一個簡單的類,可用於確保在您選擇組件時可以看到該組件。 FormScroller可以與任何滾動窗格一起使用,並且無需將FocusListeners添加到表單上的每個組件。
它提供了一些選項,使您可以精確控制滾動的工作方式。
我用自定義焦點遍歷策略解決了這個問題。 它包裝了容器的原始遍歷策略,並在請求下一個或上一個組件時對滾動請求進行排隊:
private static class FocusTraversalPolicyAdapter extends FocusTraversalPolicy {
FocusTraversalPolicy focusTraversalPolicy;
FocusTraversalPolicyAdapter(FocusTraversalPolicy focusTraversalPolicy) {
this.focusTraversalPolicy = focusTraversalPolicy;
}
@Override
public Component getComponentAfter(Container container, Component component) {
var nextComponent = focusTraversalPolicy.getComponentAfter(container, component);
scrollToVisible(nextComponent);
return nextComponent;
}
@Override
public Component getComponentBefore(Container container, Component component) {
var previousComponent = focusTraversalPolicy.getComponentBefore(container, component);
scrollToVisible(previousComponent);
return previousComponent;
}
@Override
public Component getFirstComponent(Container container) {
return focusTraversalPolicy.getFirstComponent(container);
}
@Override
public Component getLastComponent(Container container) {
return focusTraversalPolicy.getLastComponent(container);
}
@Override
public Component getDefaultComponent(Container container) {
return focusTraversalPolicy.getDefaultComponent(container);
}
void scrollToVisible(Component component) {
var parent = component.getParent();
if (parent instanceof JComponent) {
SwingUtilities.invokeLater(() -> {
((JComponent)parent).scrollRectToVisible(SwingUtilities.convertRectangle(parent, component.getBounds(), parent));
});
}
}
}
請注意,這確實依賴於現有行為,理論上將來可能會中斷。
根據我之前的回答,一種更簡單且可能更可靠的方法是定義自定義鍵盤焦點處理程序。 每當組件接收到輸入焦點時,管理器就會調度事件並將組件滾動到視圖中:
public class ScrollingKeyboardFocusManager extends DefaultKeyboardFocusManager {
@Override
public boolean dispatchEvent(AWTEvent event) {
var dispatched = super.dispatchEvent(event);
if (dispatched && event.getID() == FocusEvent.FOCUS_GAINED) {
var component = (Component)event.getSource();
var parent = component.getParent();
if (parent instanceof JComponent) {
((JComponent)parent).scrollRectToVisible(SwingUtilities.convertRectangle(parent, component.getBounds(), parent));
}
}
return dispatched;
}
}
可以按如下方式安裝焦點管理器:
KeyboardFocusManager.setCurrentKeyboardFocusManager(new ScrollingKeyboardFocusManager());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.