Java 在JFrame中以编程方式交换两个JPanel

Java 在JFrame中以编程方式交换两个JPanel,java,swing,jpanel,awt,swap,Java,Swing,Jpanel,Awt,Swap,我正在尝试完成上述功能,但收效甚微。 我使用2列2行的GridLayout向用户展示了一个类似于拼图的游戏,其中有4个(200x200像素)JPanel(3种颜色,1种默认bgColor)填充整个contentPane。如果面板靠近灰色面板,则单击彩色面板将在评估中解析。如果是这样,他们应该交换。我已经完成了每一步,直到最后一步,在那里他们交换。代码如下: public class MainClass extends JFrame { //Generated private static fin

我正在尝试完成上述功能,但收效甚微。 我使用2列2行的GridLayout向用户展示了一个类似于拼图的游戏,其中有4个(200x200像素)JPanel(3种颜色,1种默认bgColor)填充整个contentPane。如果面板靠近灰色面板,则单击彩色面板将在评估中解析。如果是这样,他们应该交换。我已经完成了每一步,直到最后一步,在那里他们交换。代码如下:

public class MainClass extends JFrame {
//Generated
private static final long serialVersionUID = 4710628273679698058L;

private SpecialPanel redPanel;
private SpecialPanel greenPanel;
private SpecialPanel yellowPanel;
private SpecialPanel grayPanel;

public MainClass() {
    super("Puzzle");

    initPanels();

    setSize(410, 410);
    setLayout(new GridLayout(2, 2));

    this.add(redPanel);
    this.add(greenPanel);
    this.add(grayPanel);
    this.add(yellowPanel);
}
private void initPanels() {
    redPanel = new SpecialPanel();
    greenPanel = new SpecialPanel();
    yellowPanel = new SpecialPanel();
    grayPanel = new SpecialPanel();

    grayPanel.setGreyPanel(true);

    redPanel.setBackground(Color.RED);
    greenPanel.setBackground(Color.GREEN);
    yellowPanel.setBackground(Color.YELLOW);
    grayPanel.setBackground(this.getBackground());

    redPanel.setSize(200, 200);
    greenPanel.setSize(200, 200);
    yellowPanel.setSize(200, 200);
    grayPanel.setSize(200, 200);

    MouseAdapter ma = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent arg0) {
            super.mouseClicked(arg0);

            SpecialPanel sp = (SpecialPanel) arg0.getComponent();

            if (sp.getIsGray()) {
                //Do nothing
            } else if (checkIfNeighbourToGray(sp, grayPanel)) {
                //Swap them
                System.out.println("Swap notification");
                swap(sp, grayPanel);                
                //Update UI
            } else {
                //Again, do nothing for the clicked panel is diagonal to the gray panel
            }
        }

        private boolean checkIfNeighbourToGray(SpecialPanel sp, SpecialPanel grayPanel) {

            Point startPointSp = sp.getLocation();
            double x = startPointSp.getX();
            double y = startPointSp.getY();

            double width = sp.getWidth();
            double height = sp.getHeight();

            Point grayPoint = grayPanel.getLocation();
            double xG = grayPanel.getX();
            double yG = grayPanel.getY();

            double widthG = grayPanel.getWidth();
            double heightG = grayPanel.getHeight();

            //Gray panel is RIGHT of clicked one
            if (x + width == xG && y + height == yG + heightG) {
                return true;                    
            }
            //Gray panel is LEFT of clicked one
            else if (x - width == xG && y + height == yG + heightG) {
                return true;
            }
            //Gray panel is ABOVE of clicked one
            else if (x == xG && x + width == xG + widthG) {
                return true;
            }
            //Gray panel is UNDER of clicked one
            else if (xG == x && yG + widthG == x + width) {
                return true;
            }

            return false;
        }

        private void swap(SpecialPanel sp, SpecialPanel grayPanel) {
            //Swap logic
        }

    };
    redPanel.addMouseListener(ma);
    greenPanel.addMouseListener(ma);
    yellowPanel.addMouseListener(ma);
    grayPanel.addMouseListener(ma);

}
public static void main(String[] args) {
    MainClass mc = new MainClass();
    mc.setVisible(true);

}

}
SpecialPanel类使用一个新的布尔属性IsGrayPanel扩展了JPanel,该属性最初设置为false+getter和setter。 注意:这是以一种“我有基本的Swing技能”的方式完成的,虽然我在这段时间里学到了更多关于java Swing的知识,但我当时只限于基本的Swing功能,所以我应该保持这种方式。
因此,我的问题是如何正确地交换相邻的两个面板,包括UI更新?

我不确定这是否有效。看起来太容易了

JPanel tempPanel = sp;
sp = grayPanel;
grayPanel = tempPanel;

this.setVisible(false);
this.setVisible(true);
this.validate(); //try this first
this.repaint(); // if it doesnt work, add this function. 
  • 不需要将
    JPanels
    移动到容器中,否则您需要使用一堆非常无用的代码从包含两个
    索引的容器中删除两个
    JPanels
    ,然后使用
    交换索引将其布局回容器中

  • (如果是关于
    Color
    only)仅在两个
    jpanel之间交换
    setBackground(Color.Xxx)

  • 益智类游戏
    是关于
    图像
    ,益智类或地雷类游戏是关于,(你不清楚…)

  • Images
    作为
    Icon/ImageIcons
    放置到
    JLabel
    而不是
    JPanel
    ,并在
    Mouse Events
    上使用
    图标切换(
    setIcon()
    ),将
    图标加载到本地变量

  • (最简单的方法)有与
    JLabel
    相似的逻辑,但是关于在
    setPressedIcon()上显示
    图标


您是否尝试过同时添加它们,但从未删除任何一个,只是更改setVisible()标志?我相信你可以把它们都放在面板上,但是一次只看到一个,你会得到你想要的结果。太多可能的问题,看看ZOrder,但是要想得到真正的答案,发布,简而言之,运行,可编译,由GridLayout放置的空JPanel,这个SSCE需要设置大小JFrame@SaviourSelf “他们两个都在小组里,您指的是主windows内容窗格吗?如果我用wright的方法,如果单击灰色面板旁边的彩色面板,将Visible属性设置为false应该可以让我更接近结果?@mKorbel可以,在删除任何不必要的代码时编辑问题,对不起!另请参阅这篇相关文章。中途,我在控制台中收到了交换通知,但在UI方面并没有特别的更改。如果您知道一种不用SwingWorker类或invokeLater方法更新UI更改的好方法,我将非常感谢您的贡献:)天哪,它成功了!我很惊讶。尝试刷新框架。我编辑了代码。我在编程课上经常使用这种技巧。在执行交换后扩展窗口时,它会改变吗?不,不会!我很惊讶同样的事情对我不起作用。我确实有一个交换(sp,grayPanel),它的代码与您的答案相同,我把它注释掉了,因为最简单的操作不起作用。这是我的第一个选择,从那以后我只会经历一次又一次的失败。好吧,我添加了一些改变。建议:如果你做的只是换一块灰色的面板,为什么不换一下面板的颜色呢?获取每个面板的背景色属性并对其进行更改。在我看来,仅交换backgroundColor属性并设置/取消设置IsGrayPanel属性的选项必须完成这项任务……我非常热衷于实现JPanel之间的物理交换,但它看起来像是最初的Java类没有权利这么做。谢谢大家!