繁体   English   中英

将JPanel添加到BorderLayout.Center时,以前的内容仍然可见

[英]When adding JPanel to BorderLayout.Center previous content remains visible

我有一个带有静态标头(BorderLayout.NORTH)和页脚(BorderLayout.SOUTH)的程序,并尝试在标头中的JComboBox上使用动作侦听器为正文(BorderLayout.CENTER)循环不同的JPanel。 据我了解BorderLayout,每次我向CENTER(或布局中的其他任何地方)添加JPanel(或任何组件)时,都会覆盖旧内容。 多数情况是这样,但是新的CENTER在其顶部保留了先前JPanel的轮廓(就像我从面板中删除removeAll()一样,轮廓)。

我一直在期望我犯了一个普遍的错误,但是我一直看到人们试图抵消我似乎无法触发的覆盖能力。 尝试了几种不同的修复方法(将单个Jpanel声明为实例变量,然后使用removeAll / revalidate / repaint更改其内容,创建单独的面板并将其添加,等等。)。

我将在下面包含大多数代码,但这是我的构造函数:

public UserInterface(Operator o, LocalDate d) {
    DefaultDateModel model = new DefaultDateModel(d);
    user = o; 

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //setup Menus
    if (user.getAccessPrivs().equalsIgnoreCase("OPRTR")) {
        OperatorMenus menu = new OperatorMenus(); 
        setJMenuBar(menu); }
    else if (user.getAccessPrivs().equalsIgnoreCase("ADMIN")) {
        AdminMenus menu = new AdminMenus(); 
        setJMenuBar(menu); }
    else {
        GalileoMenus menu = new GalileoMenus();
        setJMenuBar(menu); }

    //creates header with navigation buttons
    add(new NavButtons(model), BorderLayout.NORTH);

    //loads content 
    viewConstructor(model); 

    //creates footer
    JPanel footer = new JPanel();
        footer.setLayout(new BorderLayout());
        footer.setBackground(Color.BLACK);

        focusPoint = new JLabel(DateTimeFormatter.ofPattern("E, dd MMM yyyy").format(model.getDate()));
            focusPoint.setForeground(Color.RED);
        footer.add(focusPoint, BorderLayout.WEST);

        JLabel loggedIn = new JLabel(user.getName(), JLabel.RIGHT);
            loggedIn.setForeground(Color.CYAN);
        footer.add(loggedIn, BorderLayout.EAST);
    add(footer, BorderLayout.SOUTH); }

...以及我用来修改主体的方法:

public void viewConstructor(DefaultDateModel m) {
    DefaultDateModel model = m;

    //removeAll();
    body.removeAll();
    body.revalidate();
    body.repaint();
    getContentPane().remove(body);
    //body = new JPanel();
    //body.revalidate();
    //body.repaint();
    //body.updateUI();
    //body.setOpaque(false);

    //set window frame's title
    if      (panelZone == MYVIEW) { setTitle("My View"); }
    else if (panelZone == OPERTR) { setTitle("Operations"); }
    else if (panelZone == SHIFTS) { setTitle("Scheduling"); }
    else if (panelZone == FISCAL) { setTitle("Fiscal Report"); } 

    //builds body panel
    if (panelZone == MYVIEW) {
        add(new JScrollPane(buildMyView(model.getDate())), BorderLayout.CENTER); }

    else if (panelZone == OPERTR) {
        add(new JScrollPane(buildOperatorView(model.getDate())), BorderLayout.CENTER); }

    else if (panelZone == SHIFTS) {
        add(new JScrollPane(buildSchedulingView(model.getDate())), BorderLayout.CENTER); }

    else if (panelZone == FISCAL) {
        add(new JScrollPane(buildFiscalView(model.getDate())), BorderLayout.CENTER); }

    validate();
    revalidate();
    repaint();
    pack(); }

我知道我应该提出更多评论,等等。。。但是我将这些方法分开提出,因为其他方法现在有点混乱,这似乎是问题所在。 为了完整起见,这里是问题和其他代码段的屏幕截图(我在我的主UserInterface frame = new UserInterface(Current_User);称为UserInterface frame = new UserInterface(Current_User);就是这样)。

剩余的“正在建设中”来自默认的MyView面板

注意试图包括我的其余代码,但达到了字符数限制。 如果有人要我发布更多内容,我会以他们认为是问题的任何方式答复。

更新实现我正在使用JScrollPane,所以我创建了一个实例变量: private JScrollPane pane = new JScrollPane(); 所以我可以.removeAll()+ revalidate()+ repaint() pane

