- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的问题与这个非常相似:
Set the vertical scroll to current position after revalidate
不同之处在于,我不想滚动回 0,而是滚动到更新子组件之前保存的位置,如下所示:
final int oldPos = scrollPanel.getVerticalScrollBar().getValue();
removeAll(); // Removes all components from the JPanel
add(mList()); // Adds a bunch of content
revalidate();
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
ml.getVerticalScrollBar().setValue(oldPos);
}
});
此代码在另一个组件的鼠标运动监听器中触发,因此调用非常频繁。
即使最初 jscrollpane 滚动到顶部,有时 oldPos 也不为零,这会导致 Pane 向下滚动,尽管设置了该值。
即使我强制滚动到顶部并只记录 oldPos 值,它也不总是 0:
final int oldPos = scrollPanel.getVerticalScrollBar().getValue();
removeAll();
add(mList());
revalidate();
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
System.out.println(oldPos); // Sometimes this is > 2000
ml.getVerticalScrollBar().setValue(0); // scroll to the top
}
});
我猜如果 oldPos = ...
代码在调用前一个执行的 invokeLater block 之前执行,就会发生这种情况。我该如何解决这个问题?
更新:
我按照 @mKorbel 的建议创建了一个 sscce:
更新 2: 我更新了 sscce 以允许在 jTextArea/jLabel 之间切换,启用/禁用监听器的重新绑定(bind),以及在 jTextArea 和继承自 jTextArea 的自定义类(覆盖了 scrollRectToVisible 方法)之间切换。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
public class Main {
static class MyTextArea extends JTextArea {
@Override
public void scrollRectToVisible(final Rectangle aRect) {
// supress scrollToRect in textarea
}
}
static final Box inner = Box.createVerticalBox();
// if the jtextarea should contain text
private static boolean textEnabled = true;
private static boolean usejLabel = false;
private static boolean useRebinding = false;
private static boolean useLock = true;
private static boolean customTextarea = false;
private static boolean _locked = false;
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final JPanel insideScroll = insideScroll();
final JScrollPane scrollpane = new JScrollPane(insideScroll);
scrollpane.setAutoscrolls(false);
scrollpane
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
final JPanel rightPanel = new JPanel();
rightPanel.setPreferredSize(new Dimension(300, 300));
final MouseMotionAdapter listener = new MouseMotionAdapter() {
@Override
public void mouseDragged(final MouseEvent e) {
super.mouseDragged(e);
final boolean rebind = useRebinding;
final MouseMotionAdapter self = this;
if (rebind) {
rightPanel.removeMouseMotionListener(self);
}
final int pos = scrollpane.getVerticalScrollBar().getValue();
if (!useLock || !_locked) {
if (useLock) {
_locked = true;
}
update();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (rebind) {
rightPanel.addMouseMotionListener(self);
}
if (useLock) {
_locked = false;
}
}
});
}
}
};
rightPanel.addMouseMotionListener(listener);
// Add labels describing the problem
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));
final JButton toggleButton = new JButton("Toggle text");
final JButton toggleButtonLabel = new JButton("Toggle JLable/JTextArea");
final JButton toggleButtonRebind = new JButton("Turn rebinding on");
final JButton toggleButtonCustomTextArea = new JButton(
"Toggle Custom Textarea");
rightPanel.add(toggleButton);
rightPanel.add(toggleButtonLabel);
rightPanel.add(toggleButtonRebind);
rightPanel.add(toggleButtonCustomTextArea);
rightPanel
.add(new JLabel(
"<html>If the text is disabled, you can press/drag<br> your mouse on on right side of the<br> window and the scrollbar will<br> stay in its position."));
rightPanel
.add(new JLabel(
"<html><br/>If the text is enabled, the scrollbar<br> will jump around when dragging<br> on the right side."));
rightPanel
.add(new JLabel(
"<html><br/>The problem does not occur when using JLabels instead of JTextArea"));
// enable/disable the text when the button is clicked.
toggleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
textEnabled = !textEnabled;
update();
}
});
toggleButtonLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
usejLabel = !usejLabel;
update();
}
});
toggleButtonRebind.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
useRebinding = !useRebinding;
toggleButtonRebind.setText(useRebinding ? "Turn rebinding off"
: "Turn rebinding on");
update();
}
});
toggleButtonCustomTextArea.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
customTextarea = !customTextarea;
update();
}
});
final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
scrollpane, rightPanel);
frame.add(split);
// initialize the scrollpane content
update();
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
// initializes the components inside the scrollpane
private static JPanel insideScroll() {
final JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(inner, BorderLayout.NORTH);
return panel;
}
// replaces all components inside the scrollpane
private static void update() {
inner.removeAll();
for (int i = 0; i < 30; i++) {
inner.add(buildRow(i));
}
inner.revalidate();
}
// build a single component to be inserted into the scrollpane
private static JPanel buildRow(final int i) {
final JPanel row = new JPanel();
final Color bg = i % 2 == 0 ? Color.DARK_GRAY : Color.LIGHT_GRAY;
row.setBackground(bg);
row.setPreferredSize(new Dimension(300, 80));
row.setLayout(new BorderLayout());
row.add(textarea(bg), BorderLayout.CENTER);
return row;
}
// build the textarea to be inserted into the cells in the scroll pane
private static Component textarea(final Color bg) {
final String text = String.format("%d", (int) (1000 * Math.random()))
+ " Lorem ipsum dolor si amet. Lorem ipsum dolor si amet. Lorem ipsum dolor si amet";
if (usejLabel) {
final JLabel textarea = new JLabel();
textarea.setBackground(bg);
if (textEnabled) {
textarea.setText(text);
}
return textarea;
} else {
final JTextArea textarea;
if (customTextarea) {
textarea = new MyTextArea();
textarea.setDisabledTextColor(Color.cyan);
} else {
textarea = new JTextArea();
textarea.setDisabledTextColor(Color.black);
}
textarea.setEnabled(false);
textarea.setLineWrap(true);
textarea.setBackground(bg);
textarea.setEditable(false);
if (textEnabled) {
textarea.setText(text);
}
return textarea;
}
}
}
通过这样做,我意识到只有当 jscroll 包含将其文本设置为字符串的 jTextarea 元素时才会出现问题。在我的实际应用程序中,我需要自动换行的文本区域,但即使禁用换行也会出现问题。
最佳答案
我找到了解决方案。整个问题不在于 JScrollPane 本身,而在于如果文本不适合,则 JTextArea 调用自身的scrollRectToVisible。此调用通过 View 层次结构传播到 JScrollPane,导致它滚动到文本区域。
在我的例子中,我有 30 多个 JTextarea 且文本不断变化,这种情况经常发生。
我的解决方案是创建一个继承自 JTextArea 的自定义类,并使用空实现重写 scrollRectToVisible 方法。
这是工作示例:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class Main {
// custom Textarea class
static class MyTextArea extends JTextArea {
@Override
public void scrollRectToVisible(final Rectangle aRect) {
// supress scrollToRect in textarea
}
}
static final Box inner = Box.createVerticalBox();
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final JPanel insideScroll = insideScroll();
final JScrollPane scrollpane = new JScrollPane(insideScroll);
scrollpane.setAutoscrolls(false);
scrollpane
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
final JPanel rightPanel = new JPanel();
rightPanel.setPreferredSize(new Dimension(300, 300));
final MouseMotionAdapter listener = new MouseMotionAdapter() {
@Override
public void mouseDragged(final MouseEvent e) {
super.mouseDragged(e);
update();
}
};
rightPanel.addMouseMotionListener(listener);
// Add labels describing the problem
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));
final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
scrollpane, rightPanel);
frame.add(split);
// initialize the scrollpane content
update();
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
// initializes the components inside the scrollpane
private static JPanel insideScroll() {
final JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(inner, BorderLayout.NORTH);
return panel;
}
// replaces all components inside the scrollpane
private static void update() {
inner.removeAll();
for (int i = 0; i < 30; i++) {
inner.add(buildRow(i));
}
inner.revalidate();
}
// build a single component to be inserted into the scrollpane
private static JPanel buildRow(final int i) {
final JPanel row = new JPanel();
final Color bg = i % 2 == 0 ? Color.DARK_GRAY : Color.LIGHT_GRAY;
row.setBackground(bg);
row.setPreferredSize(new Dimension(300, 80));
row.setLayout(new BorderLayout());
row.add(textarea(bg), BorderLayout.CENTER);
return row;
}
// build the textarea to be inserted into the cells in the scroll pane
private static Component textarea(final Color bg) {
final String text = String.format("%d", (int) (1000 * Math.random()))
+ " Lorem ipsum dolor si amet. Lorem ipsum dolor si amet. Lorem ipsum dolor si amet";
final JTextArea textarea = new MyTextArea();
textarea.setDisabledTextColor(Color.cyan);
textarea.setEnabled(false);
textarea.setLineWrap(true);
textarea.setBackground(bg);
textarea.setEditable(false);
textarea.setText(text);
return textarea;
}
}
更新:我刚刚遇到了另一个线程,它提供了一个更好的解决方案来禁用 JTextArea 的自动滚动 - 无需子类化:
Java / Swing : JTextArea in a JScrollPane, how to prevent auto-scroll?
关于java - JScrollPane:重新验证后滚动位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31372997/
在 JSF2 应用程序中遇到验证属性的问题时,有两种主要方法。 使用 Annotation 在 ManagedBean 上定义验证 @ManagedBean public class MyBean {
我想实现一个不常见的功能,我认为 jquery 验证插件将是最好的方法(如果您在没有插件的情况下建议和回答,我们也会欢迎)。我想在用户在输入字段中输入正确的单词后立即隐藏表单。我试过这个: $("
我有几个下拉菜单(类名为month_dropdown),并且下拉菜单的数量不是恒定的。我怎样才能为它们实现 NotEqual 验证。我正在使用 jQuery 验证插件。 这就是我写的 - jQuery
我设法制作了这个网址验证代码并且它起作用了。但我面临着一个问题。我认为 stackoverflow 是获得解决方案的最佳场所。 function url_followers(){ var url=do
我目前正在使用后端服务,该服务允许用户在客户端应用程序上使用 Google Games 库登录。 用户可以通过他们的 gplay ID 向我们发送信息,以便登录或恢复旧帐户。用户向我们发送以下内容,包
我正在尝试验证输入以查看它是否是有效的 IP 地址(可能是部分地址)。 可接受的输入:172、172.112、172.112.113、172.112.113.114 Not Acceptable 输入
我从 Mongoose 验证中得到这条消息: 'Validator failed for path phone with value ``' 这不应该发生,因为不需要电话。 这是我的模型架构: var
我一直在尝试使用Python-LDAP (版本 2.4.19)在 MacOS X 10.9.5 和 Python 2.7.9 下 我想在调用 .start_tls_s() 后验证与给定 LDAP 服务
我正在处理一个仅与 IE6 兼容的旧 javascript 项目(抱歉...),我想仅在 VS 2017 中禁用此项目的 ESLint/CSLint/Javascript 验证/CSS 验证。 我知道
我正在寻找一种方法来验证 Spring 命令 bean 中的 java.lang.Double 字段的最大值和最小值(一个值必须位于给定的值范围之间),例如, public final class W
我正在尝试在 springfuse(JavaEE 6 + Spring Framework (针对 Jetty、Tomcat、JBoss 等)) 和 maven 的帮助下构建我的 webapps 工作
我试图在我们的项目中使用 scalaz 验证,但遇到了以下情况: def rate(username: String, params: Map[String, String]): Validation
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
我有一个表单,人们可以单击并向表单添加字段,并且我需要让它在单击时验证这些字段中的值。 假设我单击它两次并获取 2 个独立的字段集,我需要旋转 % 以确保它在保存时等于 100。 我已放入此函数以使其
在我的页面中有一个选项可以创建新的日期字段输入框。用户可以根据需要创建尽可能多的“截止日期”和“起始日期”框。就像, 日期_to1 || date_from1 日期到2 ||日期_from2 date
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
有没有办法在动态字段上使用 jquery 验证表单。 我想将其设置为必填字段 我正在使用 Jsp 动态创建表单字段。 喜欢 等等...... 我想使用必需的表单字段验证此表单字段。 最佳答
嗨,任何人都可以通过提供 JavaScript 代码来帮助我验证用户名文本框不应包含数字,它只能包含一个字符。 最佳答案 使用正则表达式: (\d)+ 如果找到匹配项,则字符串中就有一个数字。 关于J
我有两个输入字段holidayDate和Description(id=tags) $(document).ready(function() {
我遇到了这个问题,这些验证从电子邮件验证部分开始就停止工作。 我只是不明白为什么即使经过几天的观察,只是想知道是否有人可以在这里指出我的错误? Javascript部分: function valid
我是一名优秀的程序员,十分优秀!