Time Line Events

0

Hej,

Dwie sprawy:

  1. Mam 2 jPanele. Z pierwszego przechodzę klawiszem "VK_RIGHT (strzałka w prawo)" po jakichś tam warunkach do drugiego jPanelu. Gdy przechodzę do drugiego, to pierwszy ustawiam na visible(false), a drugi na (true), w tym samym czasie chcę też by na środku tego drugiego został wyrysowany biały punkt. To jednak się nie udaje. Mogę ujrzeć jak miga na chwilkę i znika. Co zrobić, by został tam na stałe? Poniżej kod:
private void jButton1KeyPressed(java.awt.event.KeyEvent evt)
{
     
    int keyCode = evt.getKeyCode();
    switch( keyCode ) 
    { 
            case KeyEvent.VK_LEFT:
            String tekst = jLabel2.getText();
            if (tekst.equals("blablabla"))
            {
                dispose();
            }
            break;

            case KeyEvent.VK_RIGHT :
            String tekst2 = jLabel2.getText();
            if (tekst2.equals("blablabla"))
            {
                jLabel2.setText("Próba");
            }
            else if (tekst2.equals("Próba"))
            {
                jPanel1.setVisible(false);
                jPanel2.setVisible(true);
                jPanel2.createImage(1366, 768);
                
                Graphics g;
                g = jPanel2.getGraphics();
                g.setColor(Color.WHITE);
                g.fillOval(683, 384, 8, 8);
            }
            break;
     }
}
  1. Druga sprawa tyczy się dalszej fazy jak już ten biały punkt zostanie na środku ekranu i nie zniknie :) w tej sytuacji (gdy już nie zniknie) chciałbym, by wydarzyło się kilka rzeczy np. po pewnym czasie pojawia się pod punktem jakiś napis, po napisie błyska kilka białych punktów w różnych miejscach ekranu i pojawia się okno, w którym user jakoś tam odpowiada na to co widział. Pytanie - jak podejść do tego pojawiania się i znikania punktów?

Pozdrawiam serdecznie po zarwanej nocy :D

0
  1. Musisz ten obrazek tam dodać na stałe, tak żeby metoda paint() tego jPanelu go odrysowywała.
  2. Nie rozumiem pytania. Odpalasz nowy wątek który cośtam mazia po ekranie, gdzie widzisz problem?
0

W nadpisanej metodzie paint() lub paintComponent() powinieneś rysować ten jeden punkt w środku oraz punkty z pewnej kolekcji, która na starcie jest pusta. Tworzysz dwa Timery, pierwszy po ustalonym czasie dodaje do kolekcji błyskające punkty i wywołuje repaint() , drugi je usuwa i tez wywołuje repaint().

0

Dzięki za odpowiedzi :) siadam i będę próbował :)

0

Hej, nie rozumiem tego co robię źle. Kod jak powyżej, ale stworzyłem jeszcze zewnętrzną publiczną metodę rysuj(), która powinna przy wywołaniu rysować na środku panelu punkt, a tego nie robi. Nie rozumiem dlaczego punkt miga i znika. Szukam informacji na temat mechanizmu i nie mogę nic znaleźć. Będę bardzo wdzięczny za łopatologiczne objaśnienie, albo jakiś tutorial o implementacji grafiki w jPanelach.

Pozdrawiam serdecznie!

0

Przecież napisaliśmy, że rysować masz w metodzie paint(), a dokładnie w metodzie o sygnaturze

public void paint(Graphics g)

Ta metoda jest wykonywana automatycznie gdy JVM stwierdza, że należy odrysować panel. Jeśli wygląd panelu ma się zmieniać, to metoda paint winna korzystać z flag logicznych lub kolekcji obiektów do narysowania. Po każdej zmianie flagi/kolekcji należy wywołać metodę repaint(). JVM w odpowiedzi samodzielnie wywoła paint().

0

Uf!!! :D Odpowiedź na pierwsze pytanie znaleziona. Jak zwykle, zamieszczam rozwiązanie swojego problemu :)

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

public class Window extends javax.swing.JFrame     // Klasa jPanelu, w którym chcę rysować
{
    public static void main(String args[])
    {
        new Window();
    }
    
    
    public Window()     // Tutaj tworzę nowe okno JFrame
    {
        setLayout(null);           
        setPreferredSize(new Dimension(1366, 768));
        setTitle("Window");
        setResizable(false);
        
        // A tutaj tworzę nowy JPanel w klasie Rysuj(), która będzie wyrysowywała w nim co tam będę chciał          
        JPanel jPanel1Per = new Rysuj();    

        // Tutaj nadaję panelowi kształt i barwę                     
        jPanel1Per.setPreferredSize(new java.awt.Dimension(1366, 768));      
        jPanel1Per.setBackground(new java.awt.Color(0, 0, 0));
        jPanel1Per.setBounds(0, 0, 1366, 768);
       
        // Ostatecznie dodaję go do JFrame i  pakuję
        add(jPanel1Per);          
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }            
}

