Java JScrollBars值更改不保持最大值不变
因此,我有JScrollPaneJava JScrollBars值更改不保持最大值不变,java,max,setvalue,jscrollbar,Java,Max,Setvalue,Jscrollbar,因此,我有JScrollPane视图这样(这是我的最小可复制示例) 我将JScrollPane滚动条设置为具有新的最大值,可以在上面看到,但我将在这里再次键入。(这样做是为了在相同的视图大小下滚动得更慢(我的单位增量1对我来说仍然滚动得太快)) 所以我启动了这个程序,jscrollbars的最大尺寸明显增加了,这就是我想要的。有了这些,我还有下面的代码来使用keylistener更改jscrollbars值,这也可以在上面看到 case KeyEvent.VK_W: view.getVe
视图
这样(这是我的最小可复制示例)
我将JScrollPane滚动条设置为具有新的最大值,可以在上面看到,但我将在这里再次键入。(这样做是为了在相同的视图大小下滚动得更慢(我的单位增量1对我来说仍然滚动得太快))
所以我启动了这个程序,jscrollbars的最大尺寸明显增加了,这就是我想要的。有了这些,我还有下面的代码来使用keylistener更改jscrollbars值,这也可以在上面看到
case KeyEvent.VK_W:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() - 10*0.3));
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() + 10*0.3));
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() - 10*0.3));
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() + 10*0.3));
break;
问题:
当我按下这些键中的任何一个时,滚动条的最大值不再是我设置的值,而是将它们的最大值默认为首选大小map
(我通过在按下任何键之前和之后打印滚动条的最大值进行了测试,结果它们发生了变化)。我相信这个问题源于bar.setValue()
方法,不知道为什么
那么,如何防止jscrollbars更改其最大大小呢?我的目标是滚动整个jlabel
map
,仅使用W、A、S和D键,并将设置的最大值滚动到jscrollbars。我终于让您的示例在某种程度上起作用了。我可以用WASD键移动滚动条
我从JScrollPane
类字段中删除了static
我通过调用SwingUtilities
invokeLater
方法启动了Swing应用程序。此方法确保在上创建和执行Swing组件
我将键侦听器添加到JScrollPane
,而不是JFrame
我将JScrollPane
设置为可聚焦,这样按键就可以注册了。这样会容易得多
下面是完整的可运行代码
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
public class JScrollPaneTest implements KeyListener {
private JScrollPane view;
public JScrollPaneTest() {
create();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JScrollPaneTest();
}
});
}
public void create() {
JFrame frame = new JFrame(); //make frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
SpringLayout layout = new SpringLayout();
JPanel base = new JPanel();
base.setPreferredSize(new Dimension(1000, 1000));
base.setLayout(layout);
JPanel map = new JPanel(); //make panel for the scrollpane
map.setPreferredSize(new Dimension(1000, 1000));
view = new JScrollPane(map); //initialize scrollpane and add to base with a SpringLayout
view.setFocusable(true);
view.setPreferredSize(new Dimension(300, 300));
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, view, 0, SpringLayout.HORIZONTAL_CENTER, base);
layout.putConstraint(SpringLayout.VERTICAL_CENTER, view, 0, SpringLayout.VERTICAL_CENTER, base);
base.add(view); //add scrollpane to base jpanel
frame.add(base);
frame.setVisible(true);
view.addKeyListener(this);
view.getHorizontalScrollBar().setMaximum(10*800); //set wanted max sizes of each scroll bar
view.getVerticalScrollBar().setMaximum(10*800);
}
public void keyPressed(KeyEvent event) { // W, A, S, D keys to change values of jscrollbars
int verticalValue = view.getVerticalScrollBar().getValue();
int horizontalValue = view.getHorizontalScrollBar().getValue();
switch (event.getKeyCode()) {
case KeyEvent.VK_W:
view.getVerticalScrollBar().setValue(verticalValue - 10);
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().setValue(verticalValue + 10);
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().setValue(horizontalValue - 10);
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().setValue(horizontalValue + 10);
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
JScrollBar
使用DefaultBoundedRangeModel
跟踪值
在BasicScrollPaneUI
中是调用hsb.setValues(…)
的方法syncScrollPaneWithViewport()
setValues(…)方法调用BoundedRangeModel的setRangeProperties(…)
方法
不幸的是,最大值是根据添加到视口的面板宽度重置的
因此,我的建议是,您需要创建自己的自定义BoundedRangeModel,并确保“max”值未重置(为较小的值)?我不知道这是否会影响滚动
您可以在以下位置查看DefaultBoundedRangeModel和BasicScrollPaneUI的源代码:
下面是我用来验证max值是否由setValue(…)语句本身之外的方法更改的测试代码。但是,此语句显然会导致视口同步:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Test implements KeyListener {
private static JScrollPane view;
public Test() {
create();
}
public static void main(String[] args) {
SwingUtilities.invokeLater( () -> new Test() );
}
public void create() {
JFrame frame = new JFrame(); //make frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
SpringLayout layout = new SpringLayout();
JPanel base = new JPanel();
base.setPreferredSize(new Dimension(1000, 1000));
base.setLayout(layout);
JPanel map = new JPanel(); //make panel for the scrollpane
map.setPreferredSize(new Dimension(1200, 1200));
view = new JScrollPane(map); //initialize scrollpane and add to base with a SpringLayout
view.setPreferredSize(new Dimension(300, 300));
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, view, 0, SpringLayout.HORIZONTAL_CENTER, base);
layout.putConstraint(SpringLayout.VERTICAL_CENTER, view, 0, SpringLayout.VERTICAL_CENTER, base);
base.add(view); //add scrollpane to base jpanel
view.getHorizontalScrollBar().setModel( new MyBoundedRangeModel() );
System.out.println("default value");
System.out.println(view.getHorizontalScrollBar().getMaximum());
frame.add(base);
frame.setVisible(true);
frame.addKeyListener(this);
System.out.println("after Visible");
System.out.println(view.getHorizontalScrollBar().getMaximum());
view.getHorizontalScrollBar().setMaximum(10*800); //set wanted max sizes of each scroll bar
view.getVerticalScrollBar().setMaximum(10*800);
System.out.println("after changing maximum");
System.out.println(view.getHorizontalScrollBar().getMaximum());
}
public void keyPressed(KeyEvent event)
{
System.out.println("Before");
System.out.println(view.getHorizontalScrollBar().getValue());
System.out.println(view.getHorizontalScrollBar().getMaximum());
switch(event.getKeyCode()) {
case KeyEvent.VK_W:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() - 10*0.9));
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() + 10*0.9));
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() - 10*0.9));
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() + 10*0.9));
break;
}
System.out.println("after");
System.out.println(view.getHorizontalScrollBar().getValue());
System.out.println(view.getHorizontalScrollBar().getMaximum());
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
class MyBoundedRangeModel extends DefaultBoundedRangeModel
{
@Override
public void setValue(int i)
{
System.out.println("setValue");
super.setValue(i);
}
@Override
public void setMaximum(int i)
{
System.out.println("setMaximum");
super.setMaximum(i);
}
@Override
public void setMinimum(int i)
{
System.out.println("setMinimum");
super.setMinimum(i);
}
@Override
public void setExtent(int i)
{
System.out.println("setExtent");
super.setExtent(i);
}
@Override
public void setRangeProperties(int newValue, int newExtent, int newMin, int newMax, boolean adjusting)
{
System.out.println("setRangeProperties");
System.out.println(newValue + " : " + newExtent + " : " + newMax);
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
}
}
}
编辑:
上面的代码演示了如何扩展DefaultBoundedRangeModel。目前,它仅显示在更新模型时调用每个方法以尝试理解逻辑流的情况
请注意,在“setMaximum”之后,将使用正确的最大值调用“setRangeProperties”
但是,“setRangeProperties”会被第二次调用(这是在BasicScrollPaneUI中找到的逻辑的结果,正如我试图在回答的顶部解释的那样)。只有这一次,它是以面板宽度(1200)作为最大值调用的,而不是最初指定的8000
因此,您似乎需要重写setRangeProperties(…)
方法的代码,以便始终使用8000作为最大值。因此,当您创建MyBoundedRangeModel
的实例时,可能会传入您想要使用的最大值
我提供了一个链接,您可以在其中找到DefaultBoundedRangeModel的源代码。从setRangeProperties(…)
方法复制代码作为起点开始。然后您需要自定义代码,以确保最大值始终为8000
这是我对你如何解决这个问题的最好猜测。我不知道它是否有效。我们又一次提出了一个没有答案的问题。如果人们没有读过你最后的3或4个问题,他们就不知道你想做什么。@camickr对不起,让我把它做好now@camickr好的,在顶部我声明代码是我的最小可复制示例。我已经包括了主类的所有内容,下面我还有Map类的代码。我认为这就足够了。发布的代码无法编译。因此,这不是一个问题。我们应该能够复制/粘贴/编译和测试以查看所描述的行为。另外,您不需要Map类。您只需创建一个JPanel并设置首选大小。我通过在按下任何键之前和之后打印出滚动条的最大大小来测试它-这应该是MRE的一部分,这样我们就可以确切地看到您是如何测试的。@camickr好的,我编辑了我的帖子,我编辑了代码并亲自测试了它-它再现了我的问题。很抱歉在这里如此无知,谢谢你对我的耐心。我会在以后的帖子上投入更多的精力。@camickr你完全正确。我睡了一夜,然后立即醒来测试,忘记了我的最大值需要保持不变,并在意识到之前关闭了电脑。我刚刚回到这里,是想对你的评论进行评论,也是想看看你的评论。还有,如果你以前尝试过这个问题,你运气好吗?@ Gilbert Le Blanc,所以我的帖子应该已经和W,A,S和D键一起移动了。问题是,我设置滚动条的最大值在按下这些键后改变了它们的最大值。在您发布的示例中,我设置的最大值被忽略,并采用默认的滚动条大小。虽然这不完全是我想要的,但我感谢你的尝试
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
public class JScrollPaneTest implements KeyListener {
private JScrollPane view;
public JScrollPaneTest() {
create();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JScrollPaneTest();
}
});
}
public void create() {
JFrame frame = new JFrame(); //make frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
SpringLayout layout = new SpringLayout();
JPanel base = new JPanel();
base.setPreferredSize(new Dimension(1000, 1000));
base.setLayout(layout);
JPanel map = new JPanel(); //make panel for the scrollpane
map.setPreferredSize(new Dimension(1000, 1000));
view = new JScrollPane(map); //initialize scrollpane and add to base with a SpringLayout
view.setFocusable(true);
view.setPreferredSize(new Dimension(300, 300));
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, view, 0, SpringLayout.HORIZONTAL_CENTER, base);
layout.putConstraint(SpringLayout.VERTICAL_CENTER, view, 0, SpringLayout.VERTICAL_CENTER, base);
base.add(view); //add scrollpane to base jpanel
frame.add(base);
frame.setVisible(true);
view.addKeyListener(this);
view.getHorizontalScrollBar().setMaximum(10*800); //set wanted max sizes of each scroll bar
view.getVerticalScrollBar().setMaximum(10*800);
}
public void keyPressed(KeyEvent event) { // W, A, S, D keys to change values of jscrollbars
int verticalValue = view.getVerticalScrollBar().getValue();
int horizontalValue = view.getHorizontalScrollBar().getValue();
switch (event.getKeyCode()) {
case KeyEvent.VK_W:
view.getVerticalScrollBar().setValue(verticalValue - 10);
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().setValue(verticalValue + 10);
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().setValue(horizontalValue - 10);
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().setValue(horizontalValue + 10);
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Test implements KeyListener {
private static JScrollPane view;
public Test() {
create();
}
public static void main(String[] args) {
SwingUtilities.invokeLater( () -> new Test() );
}
public void create() {
JFrame frame = new JFrame(); //make frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
SpringLayout layout = new SpringLayout();
JPanel base = new JPanel();
base.setPreferredSize(new Dimension(1000, 1000));
base.setLayout(layout);
JPanel map = new JPanel(); //make panel for the scrollpane
map.setPreferredSize(new Dimension(1200, 1200));
view = new JScrollPane(map); //initialize scrollpane and add to base with a SpringLayout
view.setPreferredSize(new Dimension(300, 300));
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, view, 0, SpringLayout.HORIZONTAL_CENTER, base);
layout.putConstraint(SpringLayout.VERTICAL_CENTER, view, 0, SpringLayout.VERTICAL_CENTER, base);
base.add(view); //add scrollpane to base jpanel
view.getHorizontalScrollBar().setModel( new MyBoundedRangeModel() );
System.out.println("default value");
System.out.println(view.getHorizontalScrollBar().getMaximum());
frame.add(base);
frame.setVisible(true);
frame.addKeyListener(this);
System.out.println("after Visible");
System.out.println(view.getHorizontalScrollBar().getMaximum());
view.getHorizontalScrollBar().setMaximum(10*800); //set wanted max sizes of each scroll bar
view.getVerticalScrollBar().setMaximum(10*800);
System.out.println("after changing maximum");
System.out.println(view.getHorizontalScrollBar().getMaximum());
}
public void keyPressed(KeyEvent event)
{
System.out.println("Before");
System.out.println(view.getHorizontalScrollBar().getValue());
System.out.println(view.getHorizontalScrollBar().getMaximum());
switch(event.getKeyCode()) {
case KeyEvent.VK_W:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() - 10*0.9));
break;
case KeyEvent.VK_S:
view.getVerticalScrollBar().setValue((int) (view.getVerticalScrollBar().getValue() + 10*0.9));
break;
case KeyEvent.VK_A:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() - 10*0.9));
break;
case KeyEvent.VK_D:
view.getHorizontalScrollBar().setValue((int) (view.getHorizontalScrollBar().getValue() + 10*0.9));
break;
}
System.out.println("after");
System.out.println(view.getHorizontalScrollBar().getValue());
System.out.println(view.getHorizontalScrollBar().getMaximum());
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
class MyBoundedRangeModel extends DefaultBoundedRangeModel
{
@Override
public void setValue(int i)
{
System.out.println("setValue");
super.setValue(i);
}
@Override
public void setMaximum(int i)
{
System.out.println("setMaximum");
super.setMaximum(i);
}
@Override
public void setMinimum(int i)
{
System.out.println("setMinimum");
super.setMinimum(i);
}
@Override
public void setExtent(int i)
{
System.out.println("setExtent");
super.setExtent(i);
}
@Override
public void setRangeProperties(int newValue, int newExtent, int newMin, int newMax, boolean adjusting)
{
System.out.println("setRangeProperties");
System.out.println(newValue + " : " + newExtent + " : " + newMax);
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
}
}
}