[英]How can I force a repaint() after every update() in a for loop in Java?
我寫了一個小的,基本的,萬花筒類型的程序,應該在六個不同的點和不同的方向逐漸繪制相同的模式(隨着時間的推移)。
為此,我創建了一個數組來存儲每個像素的顏色(它的初始顏色是黑色,用數字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
發生了什么事情,你被困在你的for-loop
直到它完成處理然后你重繪。 您應該做的是,因為您正在擴展JPanel
,所以您可以訪問Component的paintComponent
方法,該方法在您第一次繪制和重新繪制組件時調用。
像那樣
@Override
public void paintComponent(Graphics g) {
}
而不是你的
public void paint(Graphics g) {
}
但是,當您覆蓋paintComponent
時,您需要確保將其稱為parent的paintComponent
像這樣:
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
當我們在這里時,我們可以在你的所有繪畫之前或之后調用你的Update方法,我在我的例子中選擇了所有內容:
@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()
- 這不是一個好主意,因為將停止在那段時間內進一步重新繪制你的應用程序。 (事件調度線程/繪圖線程不得用於任何慢速操作)
您希望在此處實現的通常流程如下(可能比您需要的更詳細):
Trip1
)並設置為實例變量。 interface
。 (例如ModelChangedListener
等) 在你的主控制類中,為這個模型注冊一個監聽器, trip2Panel.repaint();
調用: 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(ui)
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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.