Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 5
×

Кольорові кульки на Java

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

доброго часу доби усім!
є наступна ситуація: потрібно створити аплет на якому мають бути 2 кульки(різного кольору),при чому одна кулька повинна перекривати іншу(перша: нерухома-певно розміру, а інша збільшуватись і зменшуватись).
Дану ситуацію вирішив на 80%, другий шарік збільшується, а зменшуватись не хоче...... буду вдячний за будь які пропозиції.

код наступний.......

package applets;
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Applets extends JApplet {
      int w,h;
      int centerx,centery;
     
    boolean AnimationDone,Animation;
      @Override
    public void init() {
        centerx = centery=100;
        w = h = 50;
           new Thread() {
             @Override
             public void run (){
                while(!AnimationDone){
                    updateAnimation();
                    
                   repaint();
                    
                    delayAnimation();
                }
             
                
            }
        }.start();
    }
          public void updateAnimation(){
         if(w < 100 && h < 100){
           w+=2;
           h+=2;
        }
         
    }
     
    public void delayAnimation() {
        try {
            Thread.sleep(30);
            
        } catch (InterruptedException ex) {
            Logger.getLogger(Applets.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
        @Override
    public void paint (Graphics g){
            g.setColor(Color.GREEN);
            g.fillOval(centerx-w/2,centery-h/2,w,h);
             g.setColor(Color.RED);
        g.fillOval(65,65, 70, 70);
    }
    // TODO overwrite start(), stop() and destroy() methods
}
👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

У Карашецького запитайся =)

Проект для raspberry успешно сдали? (просто любопытство).

це дипломна робота, а цей код то її продовження.

Надо полагать, что шарик не уменьшается из-за того, что нужно стирать предыдущее изображение. Когда начнете стирать предыдущее изображения появится мигание. Когда появится мигание, то вы сделаете double buffering. Когда надоест выгребать ошибки c double buffering’ом и оказиональными миганиями. то воспользуетесь OpenGL.

так все і є , але можна детальніше?

Я не знаю Java и её GUI фреймворков. Но обычно у GUI API есть возможность создать нечто подобное offscreen rendering context, что-то в этом духе. При работе с таким контекстом, получается, что все операции отрисовки (стирание и отрисовка заново) происходят в памяти и затем по expose/damage событию отрисовываются из памяти в содержимое окна. Гуглопоиск по «swing offscreen rendering» выдаёт интересную информацию. Если SWING ещё и умеет синхронизироваться с текущим видеорежимом для обновления содержимого по vsync, то миганий можно избежать навсегда.

А почему if без else, может просто поставить если больше 100 то h=-2. Ну или можно через while попробовать.

Можно ввести переменную «направление».
Сначала шарик растет, «направление» = 1, увеличиваем размеры,
когда шарик вырос, ставим «направление» = 2, уменьшаем размеры,
когда шарик стал слишком маленьким, снова «направление» = 1
или останавливаем анимацию вообще, AnimationDone = true,
ну или как Вам там нужно.

Потом, т.к. вы уже закрасили часть экрана шариком, вы не увидите как он уменьшается, т.к. рисовать оно будет уже сверху по закрашенным пикселям. Нужно вызвать super.paint(g) в начале метода paint, это очистит экран.

Выделять отдельный поток и из него вызывать repaint это, думаю, неправильно.
docs.oracle.com/...let.html#thread
download.oracle.com/...y/dispatch.html
Все что касается Swing должно выполнятся в Swing Event Dispatch Thread (EDT).
Можно использовать SwingUtilities.invokeLater для вызова repaint в том вашем потоке.

updateAnimation();
SwingUtilities.invokeLater(new Runnable() {
	@Override
	public void run() {
		repaint();
	}
});
delayAnimation();

Еще можно попробовать использовать Swing таймер, а не создавать свой поток.
docs.oracle.com/...wing/Timer.html

P.S. Я не специалист в Swing анимации, так что это совет почти начального уровня, может еще кто поправит.

велике дякую за пораду!!!
скориставшись вашою порадою, я ї модифікував програму але результат той самий(((

package applets;
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Applets extends JApplet {
      int w,h;
      int centerx,centery;
     int moove  ;
    boolean AnimationDone=false;//false ставиться по замовчуванню;
      @Override
    public void init() {
        centerx = centery=100;
        w = h = 50;
           new Thread() {
             @Override
             public void run (){
                while(!AnimationDone){
                  if (w<100||h<100)
                   {updateAnimation(1);}
                      else
                   {updateAnimation(2);}
                   SwingUtilities.invokeLater(new Runnable() {
	            @Override
	             public void run() {
                    repaint();
                	}
});
                    delayAnimation();
                }
                            
            }
        }.start();
    }
         public  void  updateAnimation(int moove){
        if (moove == 1){
        w+=2;
        h+=2;
        }
        if (moove == 2){
        w-=2;
        h-=2;
        }
        }
     
    public void delayAnimation() {
        try {
            Thread.sleep(40);
            
        } catch (InterruptedException ex) {
            Logger.getLogger(Applets.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
        @Override
    public void paint (Graphics g){
        super.paint(g);
            g.setColor(Color.GREEN);
            g.fillOval(centerx-w/2,centery-h/2,w,h);
            //   g.setColor(Color.RED);
      //  g.fillOval(65,65, 70, 70);
    }
       
    // TODO overwrite start(), stop() and destroy() methods
}

Что происходит сейчас:
— вы увеличиваете размер, пока он < 100, и как только размер больше или равен 100 вы начинаете его уменьшать,
но уменьшить вы так сможете только 1 раз, т.е. если было 100 вы вызываете updateAnimation(2), но здесь же у вас размер уменьшится до 98 и в следующий раз вы опять вызовете updateAnimation(1). И получаются скачки 100, 98, 100, 98, ... 100, 98, ...

Представьте, что у вас есть паровоз, который едет из точки А в точку Б, а потом из Б в А. Пока он не доехал в точку Б у него мотор работает в обычном режиме (режим 1), а вот когда он доедет в точку Б, нужно переключить один раз передачу на «реверс» (режим 2) и не переключать передачу до самой точки А.

Попробуйте нарисовать алгоритм на бумаге, для себя, чтобы легче было видеть свои ошибки. А еще попробуйте вывести сначала цифры от 1 до 10, а потом, назад, до 1, без графики, в консоль, System.out.println, но не в двух циклах, это уж слишком просто, а в одном.

Не нужно пугаться таких ошибок конечно. Я когда-то тоже делал похожие ошибки, давно правда, еще когда только начинал программировать. Но мне было намного проще — не было Java, был Бейсик, да и что-то другое кроме Бейсика я бы в то время вряд ли бы освоил вообще.

вашу пораду я реалізував, але при запуску шарік уже “повного” розміру, а змінюється він тільки тоді коли змінюю розмір вікна і то моргаючи.....Я не знаю в чому причина, що не так, що потрібно виправити.....

package applets;
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Applets extends JApplet {
int w,h;
int centerx,centery;
int moove ;
boolean AnimationDone=false;//false ставиться по замовчуванню;
@Override
public void init() {
centerx = centery=100;
// w = h = 0;
new Thread() {
@Override
public void run (){
while(!AnimationDone){
updateAnimation();
//repaint();

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
repaint();
}
});
delayAnimation();
}

}
}.start();
}
public void updateAnimation(){
int n = 1;
for ( h = 1, w = 1; h > −1; h += n,w+=n ) {

if ( h > 99 && w > 99 )
n = −1;
System.out.print("h"+h + "w"+w+"\n ");

}

}

public void delayAnimation() {
try {
Thread.sleep(110);

} catch (InterruptedException ex) {
Logger.getLogger(Applets.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void update(Graphics g){
g.setColor(Color.GREEN);
g.fillOval(centerx-w/2,centery-h/2,w,h);
g.setColor(Color.RED);
g.fillOval(65,65, 70, 70);
}
@Override
public void paint (Graphics g){
// super.paint(g);
update(g);
}

// TODO overwrite start(), stop() and destroy() methods
}

Нужно было пример с цифрами отдельно сделать, вообще без графики, а так вы просто запутались.

Можно поправить так:

        int n = 1; // направление - это свойство обьекта;

	public void updateAnimation() {
		if (h > -1) {
			h += n;
			w += n;
			if ( h > 99 && w > 99 ) {
				n = -1;
			}
			System.out.println("h=" + h + " w=" + w);	
		}
	}

	//public void update(Graphics g) {
	//}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		g.setColor(Color.GREEN);
		g.fillOval(centerx - w / 2, centery - h / 2, w, h);
		g.setColor(Color.RED);
		g.fillOval(65, 65, 70, 70);
	}

Я сделал для себя так:

	int direction = 1;

	public void updateAnimation() {
		if (direction == 1) {
			if (w < 100) { // направление = 1, шарик растет;
				w += 2;
				h += 2;
			} else {
				direction = 2;
			}
		}
		else if (direction == 2) { // направление = 2, шарик уменьшается;
			if (w > 2) {
				w -= 2;
				h -= 2;
			} else {
				// анимация завершена;
				AnimationDone = true;
			}
		}
	}

як не дивно, але програма працює, трішки змінив функцію updateAnimation()

public void updateAnimation(){
int n = 1;
for ( h = 1, w = 1; h > −1; h += n,w+=n ) {
try {
if ( h > 99 && w > 99 )
n = −1;
System.out.print("h"+h + "w"+w+"\n ");
Thread.sleep(30);
repaint();
} catch (InterruptedException ex) {
Logger.getLogger(Applets.class.getName()).log(Level.SEVERE, null, ex);
}

}

}

але коли шарік зменшується то він не перемальовується, але якщо рухнути межами фрейму, то все ок,...де потрібно прописати repaint()?

P.S. дякую за відповідь!

Thread.sleep(30);
А если частота обновления у монитора будет не 60Hz, а 59.7Hz как у большинства TFT матриц, то будут видимые мигания при перерисовке, когда содержимое сильно отличается.

Все операции с графикой нужно выполнять в Swing EDT.
т.е. repaint() нельзя вызывать из обычного потока (Thread), но нужно вызывать repaint() с помощью SwingUtilities.invokeLater.

Считайте, что у вас есть поток N1 — он выполняет прорисовку графики, этот поток создает сам Swing, и поток N2 — это ваш, самый обыкновенный поток (

new Thread()
), где вы изменяете размер шарика.

Эти 2 потока работают параллельно.
Просто задачи для Swing потока вы даете последовательно, с помощью SwingUtilities.invokeLater.

Чтобы Swing работал нормально, нужно использовать для рисования его поток (EDT).

А вот паузу «Thread.sleep» вы можете делать только в своем потоке, иначе «заморозите» рисование.

Коментар порушує правила спільноти і видалений модераторами.

Підписатись на коментарі