Displaying multiple images without creating new variables [closed]

。_饼干妹妹 提交于 2019-12-13 11:01:38

问题


I'm making a program in java to emulate a basic deck of cards; no specific game in mind, just a good old deck of cards that you can move around and flip over freely (of course, with the limit of 52 total cards). Here is my current code:

package cards;
import java.awt.Color;
import java.awt.Graphics;
import java.util.List;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class DeckOfCards extends JPanel{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    static final int SIZE = 500;
    public static String side = "back";
    static final int xSize = 73;
    static final int ySize = 98;
    static int x = SIZE - xSize;
    static int y = 0;
    static int i, j = 0;
    static int inDeck = 52;
    public boolean flipped = false;
    static final DeckOfCards m = new DeckOfCards();
    static final Color rgb = new Color(0, 180, 10);
    static final JFrame frame = new JFrame();
    static List<Integer> yList = new ArrayList<Integer>();
    static List<Integer> xList = new ArrayList<Integer>();
    Random random = new Random();
    int randX = random.nextInt(13) * xSize; 
    int randY = random.nextInt(4) * ySize;
    int xRand = randX;
    int yRand = randY;
    public static void main(String[] args){
        frame.setTitle("Virtual Cards");
        frame.add(m);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(SIZE, SIZE);
        frame.setResizable(false);
        m.setBackground(rgb);
        frame.setVisible(true);
    }
    public void mouseClick(){
        addMouseListener(new MouseAdapter(){
            @Override
            public void mouseClicked(MouseEvent e){
                if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize))) && (flipped == false)){
                    flipped = true;
                    side = "front";
                }else if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize))) && (flipped == true)){
                    flipped = false;
                    side = "back";
                }else if((e.getX() >= SIZE - xSize && e.getX() <= SIZE) && (e.getY() >= 0 && e.getY() <= SIZE - (SIZE - ySize)) && inDeck > 0){
                    randCardFace(random);
                    inDeck--;
                    side = "back";
                    x = SIZE - xSize;
                    y = 0;
                }
            }

        });
    }
    public void mouseMove(){
        addMouseMotionListener(new MouseMotionAdapter(){
            @Override
            public void mouseDragged(MouseEvent e){
                if(((e.getX() >= x && e.getX() <= (x + xSize)) && (e.getY() >= y && e.getY() <= (y + ySize)))){
                    x = e.getX() - (xSize / 2);
                    y = e.getY() - (ySize / 2); 
                }
            }
        });
    }
    public DeckOfCards(){
        mouseClick();
        mouseMove();
    }
    public void randCardFace(Random random){
            randX = random.nextInt(13) * xSize;
            randY = random.nextInt(4) * ySize;
    }
    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        paint(g);
    }
    public void paint(Graphics g){
        try{
            if(inDeck > 0){
                g.drawImage(ImageIO.read(getClass().getResource("images/deck.png")), SIZE - xSize, 0, null, null);
            }
            BufferedImage image = ImageIO.read(getClass().getResource("images/"+side+".png"));
            if(side != "back"){
                image = image.getSubimage(randX, randY, xSize, ySize);
            }
            g.drawImage(image, x, y, xSize, ySize, null, null);
        }catch(IOException e){
            e.printStackTrace();
        }
        m.repaint();
    }
}

However, this program will only let me have one card out at a time until I click on the deck in the top right corner and reshuffle(redefine the area of the image to be read with a random number generator). What I would like to do is be able to have any amount of cards from 0 and 52 out at any given time by clicking the deck without creating 51 new variables for the other cards(fyi I have written out some of the code for what I want, but so far it's done nothing but cause problems so I decided to start from scratch and ask the experts what I should do).

edit:

just realized after asking this, this is a slightly older code than I wanted to post, and has probably has plenty of other problems as well. Please ignore those, as they are already fixed.


回答1:


There are two basic approaches, the both kind of follow the same basic concept...

Generate a list of images and paint them...

You Could...

Create a custom component which is singularly responsible for painting a single card. The benefit of this is that it's generally easy to manage and uses what is already available.

The draw back is, you're going to need take charge the the layout management (a little).

You would start with a LayredPane, which will allow you to push cards up and down (virtually) as well as allow them to be placed where you want them.

Personally, I would create a single MouseListener/MouseMotionListener and register it to each of the "Card Panels", this will allow to easily control the cards with relation to the LayeredPane (moving them to the top when they are clicked for example)

You Could...

The other choice would be to load each of the card images and place them into List. Then basically, you would then simply paint them with in the paintComponent method by simply iterating through the list.

The problem is, you suddenly become responsible for the entire management of the z-order and checking what is clicked.

Customising the painting of the images (such as adding borders) becomes a little cumbersome, as you need to do this for each image and decide when. This would be easier if they were a custom component

Feedback

  • Beware of the over use of static variables, this can quickly lead you into problem areas with trying to do determine what is actually being referenced
  • Don't call paint from paintComponent. paint actually calls paintComponent itself, which could produce a stack overflow errors
  • Don't call any method from within a paintXxx method that might call repaint, because of the way painting works, this will simply cause the EDT to simply keep painting your component, which will eventually consume your CPU...

Take a closer look at Performing Custom Painting and Painting in AWT and Swing for more details




回答2:


You posted your code with lots of problems, so allow me to give you some advice over it. If it is not the correct code, then please correct it:

  • You should override a JPanel's paintComponent method not its paint method, not unless you need to change the behavior of how a component's children and borders paint themselves (you don't).
  • You should never read in images within paint or paintComponent as this will slow your rendering and thus program responsiveness to a crawl.
  • You should never call repaint() from within paint or paintComponent.
  • You are calling paint from within paintComponent and this risks a terrible recursion since paint calls paintComponent. Never do this.
  • Your code over uses static. This will prevent it from being extensible and will limit its modifiability.
  • You're building a GUI without first creating a decent model. Card programs have well described common models. These including the use enums for Java versions with an enum for Suit and an enum for Rank. Get the abstract concept and classes for Card, Deck, Player, Game down first before working on their image counterparts.

Links to some other answers and code of mine regarding card games:

  • Small program with Card images that can be dragged and dropped
  • Card model concepts
  • Working with a Deck of Cards


来源:https://stackoverflow.com/questions/20256625/displaying-multiple-images-without-creating-new-variables

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!