Zabawne jest to, że po raz kolejny zostałem zmuszony do zrezygnowania z NetBeansowego SwingBuildera i skrobałem kod "ręcznie" :D Dalsze pisanie raczej też się tak zapowiada. Ale to dobrze. Więcej się człowiek nauczy :) W każdym razie teraz nasza klasa "Rysuj()"


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

public class Rysuj extends JPanel
{
    public Rysuj()
    {
        setPreferredSize(new Dimension(1366,768));   // Pole "działani" naszej klasy
    }
    
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);    // No to rysujemy :)
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        g2d.fillOval(40, 40, 80, 80);
       
    }
}

Dzięki Panowie za pomoc :) Teraz pora na Timery :P

Pozdrawiam serdecznie!

1

Kod konstruktora klasy Window mógłby być krótszy

    public Window()     // Tutaj tworzę nowe okno JFrame
    {
        setTitle("Window");
        setResizable(false);
 
        // A tutaj tworzę nowy JPanel w klasie Rysuj(), która będzie wyrysowywała w nim co tam będę chciał          
        JPanel jPanel1Per = new Rysuj();    
 
        // Tutaj nadaję panelowi barwę (kształt nadaję w konstruktorze)
        jPanel1Per.setBackground(Color.BLACK);
 
        // Ostatecznie dodaję go do JFrame i  pakuję
        add(jPanel1Per);          
 
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }
0

@bogdans, racja. Myślałem, że setPreferredSize() musi być oddzielnie ustawiane dla okna głównego, dla jPanelu i dla metody, która rysuje w tym jPanelu. Dobrze wiedzieć, że jest inaczej :) btw z setBackground() też prawda :D @Shalom, jak się prześpię, to zassam eclipse i buildera, bo przyznam szczerze, że choć bawię się w programowanie dopiero 2 tygodnie, to już mnie denerwuje "nietykalny szary kod" generowany przez NetBeans ;/

0

Witam ponownie :) Nie zakładam nowego tematu, bo sprawa dotyczy timerów. Sytuacja wygląda następująco. Mam 3 klasy. Window, Paint i TimerPaint. W Paint mam metodę do rysowania po panelu, w TimerPaint rozszerzam TimerTask i odpalam klasę Paint, a w Window tworzę nowy obiekt Timer timer = new Timer oraz TimerPaint paint = new TimerPaint(), po czym piszę timer.schedule(paint, 3000, 1000), by rysowanie po panelu zaczęło się po 3 sekundach. To jednak nie działa :) Zastanawiam się dlaczego i cały czas próbuję rozwiązać problem. Będę jednak wdzięczny za pomoc :) Poniżej urywki kodu klas.

Klasa Paint


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class Paint extends JPanel
{

	public Paint()
	{
		setPreferredSize(new Dimension(1366, 768));
	}

	@Override
	protected void paintComponent(Graphics g)
	{

		Font fontA = new Font("Dialog", Font.PLAIN, 10);
		Punkty punkt = new Punkty(); // na to nie zwracajcie uwagi - jest to obiekt jednej z klas bibliotecznych
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setColor(Color.WHITE);
		g2d.setFont(fontA);
		g2d.fillOval(683, 384, 8, 8);
		g2d.drawString("A1", punkt.tablicaX[0], punkt.tablicaY[0]);

	}
}

Klasa TimerPaint

import java.util.TimerTask;

public class TimerPaint extends TimerTask
{

	@Override
	public void run()
	{
		new Paint(); // coś mi tu nie gra na 100% :D ciągle jednak zastanawiam się jak to przerobić

	}
}

No i klasa Window (kawałek)

public void jButton1PerKeyPressed(java.awt.event.KeyEvent e)
	{

		int t = e.getKeyCode();

		if (t == KeyEvent.VK_RIGHT)
		{
			String inf = jLabel1Per.getText();
			if (inf.equals("blablabla"))
			{
				jLabel1Per.setText("blebleble");
			}
			else if (inf.equals("blebleble"))
			{
				jLabel1Per.setText("pufpuf");
			}
			else if (inf.equals("pufpuf"))
			{
                                // Muszę zrobić tak, by wyświetlił się nowy panel (metody Paint) i po czasie w timer.schedule() zaczął maziać to co jest dalej w metodzie Paint :)

				jPanel1Per.setVisible(false);
				Timer timer = new Timer();
				TimerPaint paint = new TimerPaint();
				timer.schedule(paint, 3000, 1000);

			}
		}

Będę wdziĘczny za pomoc :) Pozdrawiam serdecznie! Aha, btw @Shalom, jak to może będziesz czytał, to Eclipse z WB Pro wymiata :D Aż chce się zarywać noce z kodem :D

