Zastopowanie czyszczenia ekranu super.paint(g)

0

Witam, stanąłem w miejscu i nie potrafię sobie poradzić z problemem. Stworzyłem trzy klasy. W klasie Start chciałbym stworzyć dwa elementy(zielone prostokąty), które pojawiają się cyklicznie na różnych współrzędnych w określonym czasie. Niestety problem polega na tym, że na ekranie po pojawieniu jednego z tych elementów poprzedni jest usuwany. I moje pytanie: czy da się jakoś zastopować super.paint(g) przy wywołaniu jednego z tych elementów? Proszę bez zbędnych epitetów- dopiero się uczę. Z góry dziękuję za rady

Edit: albo jak usunąć ostatni narysowany obraz?

package probtimery2;

import java.util.Timer;

import javax.swing.JFrame;

public class Start extends JFrame {
	
	static JFrame frame= new JFrame();
	static Panel panel= new Panel();

	public static void main(String[] args){
		
		
		frame.setSize(300,300);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		Czas czas= new Czas();
		Czas czas2= new Czas();
		
		frame.add(panel);
		
		Timer timer=new Timer();
		Timer timer2=new Timer();
		timer.schedule(czas, 0,1*1000);
		timer2.schedule(czas2, 0,2*1000);
		
	}
}
package probtimery2;


import java.awt.Color;
import java.util.Random;
import java.util.TimerTask;

public class Czas extends TimerTask 
{
	static int x=30;
	static int y=30;
	Random random=new Random();
	
	public void run()
	{
		x=random.nextInt(200);y=random.nextInt(200);
		Start.panel.repaint();
		
		System.out.println("juz");
	}

	

}
package probtimery2;

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JPanel;

public class Panel extends JPanel {
	
	Color kolor;
	Random rand=new Random();
	
	
public void swicz()
{
	int i=rand.nextInt(5);
	switch (i) {
    case 1:   kolor=Color.GREEN;
             break;
    case 2:   kolor=Color.RED;
             break;
    case 3:   kolor=Color.BLUE ;
             break;
    case 4:   kolor=Color.YELLOW;
             break;
    case 5:   kolor=Color.WHITE;
             break;
	}
}
	
	public void paint(Graphics g){
		this.swicz();
		super.paint(g);
		g.setColor(kolor);
		g.fillRect(Czas.x,Czas.y, 30, 30);
		
	}
	

	
}
0

Wtf? Po prostu usuń wiersz

super.paint(g);

On nie jest obowiązkowy.
Nadpisz raczej metodę paintComponent, a nie metodę paint. Popraw też warunki w switchu - nextInt(5) zwraca liczbę z zakresu [0,4], a nie z zakresu [1,5].
//Edit, jeśli chcesz rysować wiele prostokątów to powinieneś stworzyć kolekcję points typu ArrayList<ColoredPoint> i rysować w pętli:

public void paintComponent(Graphics g)
{
     super.paintComponent(g);
     for(ColoredPoint p:points)
     {
          g.setColor(p.color);
          g.fillRect(p.x,p.y,30,30);
     }
}

Rysowanie tylko ostatnio wylosowanego prostokąta zadziała źle gdy użytkownik np. zminimalizuje okno a potem je przywróci - zostanie narysowany tylko jeden (ostatnio wylosowany) prostokąt. Metoda rysująca powinna być jak najszybsza, przenieś losowanie koloru do Timera.

0

Mi nie o to chodzi żeby na ekranie pojawiały się prostokąty a później zostawały na JPanelu, rozwiązanie z usunięciem super.paint(g) odpada. A raczej chodzi o to żeby po na ekranie były zawsze dwa prostokąty. Przy rysowaniu trzeciego jeden znikał. Resztę podpowiedzi za chwilę sprawdzę:)

Edit:
Ok, uzupełniłem błędy, ale i tak nie rozwiązałem swojego problemu. Potrzebuję wyrysowywać dwa elementy(prostokąty) w czasie(cyklicznie za pomocą timer.schedule). Gdy już jest jeden element z timer.schedule... i nadchodzi czas do wyrysowania następnego(z tego samego timera), to jak skasować ten poprzedni, tak aby z timer i timer2 zawsze było po jednym elemencie na jpanelu. Mógłby ktoś coś poradzić?

0
public class Czas extends TimerTask 
{
    static int x=30;
    static int y=30;
    static int x2=5;
    static int y2=5;
    static Color kolor = null;
    Random random=new Random();
 
    public void run()
    {
        x=random.nextInt(200);y=random.nextInt(200);
        x2=random.nextInt(200);y2=random.nextInt(200);
        //dopisz losowanie koloru
        Start.panel.repaint();
 
        System.out.println("juz");
    }
 
}
...
    public void paint(Graphics g){
        super.paint(g);
        g.setColor(Czas.kolor);
        g.fillRect(Czas.x,Czas.y, 30, 30);
        g.fillRect(Czas.x2,Czas.y2, 30, 30);

 
    }

