简体   繁体   中英

Painting JPanel/JComponent

Hello I have a problem with painting a picture on a panel and adding it on frame.

import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CardComponent extends JPanel {
int x;int y;
String[] str = {
           "D:\\Images\\ImageCards\\Clubs_Ace.png",
           "D:\\Images\\ImageCards\\Clubs_King.png",
           "D:\\Images\\ImageCards\\Clubs_Queen.png",
           "D:\\Images\\ImageCards\\Clubs_Jack.png",
           "D:\\Images\\ImageCards\\Clubs_10.png",
           "D:\\Images\\ImageCards\\Clubs_9.png",
           "D:\\Images\\ImageCards\\Clubs_8.png",
           "D:\\Images\\ImageCards\\Clubs_7.png",
           "D:\\Images\\ImageCards\\Clubs_6.png",
           "D:\\Images\\ImageCards\\Clubs_5.png",
           "D:\\Images\\ImageCards\\Clubs_4.png",
           "D:\\Images\\ImageCards\\Clubs_3.png",
           "D:\\Images\\ImageCards\\Clubs_2.png",
           "D:\\Images\\ImageCards\\Diamonds_Ace.png",
           "D:\\Images\\ImageCards\\Diamonds_King.png",
           "D:\\Images\\ImageCards\\Diamonds_Queen.png",
           "D:\\Images\\ImageCards\\Diamonds_Jack.png",
           "D:\\Images\\ImageCards\\Diamonds_10.png",
           "D:\\Images\\ImageCards\\Diamonds_9.png",
           "D:\\Images\\ImageCards\\Diamonds_8.png",
           "D:\\Images\\ImageCards\\Diamonds_7.png",
           "D:\\Images\\ImageCards\\Diamonds_6.png",
           "D:\\Images\\ImageCards\\Diamonds_5.png",
           "D:\\Images\\ImageCards\\Diamonds_4.png",
           "D:\\Images\\ImageCards\\Diamonds_3.png",
           "D:\\Images\\ImageCards\\Diamonds_2.png",
           "D:\\Images\\ImageCards\\Hearts_Ace.png",
           "D:\\Images\\ImageCards\\Hearts_King.png",
           "D:\\Images\\ImageCards\\Hearts_Queen.png",
           "D:\\Images\\ImageCards\\Hearts_Jack.png",
           "D:\\Images\\ImageCards\\Hearts_10.png",
           "D:\\Images\\ImageCards\\Hearts_9.png",
           "D:\\Images\\ImageCards\\Hearts_8.png",
           "D:\\Images\\ImageCards\\Hearts_7.png",
           "D:\\Images\\ImageCards\\Hearts_6.png",
           "D:\\Images\\ImageCards\\Hearts_5.png",
           "D:\\Images\\ImageCards\\Hearts_4.png",
           "D:\\Images\\ImageCards\\Hearts_3.png",
           "D:\\Images\\ImageCards\\Hearts_2.png",
           "D:\\Images\\ImageCards\\Spades_Ace.png",
           "D:\\Images\\ImageCards\\Spades_Ace.png",
           "D:\\Images\\ImageCards\\Spades_King.png",
           "D:\\Images\\ImageCards\\Spades_Queen.png",
           "D:\\Images\\ImageCards\\Spades_Jack.png",
           "D:\\Images\\ImageCards\\Spades_10.png",
           "D:\\Images\\ImageCards\\Spades_9.png",
           "D:\\Images\\ImageCards\\Spades_8.png",
           "D:\\Images\\ImageCards\\Spades_7.png",
           "D:\\Images\\ImageCards\\Spades_6.png",
           "D:\\Images\\ImageCards\\Spades_5.png",
           "D:\\Images\\ImageCards\\Spades_4.png",
           "D:\\Images\\ImageCards\\Spades_3.png",
           "D:\\Images\\ImageCards\\Spades_2.png"      
           };
   Image img;
     public CardComponent(int x,int y) {
         setOpaque(false);
         this.x = x;
         this.y = y;
         setSize(100,150);
         setVisible(true);


     }
     public void paint(Graphics g) {
         super.paint(g);
         Random r = new Random();
         String s = "";
         s = str[r.nextInt(str.length)];
         img = getToolkit().getImage(s);
         g.drawImage(img,this.x , this.y, 100, 150, this);
     }
     public static void main(String[] args) {
         CardComponent cc = new CardComponent(10,150);
         JFrame jfrm = new JFrame();
         jfrm.setSize(100, 150);
         jfrm.setVisible(true);
         jfrm.getContentPane().add(cc);
     }
 }

