在Java中,如何在for循环中的每次更新()后强制重新绘制()?
我已经写了一个小的、基本的、万花筒式的程序,它应该在六个不同的点和不同的方向逐渐绘制相同的模式(随着时间的推移) 为此,我创建了一个数组来存储每个像素的颜色(它的初始颜色为黑色,由数字0表示),然后数组中的6个起始点的颜色变为绿色(由数字1表示)。这些点应出现在屏幕上,然后根据前6个点的位置再创建6个点。然后应显示更新的屏幕。重复,重复,重复 我的问题是,所有新像素的更新都是在绘制屏幕之前进行的。我查看了一些其他帖子和网络教程等,并认为AWT足以避免浪费时间重新绘制微小的更改。这似乎还涉及到一种叫做在Java中,如何在for循环中的每次更新()后强制重新绘制()?,java,awt,Java,Awt,我已经写了一个小的、基本的、万花筒式的程序,它应该在六个不同的点和不同的方向逐渐绘制相同的模式(随着时间的推移) 为此,我创建了一个数组来存储每个像素的颜色(它的初始颜色为黑色,由数字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
package偏执狂;
导入java.awt.Color;
导入java.awt.Graphics;
导入javax.swing.JPanel;
公共类Trip2扩展了JPanel{
私有静态最终长serialVersionUID=1L;
私有整数xmin=0,
xmax=499,
ymin=0,
ymax=279;
私有整数x=120;
私人int y=80;
私有整数dx=1;
私有整数dy=1;
私人内部温度=0;
私有int更新_计数器=0;
专用重绘计数器=0;
私有整数x_pos[]=新整数[6];
私用整数y_pos[]=新整数[6];
专用整数屏幕[][]=新整数[500][280];
公共图书馆2(){
初始化();
对于(int i=0;i<5000;i++)
{
更新();
System.out.println(“刚从update()返回”);
repaint();//在所有更新之前,不会激活此重新绘制
System.out.println(“刚从paint()返回”);//已完成,但我希望在每次更新后重新绘制。
}
}
公开无效初始化(){
System.out.println(“初始化…”);
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);
对于(int j=0;j 279){
y_pos[k]=279;
}
}
屏幕[x_位置[0]][y_位置[0]]=1;
屏幕[x_位置[1]][y_位置[1]]=1;
屏幕[x_位置[2]][y_位置[2]]=1;
屏幕[x_位置[3]][y_位置[3]]=1;
屏幕[x_位置[4]][y_位置[4]]=1;
屏幕[x_位置[5]][y_位置[5]]=1;
更新_计数器=更新_计数器+1;
}//更新结束()
公共空间涂料(图g){
System.out.println(“用于“+重新喷漆计数器+”第次“)的喷漆屏幕);
g、 设置颜色(颜色为黑色);
g、 fillRect(xmin,ymin,xmax,ymax);
for(int j=0;j发生的事情是,您被困在for循环中
,直到它完成处理,然后重新绘制。您应该做的是,因为您正在扩展JPanel
,所以您可以访问组件的paintComponent
方法,该方法在您首次绘制和重新绘制组件时调用
像这样
@Override
public void paintComponent(Graphics g) {
}
而不是你的
public void paint(Graphics g) {
}
但是,当覆盖paintComponent
时,需要确保调用它的父级paintComponent
像这样:
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
我们可以在绘制之前或之后调用更新方法,在我的示例中,我选择了“一切之前”:
@Override
public void paintComponent(Graphics g) {
update();
super.paintComponent(g); // Super is used to reference the parent
// All of your painting methodology
repaint(); // Force the component to repaint so this gets called over and over.
}
一定要删除for循环;当然,如果您想在绘制之前获得大量数据,您可以始终保留它
如果您真的想要,您可以始终保持与现有代码完全相同的代码,但遵循与我上面所说的类似的模式
像这样:
public void paint(Graphics g) {
update();
// All of your painting methodology
repaint(); // Force the component to repaint so this gets called over and over.
}
这里的一个主要问题是,您正在paint方法中调用Thread.sleep()
,这不是一个好主意,因为这会在该期间停止进一步重新绘制应用程序。(事件调度线程/绘制线程不得用于任何缓慢的操作)
您希望在此处实现的通常流程如下(可能比您需要的更详细):
创建一个包含所有数字变量的模型类,特别是仅数字(无UI代码)还创建各种getter以允许UI稍后访问这些数字
允许将此模型类传递给视图类(Trip1
,在您的情况下),并设置为实例变量
从主控制类中创建一个新线程或计时器,该线程或计时器根据需要定期调整模型编号/内部构件
为模型上的更改创建侦听器界面
。(例如ModelChangedListener
或类似内容)
将侦听器列表添加到您的模型中—使用register方法只需将侦听器添加到列表中即可
使您的模型发生任何更改,即当号码更新时,这些调用会触发到已注册的侦听器
在主控制类中,将侦听器注册到此模型,该模型仅调用:
trip2Panel.repaint();
在面板的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);
}
}
TripModelListener
package paranoid;
public interface TripModelListener {
void modelChanged();
}
Trip2(用户界面)
package偏执狂;
导入java.a
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);
}
}