gpt4 book ai didi

java - 如何在 Java 中的 for 循环中的每个 update() 之后强制执行 repaint()?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:13:12 25 4
gpt4 key购买 nike

我写了一个小的、基本的、万花筒类型的程序,它应该在六个不同的点和不同的方向逐渐绘制相同的图案(随着时间的推移)。

为此,我创建了一个数组来存储每个像素的颜色(初始颜色为黑色,用数字 0 表示),然后数组中的 6 个起始点的颜色变为绿色(用数字 1 表示)。这些点应出现在屏幕上,然后根据前 6 个点的位置再创建 6 个点。然后应显示更新的屏幕。重复,重复,重复...

我的问题是所有针对新像素的更新都是在绘制屏幕之前执行的。我检查了其他一些帖子和网络教程等,并收集到 AWT 足以避免浪费时间重新绘制微小的更改。似乎还有一个叫做 paintManager 的东西参与其中。我相信问题是我在 for 循环中重新绘制。我发现这真的很令人沮丧,因为在我看来,这应该是一件简单的事情。确实有一种简单的方法可以说服 java 以我想要的方式绘制这些微小的变化吗?

我在下面包含了完整的代码:

package paranoid;

import javax.swing.JFrame;

public class MasterFrame {

public static void main(String[] args) {
// TODO Auto-generated method stub
new MasterFrame();
}


public MasterFrame(){
JFrame f = new JFrame();
f.setTitle("Kaleidoscope");
f.add(new Trip2());
f.setSize(500,300);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

和...

package paranoid;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;


public class Trip2 extends JPanel {

private static final long serialVersionUID = 1L;

private int xmin = 0,
xmax = 499,
ymin = 0,
ymax = 279;
private int x = 120;
private int y = 80;
private int dx = 1;
private int dy = 1;
private int temp = 0;
private int update_counter = 0;
private int repaint_counter = 0;
private int x_pos[] = new int[6];
private int y_pos[] = new int[6];
private int screen[][] = new int[500][280];


public Trip2() {

initialisation();
for(int i = 0; i < 5000; i++)
{
update();
System.out.println("Just returned from update()");

repaint(); //This repaint is not being activated until all updates
System.out.println("Just returned from paint()"); //have been completed, but I want a repaint after EVERY update.
}
}

public void initialisation(){
System.out.println("initialising...");
x_pos[0] = x;
y_pos[0] = y;

x_pos[1] = xmax - x;
y_pos[1] = y;

x_pos[2] = x;
y_pos[2] = ymax - y;

x_pos[3] = xmax - x;
y_pos[3] = ymax - y;

x_pos[4] = (int)(xmax/2)-50;
y_pos[4] = (int)(ymax/2);

x_pos[5] = (int)(xmax/2)+50;
y_pos[5] = (int)(ymax/2);

for(int j = 0; j<280; j++){
for(int i = 0; i<500; i++){
screen[i][j] = 0;
}
}
} //end of initialisation()

public void update(){
System.out.println("updating... for the "+update_counter+"th time");

temp = (int)Math.floor(Math.random()*100);
if(temp < 40){ // 40% chance that the direction is changed
dx = (int)Math.floor(Math.random()*3);
dy = (int)Math.floor(Math.random()*3);
dx = dx - 1;
dy = dy - 1;
}


x_pos[0] = x_pos[0]+dx;
y_pos[0] = y_pos[0]+dy;

x_pos[1] = x_pos[1]-dx;
y_pos[1] = y_pos[1]+dy;

x_pos[2] = x_pos[2]+dx;
y_pos[2] = y_pos[2]-dy;

x_pos[3] = x_pos[3]-dx;
y_pos[3] = y_pos[3]-dy;

x_pos[4] = x_pos[4]-dy;
y_pos[4] = y_pos[4]-dx;

x_pos[5] = x_pos[5]+dy;
y_pos[5] = y_pos[5]+dx;

for(int k = 0; k < 6; k++){
if(x_pos[k] < 0){
x_pos[k] = 0;
}
if(x_pos[k] > 499){
x_pos[k] = 499;
}
}

for(int k = 0; k < 6; k++){
if(y_pos[k] < 0){
y_pos[k] = 0;
}
if(y_pos[k] > 279){
y_pos[k] = 279;
}
}


screen[x_pos[0]][y_pos[0]] = 1;
screen[x_pos[1]][y_pos[1]] = 1;
screen[x_pos[2]][y_pos[2]] = 1;
screen[x_pos[3]][y_pos[3]] = 1;
screen[x_pos[4]][y_pos[4]] = 1;
screen[x_pos[5]][y_pos[5]] = 1;

update_counter = update_counter + 1;

} //end of update()

public void paint(Graphics g){
System.out.println("painting screen for the "+repaint_counter+"th time");

g.setColor(Color.BLACK);
g.fillRect(xmin, ymin, xmax, ymax);

for(int j = 0; j<280; j++){
for(int i = 0; i<500; i++){
if(screen[i][j] == 0){
g.setColor(Color.BLACK);
} else
{
g.setColor(Color.GREEN);
}
g.drawLine(i,j,i,j); //plots pixel
}
}


try{
Thread.sleep(100);
}
catch(InterruptedException e){
}

repaint_counter = repaint_counter + 1;


}//end of paint(Graphics g)

}//end of Trip2 class

最佳答案

这里的一个主要问题是您在 paint 方法中调用了 Thread.sleep() - 这不是一个好主意,因为这会停止在那段时间进一步重新绘制您的应用程序。 (事件调度线程/绘画线程不得用于任何缓慢的操作)

你想要在这里实现的通常流程如下(可能比你需要的更详细):

  1. 创建一个包含所有数字变量的模型类,特别是您的数字(无 UI 代码),同时创建各种 getter 以允许 UI 稍后访问这些数字。
  2. 允许将此模型类传递给 View 类(在您的情况下为 Trip1)并设置为实例变量。
  3. 从主控制类创建一个新的线程或定时器,根据需要定期调整您的型号/内部结构。
  4. 为模型的更改创建一个监听器接口(interface)。 (例如 ModelChangedListener 等)
  5. 将监听器列表添加到您的模型中 - 使用注册方法只需将监听器添加到列表中即可。
  6. 使您的模型发生任何变化,即当数字更新时,这些会触发对已注册监听器的调用。
  7. 在您的主控制类中,为该模型注册一个监听器,它只调用:trip2Panel.repaint();

  8. 在面板的 paint() 方法中...只需按当前状态绘制模型即可。

已发布完整代码:

package paranoid;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;

public class MasterFrame {

public static void main(String[] args) {
// TODO Auto-generated method stub
new MasterFrame();
}


public MasterFrame(){
JFrame f = new JFrame();
f.setTitle("Kaleidoscope");
final Trip2 trip2UI = new Trip2();
final TripModel model = new TripModel();
model.update();
Timer timer = new Timer(1, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
model.update();
}
});
timer.setRepeats(true);
timer.start();

model.addListener(new TripModelListener() {
@Override
public void modelChanged() {
trip2UI.repaint();
}
});
trip2UI.setModel(model);

f.add(trip2UI);
f.setSize(500,300);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setResizable(false);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}
}