In class upper is the main problem (can't paint card).And I added this thing to the main frame(code lower).I added method main in every class just to check if it works right. import java.awt.Button; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;

  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.JSlider;
  import javax.swing.event.ChangeEvent;
  import javax.swing.event.ChangeListener;


  public class PanelButtons extends JPanel{
Button but1;
Button but2;
    Button but3;
JLabel jlab;
JSlider jsl;
public PanelButtons() {
     setLayout(null);  
     Color c = new Color(0,120,0);
     setSize(700,200);
     setLocation(0,0);
     setOpaque(false);
     but1 = new Button("Check");
     but1.setBackground(Color.CYAN);
     but1.setLocation(660, 350);
     but1.setBounds(683, 650, 70, 40);
     add(but1);
     but2 = new Button("Fold");
     but2.setBackground(Color.CYAN);
     but2.setLocation(660, 350);
     but2.setBounds(753, 650, 70, 40);
     add(but2);
     but3 = new Button("Bet");
     but3.setBackground(Color.CYAN);
     but3.setLocation(660, 350);
     but3.setBounds(823, 650, 70, 40);
     add(but3);
     int money = Player.PremierMoney();
     jsl = new JSlider(0,1000);
     jsl.setMajorTickSpacing(50);
     jsl.setMinorTickSpacing(10);
     jsl.setLabelTable(jsl.createStandardLabels(100));
     jsl.setPaintTicks(true);
     jsl.setPaintLabels(true);
     jsl.setSize(400, 150);
     jsl.setBackground(c);
     jlab = new JLabel("Ваша ставка"+jsl.getValue());
     jsl.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent ce) {
            if(jsl.getValueIsAdjusting()) return;
            jlab.setText("Ваша ставка:"+jsl.getValue());

        }

     });
     jlab.setHorizontalTextPosition(JLabel.CENTER);
     jlab.setVerticalAlignment(JLabel.BOTTOM);
     jsl.setLocation(900,600);
     jlab.setLocation(150,150);
     add(jsl);
     add(jlab);
     but2.addActionListener(new ActionListener() {


         @Override
        public void actionPerformed(ActionEvent e) {
             but1.setEnabled(false);
             but2.setEnabled(false);
             but3.setEnabled(false);

        }
     });
}

public static void main(String[] args) {
    JFrame jfrm = new JFrame("Some frame");
    jfrm.setSize(200, 200);
    PanelButtons pb = new PanelButtons();
    jfrm.setContentPane(pb);
    jfrm.setVisible(true);
    jfrm.setDefaultCloseOperation(jfrm.EXIT_ON_CLOSE);
}
   }

This class describes buttons and slider. import java.awt.Color; import javax.swing.JFrame;

    public class Images extends JFrame{
   Images() {
      // CardComponent cc = new CardComponent(530,550);
       PanelButtons pb = new PanelButtons();
       Color c = new Color(0,120,0);
    //  cc.setBounds(530, 550, 100, 150);
      setSize(1366,750); 
      setBackground(c);
      setContentPane(pb);
    //  setContentPane(cc);
      setVisible(true);
   }    




   public static void main(String[] args) {
       Images im = new Images();
       im.setResizable(false);
       im.setDefaultCloseOperation(EXIT_ON_CLOSE);
   }
    }

And this is the main frame that I add panels to. So main problem is where I paint the card. Thanks for help.

There a number of problems with you entire program, the choice of null layouts is a significant one, this is going to cause you a lot of problems.

But, the significant problem you're facing is in your paint method

public void paint(Graphics g) {
    super.paint(g);
    Random r = new Random();
    String s = "";
    s = str[r.nextInt(str.length)];
    System.out.println(s);
    img = getToolkit().getImage(s);
    g.drawImage(img, this.x, this.y, 100, 150, this);
}

