You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切换CardLayout面板后可视化面板为空的问题求助

问题:选择排序可视化面板数组未渲染

点击主菜单的可视化按钮切换到Sorting面板后,数组内容未显示,面板为空。已确认面板切换逻辑正常(菜单面板隐藏,可视化面板显示),尝试过paint()和paintComponent()均无效。

  • Sorting类是承载数组可视化的面板
  • ArrayVis类负责实现数组可视化(未完成)
  • 本人为Java新手,请求排查原因

代码清单

Main.java

import project.MainMenu;

public class Main {
    public static void main(String[] args) {
        new MainMenu();
    }
}
package project;

import java.awt.*;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class MainMenu extends JFrame {
    private JPanel mainPanel;
    private JPanel visualization;
    private JPanel menu;
    private JLabel label;
    private JButton visualizeButton;
    private JLabel description;
    Dimension screen;

    public MainMenu() {
        menu = new JPanel();
        visualization = new Sorting();
        mainPanel = new JPanel();

        CardLayout cardLayout = new CardLayout();
        mainPanel.setLayout(cardLayout);

        GridLayout layout = new GridLayout(0, 1);
        layout.setVgap(10);

        menu.setLayout(layout);
        mainPanel.setBorder(new EmptyBorder(10,10,10,10));


        label = new JLabel("Сортировка выбором");
        label.setFont(label.getFont().deriveFont(36.0f));
        label.setHorizontalAlignment(getX());

        description = new JLabel("<html><span>Описание какое-то сортировки</span></html>");
        description.setFont(label.getFont().deriveFont(20.0f));

        visualizeButton = new JButton("Посмотреть визуализацию");
        visualizeButton.addMouseListener(new java.awt.event.MouseAdapter() {
            boolean clicked = false;

            public void mouseEntered(java.awt.event.MouseEvent evt) {
                visualizeButton.setBackground(new Color(155, 239, 245));
            }

            public void mouseExited(java.awt.event.MouseEvent evt) {
                if (!clicked)
                    visualizeButton.setBackground(new Color(255,255,255));
            }
/// changing panels
            public void mousePressed(java.awt.event.MouseEvent evt) {
                clicked = true;
                mainPanel.add(visualization, "visualization");
                cardLayout.show(mainPanel,"visualization");
            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.setSize(50,40);
        buttonPanel.add(visualizeButton, BorderLayout.CENTER);

        menu.add(label, BorderLayout.NORTH);
        menu.add(description, BorderLayout.CENTER);
        menu.add(buttonPanel, BorderLayout.SOUTH);


        mainPanel.add(menu,"menu");

        cardLayout.show(mainPanel,"menu");

        add(mainPanel);

        screen = Toolkit.getDefaultToolkit().getScreenSize();

        setExtendedState(Frame.MAXIMIZED_BOTH);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Сортировка выбором");
        setBounds(0, 0, 500, 500);
        setVisible(true);
    }
}

Sorting.java

package project;

import javax.swing.*;
import java.awt.*;


public class Sorting extends JPanel {
    private JPanel buttonPanel;
    private JButton addNum;
    private JButton startVisualizing;
    private JButton resetArray;
    private int x = 15;
    private int[] arr;
    private int y = 15;

    public Sorting(){
        setLayout(new FlowLayout());
        arr = new int[]{1,2,3};
        add(new ArrayVis(arr,x,y));
        x += 10 * arr.length;

    }

    public void selectionSort() {
        for (int i = 0; i < arr.length; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            int helper = arr[i];
            arr[i] = arr[min];
            arr[min] = helper;
        }
    }
}

ArrayVis.java

package project;

import javax.swing.*;
import java.awt.*;

public class ArrayVis extends JComponent {
    private int[] arr;
    private int x;
    private int y;

    public ArrayVis(int[] arr,int x, int y){
        this.arr = arr;
        this.x = x;
        this.y = y;
    }

    @Override
    public void paint(Graphics g){
        g.setColor(Color.RED);
        for (int i = 0;i<arr.length;i++){
            g.drawString(Integer.toString(arr[i]),x,y);
            x += 10;
        }
    }
}

问题排查与修复

1. ArrayVis组件未设置大小,导致无法显示

Swing的JComponent默认大小为(0,0),即使重写paint方法也不会自动计算尺寸。需要重写getPreferredSize()方法指定组件大小:

// 在ArrayVis类中添加
@Override
public Dimension getPreferredSize() {
    int width = arr.length * 15 + 20; // 每个数字留15像素宽度,加左右边距
    int height = 30; // 足够显示一行文字的高度
    return new Dimension(width, height);
}

同时,不要在paint方法中修改成员变量x,否则每次重绘时文字会持续偏移,改用局部变量:

@Override
public void paint(Graphics g){
    super.paint(g); // 必须调用父类方法,确保背景正常绘制
    g.setColor(Color.RED);
    int drawX = x; // 用局部变量保存起始x坐标
    for (int num : arr) {
        g.drawString(Integer.toString(num), drawX, y);
        drawX += 15; // 调整间距避免文字重叠
    }
}

2. 重复添加visualization面板引发布局问题

在mousePressed事件中每次点击都会执行mainPanel.add(visualization, "visualization");,导致组件被重复添加。将面板添加逻辑移到构造方法中:

// 修改MainMenu构造方法,将visualization添加逻辑移到menu之后
mainPanel.add(menu,"menu");
mainPanel.add(visualization, "visualization"); // 新增这一行
cardLayout.show(mainPanel,"menu");

然后修改mousePressed方法,只保留面板切换逻辑:

public void mousePressed(java.awt.event.MouseEvent evt) {
    clicked = true;
    cardLayout.show(mainPanel,"visualization");
}

3. JLabel水平对齐参数错误

label.setHorizontalAlignment(getX());中的getX()是窗口坐标,不是对齐常量,改为:

label.setHorizontalAlignment(JLabel.CENTER);

完成以上修改后,切换到Sorting面板即可看到红色的数组文字。后续可继续完善排序动画和按钮功能。

内容的提问来源于stack exchange,提问作者kirin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 23:27:45