java - repaint() 时 JTextArea 不显示,但 revalidate() 时 Graphics 不更新?

标签 java multithreading swing jtextarea repaint

我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 DraftLottery 类中作为线程运行。但是,当我的绘制方法调用 repaint() 时,JTextArea 不显示。我尝试将 repaint() 切换为 revalidate(),但球没有移动。然后我尝试调用 repaint() 和 revalidate(),但它的行为与 repaint() 相同。 这是我的 DraftLottery 类的代码:

package ca.WiltzSports.DraftLottery;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import ca.WiltzSports.DraftLottery.DraftBall.Ball;

public class DraftLottery extends JFrame {
public static final long serialVersionUID = 89L;

int teams;
String[] teamNames;
int[] balls;
JTextArea display;
JPanel screen;
JPanel animation;
List<String> entries;
public static List<Ball> ball;
String [] draftOrder;
Random rand;
int counter = 1;
javax.swing.Timer t;
public static int width = 1024;
public static int height = 768;
Graphics dbg;
Image dbImage;
int i = 0;

public DraftLottery(int teams, String[] teamNames, int[] balls){
    t = new javax.swing.Timer(2000, new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent arg0) {
            draft();
        }   

    });
    ball = new ArrayList<Ball>();
    rand = new Random();
    this.teams = teams;
    this.teamNames = teamNames;
    this.balls = balls;
    this.screen = new JPanel();
    this.animation = new JPanel();
    display = new JTextArea(20,50);
    display.setBackground(Color.BLACK);
    display.setForeground(Color.YELLOW);
    draftOrder = new String[teams];
    this.entries = new ArrayList<String>();
    addTeamBalls();
    setSize(width,height);
    setVisible(true);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setTitle("Draft Lottery");
    setLayout(new BorderLayout());
    screen.add(display);
    add("East", new JScrollPane(display));
    add("West", animation);
    t.start();
}

@Override
public void paint(Graphics g){
    dbImage = createImage(getWidth(), getHeight());
    dbg = dbImage.getGraphics();
    Graphics2D g2d = (Graphics2D) dbg;
    draw(g2d);
    g.drawImage(dbImage, 0, 0, this);
    Ball.runBalls(ball);
}

public void draw(Graphics2D g2d){
    for (Ball b: ball){
        b.draw(g2d);
    }
    revalidate();
    repaint();
}

public void addTeamBalls(){
    for (int c = 0; c < teamNames.length; c++){
        for (int j = 0; j < balls[c]; j++){
            entries.add(teamNames[c]);
            ball.add(new Ball(rand.nextInt(width/2 - Ball.SIZE), rand.nextInt(height - Ball.SIZE), teamNames[c], i++));
        }
    }
}

public void draft(){
    int q = 0;
    String [] e = entries.toArray(new String[entries.size()]);
    String draftedTeam;
    int index = rand.nextInt(entries.size());
    draftedTeam = e[index];
    if(!draftedTeam.equals("X")){
        display.append("" + counter++ + ". " + draftedTeam + "\n");
        for(int c = 0; c < e.length; c++){
            if (e[c].equals(draftedTeam)){
                e[c] = "X";
            }
        }
        removeBalls();
    }else {
        boolean again = false;
        for (int c = 0; c < e.length; c++){
            if (!e[c].equals("X")){
                again = true;
            }
        }
        if(again){
        }else{
            t.stop();
            display.append("DRAFT LOTTERY COMPLETE");
        }
    }
    entries = Arrays.asList(e);
}

public void removeBalls(){
    Ball [] bs;
    int q = 0;
    for (Ball b: ball){
        if (b.getTeamName().equals("X")){
            continue;
        }else{
            q++;
        }
    }
    bs = new Ball[q];
    q = 0;
    for (Ball b: ball){
        if (!b.getTeamName().equals("X")){
            bs[q++] = b;
        }
    }
    ball = Arrays.asList(bs);
}

}

任何帮助将不胜感激。 非常感谢!

最佳答案

您有很多问题:

  1. 您已重写顶级容器的 paint 方法。通常不建议这样做,因为它不是双缓冲的,并且可能会因动画和其他绘画更新而产生闪烁。

  2. 您未能调用super.paintpaint 方法负责将所有子绘制方法整合在一起,包括 paintComponents;但由于您不允许 paint 完成其工作,因此它不会为您渲染这些组件。

相反,

  1. 创建一个自定义组件,从 JPanel 等扩展而来。

  2. 将动画所需的所有逻辑添加到此组件。

  3. 重写它的paintComponent方法并向其中添加所有动画和自定义绘画。

  4. 将其添加到框架中。

看看Performing Custom PaintingPainting in AWT and Swing了解更多详情。

关于java - repaint() 时 JTextArea 不显示,但 revalidate() 时 Graphics 不更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16576361/

相关文章:

java - JButton 子类在单击/透明错误之前不显示按钮

java - 如何在MAVEN项目中访问磁盘上的资源?

c# - 线程创建范围和垃圾收集器

java - 在普通 FileChannel 上使用 MappedByteBuffer 按顺序写入长文件是否有性能优势?

windows - 当线程在 SwapBuffers() 中被阻塞时 GetMessage()

java - 测量无等待多线程 Java 程序中的争用

java - 如何在编辑时选择 JTable 单元格中的所有文本但在键入时不选择?

java - 使用 GridLayout 垂直对齐 jpanels 的组件

java - 包含 jspf 时出错

java - Java 中的可嵌入分布式版本控制系统?