简体   繁体   English

Java Swing-空布局-如何为组件设置Z索引?

[英]Java Swing - Null Layout - How to set Z index for components?

I am trying to create a freecell game, I have not implemented the logic yet as I am having trouble with the layout. 我正在尝试创建一个freecell游戏,但由于布局方面的问题,我尚未实现逻辑。

The main issue that I have not been able to solve is that the JFrame orders cards Z index values in the order that they are painted, such that the first card painted has the highest Z-index. 我无法解决的主要问题是,JFrame按绘制卡片的顺序对卡片Z索引值进行排序,以使绘制的第一张卡片具有最高的Z索引。

I am trying to make the z index changeable. 我正在尝试使z索引可变。

I am using a null layout - the professors instructions said to not utilize any managers or external layout help. 我使用的是空布局-教授的指示说不要利用任何经理或外部布局帮助。 (ugh) (啊)

Attempted solutions: 尝试的解决方案:

I tried using JLayeredPane by instantiating a pane, setting its bounds to fit exactly in the JFrame, adding all my cards to the Layered pane, and then adding the pane to the JFrame - but that did not work. 我尝试通过实例化窗格,将其边界设置为恰好适合JFrame,将我的所有卡添加到“分层”窗格中,然后将窗格添加到JFrame中来使用JLayeredPane,但这没有用。

I tried using the "setComponentZOrder(comp, index)" but that did not change the axis either. 我尝试使用“ setComponentZOrder(comp,index)”,但这也没有改变轴。

Below is my code. 下面是我的代码。 Is there no way to do this on null layouts? 没有办法在null布局上执行此操作吗?

This oneDrive link contains the card images if you are attempting to run the program. 如果您尝试运行该程序,则该oneDrive链接包含卡映像。

Images Download 图片下载