0

Ale co to ma niby być? Tworzysz obiekt klasy Paint() (czyli ten twój customowy panel) ale nigdzie go nie dodajesz, do żadnego okienka. To co ci się niby ma rysować? o_O
Musisz przekazać do tego obiektu TimerPaint referencje do JFrame do którego ma się ten panel dodać i potem w run() dodać go do okienka...

0
Shalom napisał(a):

Ale co to ma niby być? Tworzysz obiekt klasy Paint() (czyli ten twój customowy panel) ale nigdzie go nie dodajesz, do żadnego okienka. To co ci się niby ma rysować? o_O
Musisz przekazać do tego obiektu TimerPaint referencje do JFrame do którego ma się ten panel dodać i potem w run() dodać go do okienka...

Obiekt klasy Paint() ma się wyświetlić po danej akcji i czasie w oknie klasy Window. Wczęsniej, bez Timera po prostu tworzyłem nowy obiekt klasy Paint (jPanel) w klasie Window (deklarowałem np. private Paint jPanel) i nie było problemu. Teraz chcę, by dopiero po wykonanej akcji i danym czasie ten panel został utworzony, a dalej po kolejnym odstępie czasu, by zostały na nim wyświetlone jakieś bazgroły.

Problem w tym, że ciągle się zastanawiam jak przekazać klasie TimerPaint informację o tym, by tworzyła jPanel w Window. Próbowałem też wcisnąć metodę paintComponent() w ciało metody run() Timera, ale tak się nie da.

EDIT##

Ok wprowadziłem parę zmian w kodach

Klasa Paint


public class Paint extends JPanel
{

	TimerPaint zadanie = new TimerPaint();

	public void init()
	{

		setPreferredSize(new Dimension(1366, 768));

	}

	@Override
	protected void paintComponent(Graphics g)
	{

		Font fontA = new Font("Dialog", Font.PLAIN, 10);
		Punkty punkt = new Punkty();
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setColor(Color.WHITE);
		g2d.setFont(fontA);
		g2d.fillOval(683, 384, 8, 8);
		g2d.drawString("A1", zadanie.poz1, zadanie.poz2); // A1 powinien poruszać się po jPanelu podczas działania timera

	}
}

TimerPaint

class TimerPaint extends TimerTask
{
	int poz1 = 50; // Startowa pozycja "A1" z klasy Paint
	int poz2 = 50;

	@Override
	public void run()
	{
		poz1++;
		poz2++;

		Window.jPanel2Per.repaint(); // odrysowywanie panelu klasy Paint utworzonego w klasie Window

	}
}

Window

// To jest akcja do wykonania
jPanel1Per.setVisible(false);
jPanel2Per.setVisible(true);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerPaint(), 10, 10); // "A1" powinna poruszać się po ekranie, a jedyne co robi to stoi w miejscu

// Oczywiście zadeklarowałem jPaner2Per statycznie
static Paint jPanel2Per;

//Wcześniej w konstruktorze klasy Window dodałego go też do JFrame'a

Teoretycznie "A1" powinien śmigać po ekranie, a tego nie robi :)

1
  1. Poniższy fragment wygląda dość oryginalnie:
jPanel1Per.setVisible(false);
jPanel2Per.setVisible(true);
  1. A niby czemu ma śmigać? Tworzysz dwa obiekty typu TimerPaint, zmieniasz współrzędne w tym utworzonym przy tworzeniu Timera, a przy rysowaniu korzystasz z tego obiektu
TimerPaint zadanie = new TimerPaint();

Kod winien wyglądać tak:

timer.scheduleAtFixedRate(zadanie, 10, 10);
0

Uf... udało się... :D

obiekt "zadanie" miałem w klasie Paint. Zrobiłem go statycznym i napisałem tak jak poradziłeś "timer.schedule(Paint.zadanie, 10, 10)" i ożyło, tak coś czułem, że mogę próbować repaintować coś co nie dostaje danych jak się zmieniać :)

Btw co do punktu "1.", dopiero wstałem, ale chyba domyślam się, że ironizujesz :D dlaczego? Źle wyłączam panel1 i odpalam panel2? W sumie teraz zostawiłem tylko

jPanel1Per.setVisible(false);

Timer timer = new Timer();

timer.scheduleAtFixedRate(Paint.zadanie, 10, 10);

i działa :)

Pozdrawiam i dziękuję za odpowiedź! :)

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