绘画JPanel / JComponent

时间:2013-04-06 09:14:22

标签: java image swing jpanel paintcomponent

您好我在面板上绘制图片并将其添加到框架上时遇到问题。

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);
     }
 }

在课堂上面是主要问题(不能画卡)。我把这个东西添加到主框架(代码更低)。我在每个类中添加了方法main来检查它是否正常工作。             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);
}
   }

此类描述按钮和滑块。         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);
   }
    }

这是我添加面板的主要框架。 所以主要的问题是我在哪里画卡。 谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

整个程序存在许多问题,null布局的选择很重要,这会给你带来很多问题。

但是,您面临的重大问题在于paint方法

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);
}

此方法存在三个问题。

  1. 你应该重写paintComponent,这是一种更安全的自定义绘画方法。
  2. 您可以在每个绘制周期中随机重新生成图像。您必须记住,您的组件可能由于多种原因而被绘制,并且大多数都是您无法控制的。这意味着每次绘制组件时,都会加载新图像。您应该在构建组件时为组件分配单个图像并绘制该图像。
  3. 传递给组件的Graphics上下文已被翻译,因此点0x0将位于组件的左上角。这意味着,所有绘画都是相对的。
  4. 您的代码执行此操作...

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

    这意味着,图像将相对于组件的顶部/左侧位置以x / y像素绘制。相反,你应该在0x0位置绘画。

    在您的示例中,您也可以

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

    这通常是一个坏主意,你应该切换这两个语句,否则它看起来就像什么都没画了。

    您可能会觉得值得一读

    使用简单示例进行更新

    此示例旨在演示paint方法可以采用的命中数量以及局部坐标空间的概念。

    enter image description here

    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());
            }
        }
    }
    

    通过这个例子,我甚至可以在触摸框架之前得到paintCount到3640.

    在任何paint方法中进行图像加载也是一个坏主意。它预计paint方法应该尽快返回,否则会降低程序的性能。

答案 1 :(得分:0)

我对您的代码感到有点困惑,我没有看到CardComponent对象,您必须实例化CardComponent类的对象,然后将其添加到JFrame或像JFrame这样的组件......

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);

这不是一个有效的计划,但希望你能得到这个想法。我只是略过了代码,所以我可能错过了你实例化CardComponent对象的地方,所以如果你还有问题,试试这样加载图像......

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);
 }

我刚刚运行了你的代码,我还有一个建议。在CardComponent中使用setBounds(x, y, 100, 150)方法设置构造函数中的边界,然后从左上角(0,0)到右下角(100,150)或(getWidth())绘制图像,getHeight())。

希望这有帮助,祝你好运。