【问题标题】:Adjusting JScrollPane according to the JPanel inside it根据里面的JPanel调整JScrollPane
【发布时间】:2023-04-04 15:02:01
【问题描述】:

我有一个扩展 JPanel 的类,它被放置在 JScrollPane 中。正如您从代码中看到的那样,我正在使用鼠标滚轮放大和缩小面板。到目前为止一切都很好。但是如何使 ScrollPane 相应地调整自身呢?我已经覆盖了 JPanel 的 getPreferredSize(),认为 JScrollPane 使用它来调整它的大小。但是现在当我运行程序时,我可以放大缩小所有内容,但滚动窗格不会出现。仅供参考,我有一个 JFrame,其中有 JScrollPane。我从 JFrame 创建了上面显示的 SimPanel 类的对象,并将其添加到 JscrollPane 中。

编辑: *以下类放在一起将编译并运行并显示问题。*

以下是JFrame类:

package gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;


import javax.swing.JFrame;
import javax.swing.JScrollBar;

public class MyJFrame extends JFrame{
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;  
    public MyJFrame() {
        initComponents();
    }
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jTextField1 = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jTextField2 = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();        
        jPanel2 = new SimPanel(jScrollPane1.getViewportBorderBounds().getHeight(),jScrollPane1.getViewportBorderBounds().getWidth());
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenu2 = new javax.swing.JMenu();
        JScrollBar hScrollBar;
        JScrollBar vScrollBar;
        final SwingWorker worker = new SwingWorker() {
               public Object construct() {
                   for(;;){                                        
                       repaint();
                   }
               }               
            };

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jLabel1.setText("");

        jLabel2.setText("");

        jButton1.setText("START");

        jButton2.setText("USELESS");

        jButton1.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae){
                worker.start();             
                repaint();              
            }
        });
        jButton2.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae){        
                repaint();              
            }
        });
        hScrollBar=jScrollPane1.getHorizontalScrollBar();
        vScrollBar=jScrollPane1.getVerticalScrollBar();

        hScrollBar.addAdjustmentListener(new AdjustmentListener(){
            public void adjustmentValueChanged(AdjustmentEvent ae1){
                repaint();
            }
        });
        vScrollBar.addAdjustmentListener(new AdjustmentListener(){
            public void adjustmentValueChanged(AdjustmentEvent ae2){
                repaint();
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jTextField2)
                    .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 51, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButton1)
                    .addComponent(jButton2))
                .addContainerGap(14, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton2))
                .addContainerGap(568, Short.MAX_VALUE))
        );

        jPanel2.setPreferredSize(new java.awt.Dimension(5000, 5000));

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 5000, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 5000, Short.MAX_VALUE)
        );

        jScrollPane1.setViewportView(jPanel2);

        jMenu1.setText("File");
        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");
        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 858, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 631, Short.MAX_VALUE)
        );

        pack();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MyJFrame().setVisible(true);
            }
        });
    } 
}

以下是 SimPanel 类:

package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.Random;

import javax.swing.JPanel;

public class SimPanel extends JPanel implements MouseWheelListener{
    Dimension area;
    double height,width;
    double scale=0.5;
    private static Random rand=new Random();
    public SimPanel(double h, double w) {       
        height=h;
        width=w;
        addMouseWheelListener(this);
    }
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2d;
        g2d=(Graphics2D)g.create();
        g2d.translate(width/2, height/2);
        g2d.scale(scale, scale);
        g2d.translate(-width/2, -height/2);
        g2d.setColor(Color.GREEN);
        g2d.drawLine(5000, 0, 5000, 5000);
        g2d.drawLine(0, 5000, 5000, 5000);
        g2d.drawLine(0, 0, 0, 5000);
        g2d.drawLine(0, 0, 5000, 0);
        area=new Dimension((int)width,(int)height);     
        for(int i=0;i<100;i++){
            g2d.fillRect(rand.nextInt(5000), rand.nextInt(5000), 100, 100);         
        }
        g2d.setColor(Color.RED);
        for(int i=0;i<100;i++){
            g2d.fillRect(rand.nextInt(5000), rand.nextInt(5000), 100, 100);
        }
        g2d.dispose();
    }
    /*@Override
    public Dimension getPreferredSize(){
        return new Dimension((int)(width*scale) , (int)(height*scale));
    }*/
    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        if(e.getWheelRotation()<0){
            scale=scale>=1.0?1.0:scale+0.05;
        }
        else if(e.getWheelRotation()>0){
            scale=scale<=0.1?0.1:scale-0.05;
        }
        repaint();
    }
}

你可以从这里获得摇摆工人阶级: http://java.sun.com/products/jfc/tsc/articles/threads/src/SwingWorker.java

【问题讨论】:

  • 请提供sscce
  • @trashgod 我已按问题更新以提供一个简短的、自包含的示例来显示问题。它将编译并运行。
  • 你不需要javax.swing.SwingUtilities.SwingWorker
  • @trashgod 但这不是导致问题的原因吗?
  • 不,您需要将模型移出视图并实现Scrollable。当您确实需要它时,请使用javax.swing.SwingWorker&lt;T,V&gt;

标签: java swing jscrollpane


【解决方案1】:

您的面板需要实现 Scrollable。我总是忘记为 Scrollable 中的每个方法设置什么的确切细节,但我认为您希望 getPreferredScrollableViewportSize 返回您希望在任何给定时间可见的维度

【讨论】:

    【解决方案2】:

    您可以尝试添加:

    revalidate();
    repaint();
    

    当您更改比例时。否则我认为滚动窗格不会知道面板已更改。

    如果您需要更多帮助,请发布您的 SSCCE。

    编辑:

    这不是 SSCCE!菜单与滚轮问题有什么关系?按钮和文本字段与问题有什么关系?只发布与问题相关的代码,我们没有时间看不必要的代码。

    我建议您添加的 revalidate() 代码在哪里?

    为什么要注释掉 getPreferredSize() 方法?如果您希望滚动条按需要显示,则需要更改首选大小。

    您的代码的问题是首选大小没有意义。当我测试它时,宽度是-3。所以你创建 SimPanel 的代码是错误的。我将值 300、300 定义为 SimPanel 的参数。我也用过:

            if(e.getWheelRotation()<0){
    //            scale=scale>=1.0?1.0:scale+0.05;
                scale += 0.05;
            }
            else if(e.getWheelRotation()>0){
    //            scale=scale<=0.1?0.1:scale-0.05;
                scale -= -0.05;
            }
    

    为了我的快速测试,它运行良好。

    【讨论】:

    • 我已按问题更新以提供一个简短的、自包含的示例来显示问题。它将编译并运行。
    • 实际上我减少了很多代码,但仍然保留了一些不必要的代码。对此感到抱歉。我用过 revalidate();但这似乎没有任何区别。无论如何,我会根据您的上述建议再试一次。你在 getPreferredSize() 中使用了什么?
    • 我的问题不是滚轮。它工作正常。问题是滚动窗格没有根据里面客户端的大小进行自我调整。
    • 我说问题是你的preferredSize() 计算。添加一些调试代码以显示计算的大小,然后修复计算。我已经告诉过你我为快速测试做了什么。我不知道你的真实代码应该做什么。
    猜你喜欢
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    相关资源
    最近更新 更多