现在我身上什么也没有。 这是我的方法所在:

public void viewConstructor(DefaultDateModel m) {
    DefaultDateModel model = m;
pane.removeAll();

//set window frame's title
    if      (panelZone == MYVIEW) { setTitle("My View"); }
    else if (panelZone == OPERTR) { setTitle("Operations"); }
    else if (panelZone == SHIFTS) { setTitle("Scheduling"); }
    else if (panelZone == FISCAL) { setTitle("Fiscal Report"); } 

    //builds body panel
//      JScrollPane pane = new JScrollPane();
        if (panelZone == MYVIEW) {
 //         add(new JScrollPane(buildMyView(model.getDate())), BorderLayout.CENTER); }
        pane.setViewportView(buildMyView(model.getDate())); }

    else if (panelZone == OPERTR) {
    //  add(new JScrollPane(buildOperatorView(model.getDate())), BorderLayout.CENTER); }
        pane.setViewportView(buildOperatorView(model.getDate())); }

    else if (panelZone == SHIFTS) {
//      add(new JScrollPane(buildSchedulingView(model.getDate())), BorderLayout.CENTER); }
        pane.setViewportView(buildSchedulingView(model.getDate())); }

    else if (panelZone == FISCAL) {
//          add(new JScrollPane(buildFiscalView(model.getDate()))); }
        pane.setViewportView(buildFiscalView(model.getDate())); }       

    //validate();
//      body.revalidate();
//      body.repaint();
    pane.revalidate();
    pane.repaint();
    //repaint();
    pack(); }

社会科学中心

package interfaceComponents;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;

import javax.swing.*;

public class SSCCE extends JFrame {
    private static final long serialVersionUID = -5249508445298805323L;
private JScrollPane pane = new JScrollPane();
private int stage = 0;

public SSCCE() {
    JPanel header = new JPanel(); 
        JButton cycler = new JButton("Cycle");
        cycler.addActionListener(new ActionListener() {         
            public void actionPerformed(ActionEvent event) {
                stage++;
                if (stage == 3) { stage = 0; }
                buildBody(); }
        });
        header.add(cycler);
    add(header, BorderLayout.NORTH);

    add(pane, BorderLayout.CENTER);
    buildBody();

    JPanel footer = new JPanel();
        footer.add(new JLabel("Random Text"));
    add(footer, BorderLayout.SOUTH); }

public void buildBody() {
    JPanel body = new JPanel();
        if      (stage == 0) { body.setBackground(Color.RED); }
        else if (stage == 1) { body.setBackground(Color.WHITE); }
        else { body.setBackground(Color.BLUE); }
    pane.setViewportView(body); }
}

据我了解BorderLayout,每次我向CENTER(或布局中的其他任何地方)添加JPanel(或任何组件)时,都会覆盖旧内容。

不,它不会覆盖旧内容。 BorderLayout仅跟踪在任何给定约束位置添加的最后一个组件。 因此,当调用布局管理器时,仅给该组件一个大小/位置。

但是,任何以前的组件仍将具有大小/位置。 同样由于Z-Ordering的工作原理,最后添加的最后一个组件被绘制。 因此,先绘制新组件,然后在新组件之上绘制旧组件。

为防止这种情况发生,您必须在添加新面板之前先移除旧面板。

尝试为身体循环使用不同的JPanel

更好的解决方案是使用CardLayout因为它将为您管理面板的循环。 因此,使用CardLayout将面板添加到BorderLayout的CENTER。 然后将所有可交换面板添加到卡布局面板。 阅读Swing教程中有关如何使用CardLayout的部分,以获取更多信息和示例。

编辑:

您将如何“首先删除旧面板”

好吧,在某个地方您必须具有以下代码:

panel.add(panel1, BorderLayout.CENTER);

因此,如果要交换面板,则需要如下代码:

panel.remove(panel1);
panel.add(panel2, BorderLayout.CENTER);
panel.revalidate();
panel.repaint();

因此,您可以管理对添加到CENTER的最后一个组件的引用,以便您可以手动将其删除。 这就是CardLayout更加容易的原因,它可以为您进行管理。

编辑2:

之前没有注意到滚动窗格。 这使它变得更加容易。 创建框架时,只需使用:

frame.add(scrollPane, BorderLayout.CENTER);

然后,当您想交换面板时,它的一行代码:

scrollPane.setViewportView( panel2 );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM