如何更改 ScrollPane 的长度?

问题描述 投票:0回答:1

我想更改scrollPane的内部大小。

我尝试过各种方法,但都做不到。我希望每次创建任务时,ScrollPane 的长度都会发生变化。 (它就像感知 JPanel 是否已满然后滚动条的长度增加)。

我有一个任务类(它只是生成任务的类)

这是我的列表类(将任务放在列表中):

package com.chri_stw.todolist;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.GridLayout;
import javax.swing.JPanel;

public class List extends JPanel {

    private int cornerRadius; // Allows customization of the corner radius

    List() {
        this.cornerRadius = 30; // Default corner radius
        GridLayout layout = new GridLayout(10, 1);
        layout.setVgap(5);  // Vertical gap between components

        this.setLayout(layout);
        this.setPreferredSize(new Dimension(400, 400));  // Preferred size
        this.setBackground(Color.cyan);
        add(new Task());
        setOpaque(false); // Set the panel to be non-opaque to show rounded corners
    }

    // Override paintComponent to add rounded edges
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Smooth edges
        g2.setColor(getBackground());
        g2.fillRoundRect(0, 0, getWidth(), getHeight(), cornerRadius, cornerRadius); // Draw rounded background
        super.paintComponent(g2);
        g2.dispose();
    }

    public void updateNumbers() {
        Component[] listItems = this.getComponents();

        for (int i = 0; i < listItems.length; i++) {
            if (listItems[i] instanceof Task) {
                ((Task) listItems[i]).changeIndex(i + 1);  // Update task index
            }
        }
        revalidate();  // Ensure layout recalculation
        repaint();  // Ensure the panel is redrawn
    }

    public void removeCompletedTasks() {

        for (Component c : getComponents()) {
            if (c instanceof Task) {
                if (((Task) c).getState()) {
                    remove(c);  // Remove completed tasks
                }
            }
        }
        updateNumbers();  // Update task indices
        revalidate();  // Recalculate layout after removing tasks
        repaint();  // Redraw the panel
    }

    // Method to add tasks to the list
    public void addTask(Task task) {
        this.add(task);  // Add task to the panel
        revalidate();  // Ensure that layout updates after adding the task
        repaint();  // Redraw the panel to reflect the new task
    }

    // Force setting the size explicitly, in case revalidation does not update it
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(350, 560);  // Ensure preferred size
    }
}

这是 AppFrame(完成所有 UI):

package com.chri_stw.todolist;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicScrollBarUI;

public class AppFrame extends JFrame {

    private TitleBar title;
    private Footer footer;
    private List list;

    private JButton newTask;
    private JButton clear;

    AppFrame() {
        // Set default frame properties
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);

        // Initialize components
        title = new TitleBar();
        footer = new Footer();
        list = new List();

        JScrollPane scrollPane = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        JScrollBar scroll = scrollPane.getVerticalScrollBar();
        scrollPane.setBorder(null);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setUI(new BasicScrollBarUI() {
            @Override
            protected void configureScrollBarColors() {
                this.thumbColor = Color.gray;
            }
        });
        scroll.setUnitIncrement(1); // Smooth scrolling
        scroll.setForeground(Color.gray);

        add(scrollPane);

        // Add components to the frame
        this.setLayout(new BorderLayout());
        this.add(title, BorderLayout.NORTH);
        this.add(footer, BorderLayout.SOUTH);
        this.add(scrollPane, BorderLayout.CENTER);

        // Initialize footer buttons
        newTask = footer.getNewTask();
        clear = footer.getClear();

        // Add listeners to buttons
        addListeners();

        // Adjust frame size and make it visible
        this.setPreferredSize(new Dimension(400, 700));
        this.pack(); // Adjust size based on preferred sizes
        this.setLocationRelativeTo(null); // Center the frame on the screen
        this.setVisible(true);
    }
    
    

    public void addListeners() {
        // Listener for "New Task" button
        newTask.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                Task task = new Task();
                list.add(task);
                list.updateNumbers();

                task.getDone().addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        task.toggleState(); // Toggle the task's state
                        list.updateNumbers();
                        revalidate();
                    }
                });
            }
        });

        // Listener for "Clear" button
        clear.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                list.removeCompletedTasks(); // Remove completed tasks
                repaint();
            }
        });
    }
}

java swing jscrollpane
1个回答
0
投票

出现此问题是因为

JScrollPane
依赖于其视口的首选大小(在您的情况下为
List
面板)来计算可滚动区域。如果首选大小未动态更新,可滚动区域将保持固定,导致滚动条行为不正确。

根据

List
面板包含的任务数量修改其首选大小。将以下方法添加到您的
List
类中:

public void updatePreferredSize() {
    int taskHeight = 50;
    int gap = 5;
    int totalHeight = (taskHeight + gap) * this.getComponentCount() - gap;
    this.setPreferredSize(new Dimension(400, Math.max(totalHeight, 400)));
}

每当添加、删除或更新任务时调用

updatePreferredSize()
方法:

public void addTask(Task task) {
    this.add(task);
    updatePreferredSize();
    revalidate();
    repaint();
}

public void removeCompletedTasks() {
    for (Component c : getComponents()) {
        if (c instanceof Task) {
            if (((Task) c).getState()) {
                remove(c);
            }
        }
    }
    updatePreferredSize();
    revalidate();
    repaint();
}

public void updateNumbers() {
    Component[] listItems = this.getComponents();

    for (int i = 0; i < listItems.length; i++) {
        if (listItems[i] instanceof Task) {
            ((Task) listItems[i]).changeIndex(i + 1);
        }
    }
    updatePreferredSize();
    revalidate();
    repaint();
}

避免在

List
中为
AppFrame
面板设置固定的首选尺寸。让动态更新来处理它。

© www.soinside.com 2019 - 2024. All rights reserved.