There are three problems with this method.

  1. You should be overriding paintComponent , its a safer method for performing custom painting.
  2. You're regenerate the image random on each paint cycle. You have to remember that the your component may be painted for any number of reasons and most outside of your control. This means that every time the component is painted, a new image is loaded. You should be assigning a single image to the component when it is constructed and paint that image.
  3. The Graphics context passed to your component has been translated so that the point 0x0 will be at the top left corner of the component. This means, all painting is relative.

Your code does this...

g.drawImage(img, this.x, this.y, 100, 150, this);

This means, that the image will be painted at x/y pixels relative to the top/left position of the component. Instead, you should be painting around the 0x0 position.

In your example, you also do

jfrm.setVisible(true);
jfrm.getContentPane().add(cc);

This is generally a bad idea, you should switch these two statements, otherwise it will look like nothing has been painted.

You may find it worth while to take a read through

Update with a simple example

This example is intended to demonstrate the quantity of hits that a paint method can take as well as the concept of local coordinate space.

在此处输入图片说明

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.io.File;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Cards {

    public static void main(String[] args) {
        new Cards();
    }

    public Cards() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame jfrm = new JFrame();
                jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                jfrm.setSize(100, 150);
                jfrm.setVisible(true);
                jfrm.add(new TestPane());
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            CardComponent cc = new CardComponent();
            setLayout(new GridBagLayout());
            add(cc);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            FontMetrics fm = g.getFontMetrics();
            // Simply render the location of the component relative to it's parent.
            for (Component comp : getComponents()) {
                String text = comp.getX() + "x" + comp.getY();
                g.drawString(text, comp.getX(), comp.getY() - fm.getHeight() + fm.getAscent());
            }
        }

    }

    public class CardComponent extends JPanel {

        String[] str;
        Image img;
        private int paintCount;

        public CardComponent() {
            File[] files = new File("C:\\Users\\swhitehead\\Documents\\My Dropbox\\MegaTokyo").listFiles();
            str = new String[files.length];
            for (int index = 0; index < files.length; index++) {
                str[index] = files[index].getPath();
            }
            setOpaque(false);
            setVisible(true);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 150);
        }

        @Override
        public Dimension getMinimumSize() {
            return getPreferredSize();
        }

        public void paint(Graphics g) {
            paintCount++;
            System.out.println(paintCount);
            super.paint(g);
            Random r = new Random();
            String s = "";
            s = str[r.nextInt(str.length)];
            img = getToolkit().getImage(s);
            // Drawing image in the top left corner of the component
            g.drawImage(img, 0, 0, 100, 150, this);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth(), getHeight());
            FontMetrics fm = g.getFontMetrics();
            String text = "Local 0x0";
            g.drawString(text, 0, fm.getAscent());
        }
    }
}

With this example, I was able to get the paintCount to 3640 BEFORE I even touched the frame.

Doing image loading in any paint method is also a bad idea. It's expected that paint methods should return as quickly as possible, failing to do so will reduce the performance of your program.

I'm a little confused by your code, I don't see a CardComponent object, you have to instantiate an object of your CardComponent class then add it to your JFrame or a component in the JFrame like this...

Images im = new Images();
PanelButtons pb = new PanelButtons();
CardComponent cc = new CardComponent(x, y);
im.setContentPane(pb);
pb.setLayout(new BorderLayout());
pb.add(cc, BorderLayout.CENTER);

That's not a working program but hopefully you get the idea. And I did just skim the code so its possible I missed where you instantiate the CardComponent object so if you're still having problems try loading the image this way...

public void paint(Graphics g) {
     super.paint(g);
     Random r = new Random();
     String s = "";
     s = str[r.nextInt(str.length)];
     img = ImageIcon(s).getImage();
     g.drawImage(img,this.x , this.y, 100, 150, this);
 }

I just ran your code and I have one more suggestion. In the CardComponent set the bounds in the constructor using the setBounds(x, y, 100, 150) method and then draw the image from the top left corner (0, 0) to the bottom right (100, 150) or (getWidth(), getHeight()).

Hopefully that helps, good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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