【问题标题】:How to call my paintComponent() method in another class如何在另一个类中调用我的paintComponent() 方法
【发布时间】:2019-07-22 09:24:56
【问题描述】:

我正在编写一个 Blackjack 程序,该程序有时会调用 paintComponent() 方法从文件中绘制图像。图片应该出现在 JPanel 中,但是如果我尝试在 JPanel-> style2b1.paintComponent(getGraphics()) 上调用该方法;

它不起作用 (NullPointerException),但这本身并不让我感到惊讶。我尝试过并且没有给我任何错误的唯一方法就是简单地写:paintComponent(getGraphics());

但是图片也没有显示出来。

就像我之前说的,我尝试了一堆不同的调用,用不同的东西作为参数,但都没有给出积极的结果。

我的班级窗口

package com;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

public class Windows extends JFrame{


JFrame test = new JFrame();
JLabel text = new JLabel("Welcome to Blackjack 21");
JLabel textAction = new JLabel("");
JLabel textBank = new JLabel("BANK");
JLabel textPlayer = new JLabel("PLAYER");
JPanel style = new JPanel();
JPanel style2 = new JPanel(new BorderLayout());
JPanel style2a = new JPanel(new BorderLayout());
JPanel style2a1 = new JPanel();
JPanel style2a2 = new JPanel();
JPanel style2b = new JPanel(new BorderLayout());
JPanel style2b1 = new JPanel();
JPanel style2b2 = new JPanel();
JPanel style3 = new JPanel();
JButton b1 = new JButton("Stand");
JButton b2 = new JButton("Hit");
JButton b3 = new JButton("Double");
JButton b4 = new JButton("Split");
JButton b5 = new JButton("Insurance");
Font font = new Font("Helvetica", 10, 20);


public Windows(){
   style.setBackground(Color.BLACK);
   style2.setBackground(Color.DARK_GRAY);
   style2a.setBackground(Color.magenta);
   style2a1.setBackground(Color.BLACK);
   style2a2.setBackground(Color.DARK_GRAY);
   style2b.setBackground(Color.magenta);
   style2b1.setBackground(Color.DARK_GRAY);
   style2b2.setBackground(Color.BLACK);
   style3.setBackground(Color.BLACK);
   style3.add(b1);
   style3.add(b2);
   style3.add(b3);
   style3.add(b4);
   style3.add(b5);
   text.setForeground(Color.WHITE);
   text.setFont(font);
   style.add(text);
   textAction.setForeground(Color.WHITE);
   textAction.setFont(font);
   style2.add(textAction);
   textBank.setFont(font);
   textBank.setForeground(Color.RED);
   style2a1.add(textBank);
   textPlayer.setForeground(Color.GREEN);
   textPlayer.setFont(font);
   style2b2.add(textPlayer);
   style2b1.setSize(this.getWidth(), 300);
   DrawPicture otaku = new DrawPicture();

   b1.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           textAction.setText("You choose to stand. You won't receive any more cards.");
       }
   });
   b2.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           textAction.setText("You choose to hit. You will receive another card");
//This is where I want to call my method
           paintComponents(getGraphics());
       }
   });
   b3.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           textAction.setText("You choose to double. You will receive one last card and you have to double your bet");
       }
   });
   b4.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           textAction.setText("You choose to split. Each deck of card will be considered as individual, however you have to double your bet ");
       }
   });
   b5.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           textAction.setText("You choose to raise an insurance. Please double your bet.");
       }
   });


   test.add(style, BorderLayout.PAGE_START);
   test.add(style2, BorderLayout.CENTER);
   style2.add(style2a, BorderLayout.NORTH);
   style2a.add(style2a1, BorderLayout.NORTH);
   style2a.add(style2a2, BorderLayout.SOUTH);
   style2.add(style2b, BorderLayout.SOUTH);
   style2b.add(style2b1, BorderLayout.NORTH);
   style2b.add(style2b2, BorderLayout.SOUTH);
   test.add(style3, BorderLayout.PAGE_END);

   test.setSize(1000, 1000);
   test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   test.setVisible(true);
   test.setLocation(500, 0);
   test.setResizable(false);
}

}

我的班级画图

 package com;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;


public class DrawPicture extends JPanel {

File a = new File("C:\\Users\\km\\Pictures\\Cards\\red_back.png");

public void paintComponents(Graphics g){
    try {
        Image testItOut = ImageIO.read(a);
        g.drawImage(testItOut, 50, 300, this);
    }catch(IOException e){
        e.printStackTrace();
    }
}
}

我的目标是能够在 JPanel style2a2 和 JPanel style2b1 中显示许多图片(然后调整它们的大小)。我不知道我是否可以通过 JPanel 放置多个元素,但我还没有想到那么远。

【问题讨论】:

  • 我不是天生会说英语的人,所以请随时检查我的语法并更改句子,以便有相同问题的人可以轻松理解。非常感谢
  • 你的style2b1是一个来自JPanel类的对象,它没有你的costum方法。要解决这个问题,您只需将类更改为您的DrawPicture,然后您将拥有您的方法和所有JPanel 本机实现(因为您扩展了它)。
  • 不幸的是,这样做会在 g.drawImage(pathToPicture, 50, 300, this); 行返回一个 nullPointerExeption;观察者有什么问题吗? @JPeter
  • 好吧,至少该方法被调用...现在到下一个问题...我认为您不需要转义“\”所以文件的路径应该是File("C:\Users\km\Pictures\Cards\red_back.png"); .解决此类问题的最简单方法是使用断点(使用调试)。只需在该行中获取一个并检查所有变量
  • 我不能把“\”去掉。如果我这样做,程序会将其视为文本的一部分,而不是文件之间的分隔,我会收到语法错误。所以我必须就这样离开它。感谢您对drawPicture解释的帮助!

标签: java swing paintcomponent drawimage


【解决方案1】:

paintComponent(最好用@Override 定义以检测错别字)在(重新)绘制 GUI 期间自动调用。所以他们是事件驱动的,做出反应。它不打算直接称为。而是在 DrawPicture 变量或整个 JFrame (Windows) 上使用 JComponent 的 repaint* 方法之一。

public class DrawPicture extends JPanel {

    private Image testItOut;

    // Access for setting an other image.
    public void setImage(Image testItOut) {
        this.testItOut = testItOut;
    }

    public Image getImage() {
         return testItOut;
    }

    public DrawPicture() {
        try {
            File a = new File("C:\\Users\\km\\Pictures\\Cards\\red_back.png");
            testItOut = ImageIO.read(a);
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        if (testItOut != null) {
            g.drawImage(testItOut, 50, 300, this);
        }
    }
}

例如:

b5.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
         otaku.repaint(50L); // Repaint after 50 ms.
     }
});

这可以用 lambdas 缩短为:

b5.addActionListener(e -> {
   otaku.repaint(50L); // Repaint after 50 ms.
});

甚至

b5.addActionListener(e -> otaku.repaint(50L));

更现实一点:

b5.addActionListener(e ->
   SwingUtilities.invokeLater(() -> {
       File imgFile = new File("C:\\Users\\km\\Pictures\\Cards\\green_back.png");
       Image img = ImageIO.read(imgFile);
       otaku.setImage(img);
       otaku.repaint(50L);
}));

invokeLater 使 GUI 在actionPerformed 的代码需要更长的时间时响应更快(在按钮按下期间它不会阻塞)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    相关资源
    最近更新 更多