I pozbądź się zmiennych statycznych w klasie TimerTask.

0

tak jak wyżej w edit napisałem. Nie da się tego zrobić w inny sposób? Chciałbym za pomocą timer.schedule w przyszłości więcej elementów wyświetlać i nie chciałbym żeby wyświetlały się w tym samym czasie.

Edit: Jak nikt nie wie o co mi chodzi, to może inaczej, jak tego się dowiem to z resztą sobie poradzę. Załóżmy, że wyrysowuję 5 elementów(oddzielnie)
JPanel:

 
|---1-----------|
|--------2------|
|------3--------|
|--4------------|
|----------5----|
|---------------|

(cyfry to elementy, np prostokąty)

Jak usunąć przykładowo trzeci element, tak aby JPanel wyglądął tak:

|---1-----------|
|--------2------|
|---------------|
|--4------------|
|----------5----|
|---------------|
0

Zrób kolekcję timerów, a w paintComponent zrób pętle po timerach. Wtedy pola x, y nie mogą być statyczne. Czy wszystkie prostokąty maja mieć taki sam kolor?
//Edit, rysuj w pętli po kolekcji prostokątów i usuwaj z kolekcji zbędne prostokąty.
//Bardzo waży edit, przemyśl co chcesz uzyskać. W kolejnych postach odmiennie opisujesz swój problem.

1

Masz przykładowy kod dla dwóch timerów, jeden dodaje losowy prostokąt, drugi usuwa losowy prostokąt.

import java.awt.*;

public class ColoredRectangle
{
    int x = 0;
    int y = 0;
    Color color = null;
    public ColoredRectangle(int x,int y,Color color)
    {
        this.x = x;
        this.y = y;
        this.color = color;
    }
}

import java.util.*;
import javax.swing.*;
import java.awt.*;

public class Start extends JFrame 
{ 
    private ArrayList<ColoredRectangle> rectangles = new ArrayList<ColoredRectangle>();
    private Random random = new Random();
 
    public static void main(String[] args)
    {
        new Start();
    }
    public Start()
    {        
        java.util.Timer timer = new java.util.Timer();
        java.util.Timer timer2 = new java.util.Timer();
        timer.schedule(new Add(), 0,1*1000);
        timer2.schedule(new Remove(), 0,2*1000);
        add(new Panelik());
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);        
        setVisible(true);
    }
    class Panelik extends JPanel
    {
        public Panelik()
        {
            setBackground(Color.WHITE);
            setPreferredSize(new Dimension(300,300));
        }
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            for(ColoredRectangle cr:rectangles)
            {
                g.setColor(cr.color);
                g.fillRect(cr.x,cr.y,30,30);
            }
        }
    }
    class Add extends TimerTask 
    { 
        public void run()
        {
            rectangles.add(new ColoredRectangle(random.nextInt(200),random.nextInt(200),
                new Color(random.nextInt(256),random.nextInt(256),random.nextInt(256))));
            repaint();
        } 
    }
    class Remove extends TimerTask 
    { 
        public void run()
        {
            if(rectangles.size() > 0)
            {
                rectangles.remove(random.nextInt(rectangles.size()));
                repaint();
            }
        } 
    }      
}
0

witam, dzięki za odpowiedź i pomoc, ale u mnie to jednak nie działa(?) pojawiają się dalej nowe elementy, a stare zostają chociaż nie za każdym razem..

Edit:OK. zrobiłem swój program na podstawie wskazówek, mam problem który pojawia się co jakieś 0-50powtórzeń timera schedule, ktory ma za zadanie usuwać obiekt z kolekcji. Czasami pojawia się błąd i tego elementu nie usuwa, nie mam pojęcia dlaczego. Kod programu wykonuje się prawie zawsze. Po wystąpieniu błędu zamiast 2elementów na JPanelu pojawiają się trzy, zaradziłem temu wstawiając warunek if: if(Start.rectangles.size()>2)Start.rectangles.remove(0);, ale chciałbym się dowiedzieć z jakiego powodu ten błąd występuje. Oto screen:
http://www33.speedyshare.com/s2UBR/download/btt.jpg

0

W moim kodzie wystarczy zmienić dwie rzeczy:

  • typ kolekcji
private Vector<ColoredRectangle> rectangles = new Vector<ColoredRectangle>();
  • umieścić rysowanie w bloku synchronizowanym:
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            synchronized(rectangles)
            {
                for(ColoredRectangle cr:rectangles)
                {
                    g.setColor(cr.color);
                    g.fillRect(cr.x,cr.y,30,30);
                    /*try
                    {
                        Thread.sleep(100);
                    }
                    catch(InterruptedException e)
                    {
                    }*/
                }
            }
        }

Fragment "zakomentowany" przydaje się do testowania - usypianie wątku rysującego zwiększa zdecydowanie szansę na to, że zostanie on wywłaszczony.

1 użytkowników online, w tym zalogowanych: 0, gości: 1