旅行模型监听器

package paranoid;

public interface TripModelListener {
void modelChanged();
}

Trip2(用户界面)

package paranoid;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;


public class Trip2 extends JPanel {

private static final long serialVersionUID = 1L;

private TripModel model;

public void paint(Graphics g){

g.setColor(Color.BLACK);
g.fillRect(model.getXMin(), model.getYMin(), model.getXMax(), model.getYMax());

for (int j = 0; j < 280; j++) {
for (int i = 0; i < 500; i++) {
if (model.getScreen()[i][j] == 0) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.GREEN);
}
g.drawLine(i, j, i, j); //plots pixel
}
}
}

public void setModel(TripModel model) {
this.model = model;
}

}//en

旅行模型

package paranoid;

import java.awt.Color;
import java.awt.Graphics;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class TripModel {
private List<TripModelListener> listeners = new CopyOnWriteArrayList<TripModelListener>();
private int xmin = 0,
xmax = 499,
ymin = 0,
ymax = 279;
private int x = 120;
private int y = 80;
private int dx = 1;
private int dy = 1;
private int temp = 0;
private int update_counter = 0;
private int x_pos[] = new int[6];
private int y_pos[] = new int[6];
private int screen[][] = new int[500][280];


public TripModel() {

initialisation();
}

public void initialisation(){
System.out.println("initialising...");
x_pos[0] = x;
y_pos[0] = y;

x_pos[1] = xmax - x;
y_pos[1] = y;

x_pos[2] = x;
y_pos[2] = ymax - y;

x_pos[3] = xmax - x;
y_pos[3] = ymax - y;

x_pos[4] = (int)(xmax/2)-50;
y_pos[4] = (int)(ymax/2);

x_pos[5] = (int)(xmax/2)+50;
y_pos[5] = (int)(ymax/2);

for(int j = 0; j<280; j++){
for(int i = 0; i<500; i++){
screen[i][j] = 0;
}
}
} //end of initialisation()

public void update(){
//System.out.println("updating... for the "+update_counter+"th time");

temp = (int)Math.floor(Math.random()*100);
if(temp < 40){ // 40% chance that the direction is changed
dx = (int)Math.floor(Math.random()*3);
dy = (int)Math.floor(Math.random()*3);
dx = dx - 1;
dy = dy - 1;
}


x_pos[0] = x_pos[0]+dx;
y_pos[0] = y_pos[0]+dy;

x_pos[1] = x_pos[1]-dx;
y_pos[1] = y_pos[1]+dy;

x_pos[2] = x_pos[2]+dx;
y_pos[2] = y_pos[2]-dy;

x_pos[3] = x_pos[3]-dx;
y_pos[3] = y_pos[3]-dy;

x_pos[4] = x_pos[4]-dy;
y_pos[4] = y_pos[4]-dx;

x_pos[5] = x_pos[5]+dy;
y_pos[5] = y_pos[5]+dx;

for(int k = 0; k < 6; k++){
if(x_pos[k] < 0){
x_pos[k] = 0;
}
if(x_pos[k] > 499){
x_pos[k] = 499;
}
}

for(int k = 0; k < 6; k++){
if(y_pos[k] < 0){
y_pos[k] = 0;
}
if(y_pos[k] > 279){
y_pos[k] = 279;
}
}


screen[x_pos[0]][y_pos[0]] = 1;
screen[x_pos[1]][y_pos[1]] = 1;
screen[x_pos[2]][y_pos[2]] = 1;
screen[x_pos[3]][y_pos[3]] = 1;
screen[x_pos[4]][y_pos[4]] = 1;
screen[x_pos[5]][y_pos[5]] = 1;

update_counter = update_counter + 1;
fireModelChangedListener();
} //end of update()

private void fireModelChangedListener() {
for (TripModelListener listener : listeners) {
listener.modelChanged();
}
}


public int getXMin() {
return xmin;
}

public int getYMin() {
return ymin;
}

public int getYmin() {
return ymin;
}

public void setYmin(int ymin) {
this.ymin = ymin;
}

public int getXMax() {
return xmax;
}

public int getXmax() {
return xmax;
}

public void setXmax(int xmax) {
this.xmax = xmax;
}

public int getYMax() {
return ymax;
}

public int[][] getScreen() {
return screen;
}

public void addListener( TripModelListener listener) {
listeners.add(listener);
}
}

关于java - 如何在 Java 中的 for 循环中的每个 update() 之后强制执行 repaint()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24448799/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com