Main: 主要:

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.util.*;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class FreeCellGame extends JFrame implements MouseListener, MouseMotionListener
{
    public ArrayList<String> randomizedKeys = new ArrayList<String>();
    public HashMap<String, CardImagePanel> allCards;

    public static void main(String[] args)
    {
        FreeCellGame projectBoard = new FreeCellGame();
        projectBoard.allCards = new HashMap<String, CardImagePanel>();
        projectBoard.setSize(1218,800);
        projectBoard.setLayout(null);
        projectBoard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        projectBoard.allCards = projectBoard.loadCardObjects(projectBoard.allCards);
        projectBoard = projectBoard.placeCardsOnBoard(projectBoard);
        projectBoard = addshapes(projectBoard);
        projectBoard.repaint();
        projectBoard.revalidate();
        projectBoard.setVisible(true);

    }

    private static FreeCellGame addshapes(FreeCellGame projectBoard) {

        int xPos = 0;
        int yPos = 50;

        JLabel foundations = new JLabel("Foundations");
        foundations.setBounds(790, 50, 300, 50);
        foundations.setFont(new Font("Courier New", Font.BOLD, 30));
        projectBoard.add(foundations);
        JLabel freeCells = new JLabel("Free Cells");
        freeCells.setBounds(210, 200, 300, 50);
        freeCells.setFont(new Font("Courier New", Font.BOLD, 30));
        projectBoard.add(freeCells);

        for(int i = 0;  i < 8; i++)
        {
            JPanel rect = new JPanel();
            rect.setBorder(BorderFactory.createLineBorder(Color.black));
            rect.setBounds(xPos, yPos, 150, 150);
            projectBoard.add(rect);
            xPos+=150;
            if(i == 3)
            {
                yPos = 100;
            }
        }
        return projectBoard;
    }

    private HashMap<String, CardImagePanel> loadCardObjects(HashMap<String, CardImagePanel> allCards)
    {
      File folder = new File("C:/Users/chris/Documents/GitHub/EclipseProjects/C585-FreeCell/src/images");
      File[] listOfFiles = folder.listFiles();
      allCards = new HashMap<String, CardImagePanel>();

      for (File file : listOfFiles) {
        if (file.isFile()) {
          String hashKey = file.getName();
          randomizedKeys.add(hashKey);
          CardImagePanel currentImage = new CardImagePanel(file);
          currentImage.setPreferredSize(new Dimension(157, 157));//5px on both sides as margin
          allCards.put(hashKey, currentImage);
          allCards.get(hashKey).addMouseListener(allCards.get(hashKey));
          allCards.get(hashKey).addMouseMotionListener(allCards.get(hashKey));
        }
      }
      Collections.shuffle(randomizedKeys);
      return allCards;
    }

    private FreeCellGame placeCardsOnBoard(FreeCellGame projectBoard)
    {
        int x = 0;
        int y = 540;
        int count = 0;
        for(String newRandomKey : randomizedKeys)
        {
            System.out.println(newRandomKey);
            if(count == 7 || count == 14 || count == 21)
            {
                x+=150;
                y=540;
            }
            else if( count == 28 || count == 34 || count == 40 || count == 46)
            {
                x+=150;
                y=500;
            }
            else if (count != 0)
            {
                y-=40;
            }
            allCards.get(newRandomKey).setBounds(x, y, 150, 150);
            projectBoard.add(allCards.get(newRandomKey));
            count++;
        }
        return projectBoard;
    }
    @Override
    public void mouseDragged(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseClicked(MouseEvent e) {
//      ((CardImagePanel) e.getSource()).setComponentZOrder(projectBoard, 5000);
    }
    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mousePressed(MouseEvent arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseReleased(MouseEvent arg0) {
        // TODO Auto-generated method stub
    }
 }

JPanel Class: JPanel类别:

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class CardImagePanel extends JPanel implements MouseListener, MouseMotionListener
{
    private BufferedImage picture;  
    private char cardType;
    private int cardNum;

    public CardImagePanel(File newImageFile)
    {
        try {
            picture = ImageIO.read(newImageFile);

        } catch (IOException e){
            e.printStackTrace();
        }
        cardType = newImageFile.getName().charAt(0);
        String tempString = newImageFile.getName();
        cardNum = Integer.parseInt(tempString.substring(1,tempString.lastIndexOf('.')));
    }

    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(picture, 0, 0, 150, 150, this);
    }

    public BufferedImage getPicture() {
        return picture;
    }
    public char getCardType() {
        return cardType;
    }
    public int getCardNum() {
        return cardNum;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        this.setBounds(e.getX() + this.getX()-75, e.getY() + this.getY()-75, 150, 150);
    }
    @Override
    public void mouseMoved(MouseEvent arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseClicked(MouseEvent e) {
    }
    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
    }
}

I am using a null layout - the professors instructions said to not utilize any managers or external layout help. 我使用的是空布局-教授的指示说不要利用任何经理或外部布局帮助。 (ugh) (啊)

So then basically you need to write your own layout manager. 因此,基本上,您需要编写自己的布局管理器。

Below is my code. 下面是我的代码。 Is there no way to do this on null layouts? 没有办法在null布局上执行此操作吗?

A null layout will have no effect on how Z-Ordering working. 空布局不会影响Z-Ordering的工作方式。 The Z-Ordering will be done for you automatically. Z-Ordering将自动为您完成。 The key is the order in which you add components to the panel so that you get the Z-Ordering you desire. 关键是将组件添加到面板的顺序,以便获得所需的Z顺序。

I am trying to make the z index changeable. 我正在尝试使z索引可变。

Adding components to a panel will affect the Z-Order. 将组件添加到面板将影响Z顺序。

Check out Overlap Layout which is a layout manager specifically designed for this. 查看Overlap Layout ,这是专门为此设计的布局管理器。 I know you can't use the layout manager, but better understanding how Z-Order works will allow you to write your code simply. 我知道您不能使用布局管理器,但是更好地了解Z-Order的工作原理将使您可以轻松地编写代码。

For example check out the simple code below. 例如,查看下面的简单代码。 By simply playing with which add(...) method you use to add the cards to the panel you can control the Z-Order to your advantage: 通过简单地玩您使用哪种add(...)方法将卡片添加到面板中,就可以控制Z顺序以发挥自己的优势:

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

public class SSCCE extends JPanel
{
    ArrayList<JLabel> cards = new ArrayList<JLabel>();

    public SSCCE()
    {
        setLayout( null );

        cards.add( createCard("1", Color.RED) );
        cards.add( createCard("2", Color.GREEN) );
        cards.add( createCard("3", Color.BLUE) );
        cards.add( createCard("4", Color.YELLOW) );

        //  This would be your first natural attempt (but it doesn't work)

        for (int i = 0; i < cards.size(); i++)
            add( cards.get(i) );

        //  This affects the Z-Order to do what you want

//      for (int i = 0; i < cards.size(); i++)
//          add(cards.get(i), 0);
    }

    public JLabel createCard(String text, Color background)
    {
        JLabel label = new JLabel(text);
        label.setOpaque( true );
        label.setBackground( background );
        label.setSize(30, 70);
        label.setLocation((cards.size() + 1) * 20 , 20);

        return label;
    }



    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.setSize(200, 200);
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

I don't often support null layouts, I think there is such a small set of use-cases where the are really useful, however, you think this is one of those situations, then I would highly recommend the use of a JLayeredPane , as it will allow you to control the z-ordering of the components. 我不经常支持null布局,我认为其中有一些用例确实有用,但是,您认为这是其中一种情况,因此我强烈建议使用JLayeredPane ,因为它将允许您控制组件的z顺序。

Have a look at How to Use Layered Panes for more details 看看如何使用分层窗格了解更多详细信息

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

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