JPanel CardLayout 导致交换之间出现视觉故障

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

我正在尝试创建一个带有 CardLayout 的 JPanel,按下按钮时可以在菜单和论坛之间切换,但我遇到了一个视觉错误,当我切换到论坛时,菜单元素仍在显示。

(如果相关,我的系统规格是: MacBook Air(13 英寸,2015 年初), 2.2 GHz 双核英特尔酷睿 i7, 8 GB 1600 MHz DDR3, 英特尔高清显卡 6000 1536 MB, MacOS 蒙特利 12.6.7)

以下是我的基本实现的简化示例。显然,示例中的某些功能并未完全实现。

主要课程:

import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setContentPane(new MainPanel());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

主面板类:

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

public class MainPanel extends JPanel {
    private final CardLayout layout = new CardLayout();
    private final Menu menuScreen;
    private final Forum forumScreen;
    public static final String MENU = "1";
    public static final String FORUM = "2";

    public MainPanel() {
        setLayout(layout);
        menuScreen = new Menu(this);
        add(menuScreen, MENU);
        forumScreen = new Forum(this);
        add(forumScreen, FORUM);
        layout.show(this, MENU);
    }

    public void navigate (String destination) {
        layout.show(this, destination);
        switch (destination) {
            case MENU -> menuScreen.updateUI();
            case FORUM -> forumScreen.updateUI();
        }
        this.revalidate();
        this.updateUI();
    }
}

菜单类别:

import java.awt.*;
import java.awt.event.ActionEvent;

public class Menu extends Screen {

    private final MainPanel panel;

    public Menu(MainPanel panel) {
        this.panel = panel;

        Button deleteButton = new Button("Delete");
        deleteButton.addActionListener(this::delete);
        add(deleteButton);

        Button loadButton = new Button("Load");
        loadButton.addActionListener(this::load);
        add(loadButton);

        Button forumButton = new Button("Forum");
        forumButton.addActionListener(this::toForum);
        add(forumButton);
    }

    private void toForum(ActionEvent actionEvent) {
        panel.navigate(MainPanel.FORUM);
    }

    private void load(ActionEvent actionEvent) {
    }

    private void delete(ActionEvent actionEvent) {
    }
}

论坛课程:

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

public class Forum extends Screen {

    private final MainPanel panel;
    private final JSpinner heightField = new JSpinner(new SpinnerNumberModel(1,1,Integer.MAX_VALUE,1));
    private final JSpinner widthField = new JSpinner(new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1));

    public Forum(MainPanel panel) {
        this.panel = panel;

        add(new Label("Forum", Label.CENTER));

        add(new Label("Height"));
        add(heightField);

        add(new Label("Width"));
        add(widthField);

        Button exitButton = new Button("Exit");
        exitButton.addActionListener(this::exit);
        add(exitButton);
    }

    private void exit(ActionEvent actionEvent) {
        panel.navigate(MainPanel.MENU);
    }
}

屏幕类别:

import javax.swing.*;

public class Screen extends JPanel {
    public Screen() {
        setBorder(BorderFactory.createEmptyBorder(30,30,30,30));
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    }
}

从功能上讲,代码成功地在面板之间切换,但我一直遇到视觉故障,即最后一个面板的元素显示并覆盖新面板上的元素。我仍然可以选择新面板中被覆盖的元素,并且在我这样做之后,它们似乎被切换到有故障的元素前面的前景。

Menu Forum with Glitched Display

注意:这是一个较大项目的一部分,因此此处看到的 UI 可能与上面的代码不完全匹配。不过,我要指出的是,在使用 CardLayout 时,整个项目中都出现了类似的故障。

我尝试了多种修复方法。我将java版本回滚到java 11,但仍然遇到同样的问题。我制作了一个加载卡来强制用户界面通过两个开关进行更新,但我发现空的加载卡并不能解决问题,并且带有元素的加载卡仍然会导致视觉故障。如代码中所示,我尝试了各种可能更新面板的调用,例如 revalidate、updateUI 和 repaint,但我尝试过的任何方法都不起作用。

如果您有任何建议,请告诉我。

java swing user-interface jpanel cardlayout
1个回答
0
投票

看来,通过从 awt 组件(Button 和 Label)切换到 swing 轻量级组件(JButton 和 JLabel)可以解决视觉问题。例如,菜单类是:

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

public class Menu extends Screen {

    private final MainPanel panel;

    public Menu(MainPanel panel) {
        this.panel = panel;

        JButton deleteButton = new JButton("Delete");
        deleteButton.addActionListener(this::delete);
        add(deleteButton);

        JButton loadButton = new JButton("Load");
        loadButton.addActionListener(this::load);
        add(loadButton);

        JButton forumButton = new JButton("Forum");
        forumButton.addActionListener(this::toForum);
        add(forumButton);
    }

    private void toForum(ActionEvent actionEvent) {
        panel.navigate(MainPanel.FORUM);
    }

    private void load(ActionEvent actionEvent) {
    }

    private void delete(ActionEvent actionEvent) {
    }
}

感谢并感谢充满鳗鱼的气垫船

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