Problem z animacją w javie, usypianie wątku...

0

Witam, muszę napisać program program z krzywą beziera, część programu już mam, teraz tylko nie wiem jak zrobić animację by po kliknięciu w button włączała się animacja... Na razie chcę zrobić animację linii, żeby w ogóle zobaczyć jak to działa, jednak nie działa mi to tak jak należy, tzn kiedy kliknę button program tak jakby się zawiesza button przez chwilę pozostaje wciśnięty a następnie rysuje mi się ostateczny wygląd animacji. Wiem, że usypiam cały wątek i dlatego tak się dzieje, jednak nie wiem jak mam to zrobić by animacja działała:( z góry dzięki za pomoc i wyrozumiałość co do błedów w programie. Nie wrzucam pozostałych klas, chodzi mi o to by tą linie rysowało w paintComponent() gdzie wybor == 2 tzn animowało a nie usypiało cała aplikację:(, po wywołaniu z Main acctionPerformed funkcji panel.animacja()...


   
 /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author KJ
 */

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class MainBeizer {

    /**
     * @param args the command line arguments
     */
    public static JFrame frame;
    public static int WYSOKOSC = 724, SZEROKOSC = 1024;
    public static JSlider fid = new JSlider(JSlider.VERTICAL, 1, 100,50);
    public static boolean animacja = false;
    
    
   

    public static void main(final String[] args) throws InterruptedException {

        frame = new JFrame("Krzywa");
        frame.setSize(SZEROKOSC,WYSOKOSC);
        frame.setLayout(new BorderLayout(5,5));



        final Panel panel = new Panel();
        panel.setLayout(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder("Krzywa"));
        
        
            
        fid.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                JSlider source = (JSlider)e.getSource();
                Panel.FID = source.getValue();
                Panel.wybor = 1;
                
                frame.repaint();
                
            }
        });
        
        
        
        JButton anim = new JButton("Animuj");
        anim.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                
                
                try {
                    panel.animacja();
                } catch (InterruptedException ex) {
                    Logger.getLogger(MainBeizer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout());
        panel1.add(fid, "Center");
        panel1.add(anim, "East");
        panel1.setBorder(BorderFactory.createTitledBorder("Obsluga"));
        
        
        frame.add(panel, "Center");
        frame.add(panel1, "East");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        
        
     
    }
    
}





/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

/**
 *
 * @author Krzych
 */
public class Panel extends JPanel implements ActionListener{

   
   public Krzywa krzywaBe = new Krzywa();
   public static int XXX, YYY, wybor = -1;
   public int licznik = 0;
   public Punkt []punkty = new Punkt[4];
   public Punkt punkt;
   public boolean rysujKrzywa = false;
   public static int FID = 100;
   public static boolean suwak = false;
   
   public int licznik2=0;

    public Panel()
    {
 
        addMouseListener(new MojaMyszka());
        addMouseMotionListener(new MojaMyszkaPol());
    }
    
   
    
   @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;

        if(wybor == 1)
        {
            
            
             g2.setColor(Color.BLACK);
             if(licznik == 0 && suwak==true)
             {
             g2.fillRect(punkty[0].getX()-4, punkty[0].getY()-4, 8, 8);
             }
             else if(suwak == true){
                    for(int i=0;i<licznik;i++)
                    {
                
                        g2.fillRect(punkty[i].getX()-4, punkty[i].getY()-4, 8, 8);
                    }
                    
                    
             }

             if(rysujKrzywa == true)
                    {
                        
                        for(int i=0;i<licznik;i++)
                            {
                                g2.drawLine(punkty[i].getX(), punkty[i].getY(), punkty[(i+1)%licznik].getX(), punkty[(i+1)%licznik].getY());
                            }
                        
                        krzywaBe.changeKrzywa(punkty[0], punkty[1], punkty[2], punkty[3], FID);
                        g2.setColor(Color.RED);
                        Punkt[] krzywa = krzywaBe.getPunkty();
                        
                        for(int i=0;i<(krzywaBe.getPunkty().length);i++)
                            {
                                int j = i+1;
                                if(j>=krzywaBe.getPunkty().length) 
                                    j = krzywaBe.getPunkty().length-1;
                                    g2.drawLine(krzywa[i].getX(), krzywa[i].getY(), krzywa[j].getX(),krzywa[j].getY());
                            }
                    }
            
        }

        if(wybor == 2)
        {
    
             g2.drawLine(23+licznik2,23+licznik2,88+licznik2,88+licznik2);
       
       }
 
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

   protected class MojaMyszka implements MouseListener
   {

        public void mouseClicked(MouseEvent e) {

            if((e.getModifiers() & InputEvent.BUTTON1_MASK) !=0)
            {
               if(licznik <4)
               {
                   suwak = true;
                   dodajPunkt(e.getX(), e.getY());
               }
               else
                   nowyPunkt(e.getX(), e.getY());
               
            }
            
           if((e.getModifiers() & InputEvent.BUTTON3_MASK) !=0)
           {
           
            
           }

            
        }

        public void mousePressed(MouseEvent e) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public void mouseReleased(MouseEvent e) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public void mouseEntered(MouseEvent e) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public void mouseExited(MouseEvent e) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

   }

   protected class MojaMyszkaPol implements MouseMotionListener
   {

        public void mouseDragged(MouseEvent e) {
           
            if(licznik ==4)
            for(int i=0; i< licznik; i++)
           {
               if((e.getX() >= punkty[i].getX()-5 && e.getX() <= punkty[i].getX()+5) && (e.getY() >= punkty[i].getY()-5 && e.getY() <= punkty[i].getY()+5))
               {
                   punkty[i].setX(e.getX());
                   punkty[i].setY(e.getY());
                   wybor = 1;
                   repaint();
                   
                   
               }
           }
        }

        public void mouseMoved(MouseEvent e) {
            
        }

   }

    public void dodajPunkt(int xxxx, int yyyy)
    {
        punkt = new Punkt(xxxx, yyyy);
        punkty[licznik] = punkt;
        
        wybor = 1;
        licznik++;
        if(licznik == 4)
        {
            rysujKrzywa = true;  
        }
        repaint();
   }
    
    public void nowyPunkt(int xxxx, int yyyy)
    {
        punkt = new Punkt(xxxx, yyyy);
        for(int i = 0;i<3;i++)
        {
            punkty[i]=punkty[i+1];
        }
        punkty[3]=punkt;

        wybor = 1;
        repaint();
   }
    
    public void animacja() throws InterruptedException
    {
    
        for(int i = 0; i<30; i++)
        {
        wybor=2;
        repaint(); 
        Thread.sleep(100);
        licznik2++;
        
        }
 
    }

}


 
0

To jest Twój obiekt klasy anonimowej, którego metoda actionPerformed() jest wywoływana z wątku obsługi zdarzeń Swinga:

new ActionListener() {
 
            @Override
            public void actionPerformed(ActionEvent e) {
 
 
                try {
                    panel.animacja();
                } catch (InterruptedException ex) {
                    Logger.getLogger(MainBeizer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

To co jest w actionPerformed, to nie jest kod wywoływany przez Ciebie (sic!). Ty tylko podajesz go do użycia Swingowi. W takich metodach nie ma się nic robić, a tylko zmienić stan obiektów Swinga (np. kontrolek), albo ustawić stan swojej aplikacji i jak najszybciej się kończyć.

Żeby rozwiązać Twój problem trzeba abyś panel.animacja() wywoływał z innego wątku niż Swing. W tym celu można utworzyć nowy obiekt klasy Thread i w jego metodzie run() zdefiniować wywoływanie tej animacji.
Osobnym problemem z którym musisz sobie poradzić jest synchronizacja zmiennych wybor oraz licznik2 tak, aby paint miał te dane i nie miał ich zablokowanych innym wątkiem (np. Swinga). Mógłbyś użyć do tego SwingWorkera, ale sądzę, że na obecnym etapie przerasta to Twoje możliwości rozeznania o co chodzi. :)

Dla jasności.
Wszystkie aplikacje Swinga (poza apletami) działają w taki sposób:

  1. Uruchamia się metoda Main, w której tworzysz jakieś kontrolki, okna itp. Od tego momentu na pewno działa już pętla obsługi zdarzeń Swing, ale nie ma żadnego wpływu na Twoją aplikację.
  2. W którymś momencie odpalasz na jakimś utworzonym obiekcie okna top-level metodę setVisible(true) - od tego momentu zdarzenia idące na to okno są obsługiwane przez kod tego okna, a metoda Main powinna się zakończyć. Jeżeli zdefiniowałeś jakieś listenery i zarejestrowałeś je przez add...listener(), to niektóre zdarzenia będą obsłużone przez kod, który napisałeś.
  3. Jeżeli trzeba wykonać coś czasochłonnego w kodzie listenerów (które zarejestrowałeś), to odpala się nowe wątki (w uproszczeniu), które mają wykonać to co im zlecono i w jakiś sposób poinformować resztę Twojej aplikacji o tym co zrobiły lub nie. Jeżeli to "informowanie" ma polegać na zmianie stanu kontrolek Swinga, to w tych wątkach wszelkie wywołania metod Swinga trzeba opakować za pomocą przekazania zadania do wykonania w procedurze invokeLater(). To zadanie zostanie wywołane i wykonane w wątku Swinga. Informowanie reszty Twojej aplikacji może być przeprowadzone dowolną metodą - zmianą stanu zmiennych, wywołaniem metod itp. Sam musisz zadbać o poprawne synchronizowanie tych danych (np. stworzyć coś podobnego do invokeLater).

Jeżeli w pkt. 2 metoda Main nie zakończy się, to wątek ten działa niezależnie od wątku Swinga oraz niezależnie od ewentualnie tworzonych przez jego procedury (również te napisane przez Ciebie) nowych wątków. Można kontynuować jakieś działania w Main i przekazywać kolejne zlecenia do Swinga, ale z punktu widzenia aplikacji GUI należy to traktować jak kolejne długotrwałe zadanie - dla odmiany zainicjowane niezależne od tej aplikacji.

0

Wielkie dzięki za wyczerpującą odpowiedz, dzięki temu sobie poradziłem z problemem i utworzyłem nowy wątek:)

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