» »

[Java] Nova nit znotraj JPanel.paintComponent()

[Java] Nova nit znotraj JPanel.paintComponent()

alexa-lol ::

hej :D mene zanima zakaj omenjena zadeva noče prikazati črte? Ne vem zakaj ne zažene niti "nit". Mogoče kdo vidi težavo?
import java.awt.*;
import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable()
                                        {
                                            public void run() {
                                                Window window = new Window("Thread");
                                                JPanel drawPanel = new DrawPanel();
                                                window.add(drawPanel, BorderLayout.CENTER);
                                                window.setVisible(true);
                                            }
                                        } );
    }

    private static class DrawPanel extends JPanel{
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            Thread nit = new Thread(new Threadek(g));
            nit.start();
        }
    }

    private static class Threadek implements Runnable{
        private Graphics g;

        public Threadek(Graphics g){
            this.g = g;
        }
        
        public void run(){
            g.drawLine(10,10,600,100);
        }
    }


    private static class Window extends JFrame{
        //konstruktor
        public Window(String title){
            setTitle(title);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Toolkit tool = Toolkit.getDefaultToolkit();
            Dimension d = tool.getScreenSize();
            int width = d.width;
            int height = d.height;
            setSize(3*width/4, 3*height/4);
            setLocation(width/8, height/8);
        }
    }
}


Hvala za pomoč
Lep pozdrav

alexa-lol ::

evo najdu rešitev...in mislim, da vem zakaj je prišlo do zapleta
    private static class DrawPanel extends JPanel{
        private Thread nit;

        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            nit = new Thread(new Threadek(g));
            nit.start();
            try{
                Thread.sleep(1);
            } catch(Exception e){}
        }
    }


1. inicializiram nitko nit na zacetku, tako, da ni treba vsakic inicializirat...
2. dodam, da se metoda paintComponent izvaja se 1ms vec. Mislim, da je bil problem sledeč. Ob zagonu nitke se je klicala metoda drawLine in pomoje rabi Java nekaj casa da obdela zahtevek. No jaz sem pa metodo zakljucil in posledicno ubil nit se preden je do konca izvedla ukaz drawLine

zdaj dela (ok dobim se dolocene izjeme ampak naceloma dela)

Zgodovina sprememb…

kopernik ::

Že nekaj časa nisem delal v swingu, ampak v spominu imam, da je pametno vse gui stvari delati v enem threadu (event dispatch thread) in časovno zahtevne operacije pa v svojih threadih. Za ta namen imaš tudi razred SwingWorker, ki že out of the box podpira omenjen princip.

EDIT: še relevanten del iz javadoca:
When writing a multi-threaded application using Swing, there are two constraints to keep in mind: (refer to How to Use Threads for more details):

  • Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive.

  • Swing components should be accessed on the Event Dispatch Thread only.


Zgodovina sprememb…

  • spremenil: kopernik ()

arjan_t ::

Prvo vprašanje je zakaj bi sploh to delal?

Izriše pa ne zato ker se izris v paintComponent konča preden se konča nit (v tem času se drawLine še ne izvede, tudi lahko pride do nepredvidljivih stvari če "rišeš" medtem ko se okno že izrisuje).
Thread.sleep v tem primeru dela, ampak če bi se nit izvajala dlje bi bili spet isti problemi

Za to se uporablja Thread.join, tako bo izvajanje metode počakalo da se izvede nit do konca

alexa-lol ::

@kopernik.. vem za EDT...

ja potem če metoda počaka na konec izvajanja niti je isto če bi to izvedel zaporedno... torej nit nima pomena.

bom delal risanje (g.drawLine(..)) v drugi niti kot izris (izris bom pustil v svoji niti)

alexa-lol ::

Imam pa na tem mestu novo vprašanje...
Kako bi pripel na JPanel MouseMotionListnerja, ki bi se izvajal, delal tudi če bi npr. bila paintComponent zasedena, ker če dam npr. v paintComponent kodo za sleep(5000); mi teh 5s ne dela MouseMotionListener

arjan_t ::

alexa-lol je izjavil:


ja potem če metoda počaka na konec izvajanja niti je isto če bi to izvedel zaporedno... torej nit nima pomena.


Stvar se MORA izvajati zaporedno ...

In še zmeraj nisi odgovoril zakaj bi to sploh delal

nightrage ::

Koker sem malo pogledal kodo, se mi zdi, da je napisana mal čudno. Zakaj bi v klasu imel statičen klas, ki deduje od JFrame. "private static class Window extends JFrame", če bi lahko od JFrame-a dedoval že v primarnem klasu Main. Potem je mal čudno, da recimo niti ne zaženeš naprimer v konstruktorju. Ni ti treba overridati paintComponent metode, da bi zagnal nit. Ampak dober je, ne bom se delal pametnega, drugač pa če hočete risati v javi, vam zelo priporočam javafx tehnologijo.

alexa-lol ::

ok kaj hočem narest...

Hočem met JPanel na katerega bi pripel MouseMotionListnerja, ta bi beležil premikanje "točke" po JPanel v razred Dimension. Poleg tega hočem imeti v dveh ločenih nitih še metodo za izračun in risanje objekta Graphics, ki na podlagi podatkov razreda Dimension izračunata neke stvari. Sam izris stvari hočem imeti tudi v svoji niti, da ne bi oviral dela MouseMotionListnerja.

Torej

JPanel -> MouseMotionListner -> Dimension -> Izracun -> Izris -< nazaj v JPanel, pri čemer mora MouseMotionListner delovati vedno (ne sme se zogditi, da bi ga npr. paintComponent() zaustavil)

Kako bi se tega lotil?

Lep pozdrav :)

nightrage ::

Jaz ti priporočam, da si pogledaš tehnologijo JavaFX, ker to tam kar ti hočeš narediti, narediš v maksimalno 30 vrsticah kode.

alexa-lol ::

Samo a ni tko, da Java FX ne podpira večnitnosti?

alexa-lol ::

ok ker še vedno iščem rešitev bom povedal kaj delam, da lahko kdo pomaga ce ve..

Delam linearno projekcijo 3D skeleta na 2D(zaslon). V praksi to pomeni 3D grafika (do neke stopnje). Matematična osnova je linearna algebra oz. linearne preslikave (vse že narejeno - 2 matriki + en račun).

Kaj želim? Da bi lahko uporabnik s potegom miške obračal telo. Vsa "logika" je že narejena, edino kar mi ne uspe je to, da bi se te premiki miške (draggi) beležili neodvisno od izrisevanja (ne vem kakšno FPS bom dosegel).

Programski jezik je Java.
Kakšen nasvet?

Hvala in lep pozdrav :D

kopernik ::

A si pogledal java3d (nekakšen bridge do opengl oz. direct3d)? Verjetno je to primernejše za kompleksno grafiko (vrtenje 3d modelov).

Spura ::

alexa-lol je izjavil:


2. dodam, da se metoda paintComponent izvaja se 1ms vec. Mislim, da je bil problem sledeč. Ob zagonu nitke se je klicala metoda drawLine in pomoje rabi Java nekaj casa da obdela zahtevek. No jaz sem pa metodo zakljucil in posledicno ubil nit se preden je do konca izvedla ukaz drawLine

Niti ne delujejo tako. Ce koncas metodo, kjer si naredil nit, se nit prav nic ne ubije. Aktivne niti se niti ne garbage collectajo.

Mouse listener lahko kar na Jpanelu implementiras in ne rabi svoje niti ker samo spremeni par koordinat oziroma kotov. Lahko imas pa izrisovanje v svojih nitih.

alexa-lol ::

hej :D
@kopernik hočem narediti iz nule, ampaak se mi ustavi pri nitih oz. pri JPanel
@Spura kako bi to naredil..mi ne rata nikakor
bi mi lahko kdo dodal v program metodo za izris, ki bi tekla v svoji niti, ker mi je nikakor ne rata sprogramirati.
package grafikek;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.*;

public class Main{

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable()
                                        {
                                            public void run() {
                                                Window window = new Window("Thread");
                                                JPanel drawPanel = new DrawPanel();
                                                window.add(drawPanel, BorderLayout.CENTER);
                                                window.setVisible(true);
                                            }
                                        } );
    }

    private static class DrawPanel extends JPanel implements MouseMotionListener{
        private Dimension dim;

        public DrawPanel(){
            super();
            dim = new Dimension(0, 0);
            this.addMouseMotionListener(this);
        }
        
        public void mouseDragged(MouseEvent e) {
        }

        public void mouseMoved(MouseEvent e) {
            changeDimension(new Dimension(e.getX(), e.getY()));
        }

        private void changeDimension(Dimension dime){
            if(!dim.equals(dime)){
                dim.setSize(dime.getHeight(), dime.getWidth());
                System.out.println("Dimension changed to " + dim.getHeight() + ", " + dim.getWidth());
            }
        }
    }

    private static class Window extends JFrame{
        //konstruktor
        public Window(String title){
            setTitle(title);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Toolkit tool = Toolkit.getDefaultToolkit();
            Dimension d = tool.getScreenSize();
            int width = d.width;
            int height = d.height;
            setSize(3*width/4, 3*height/4);
            setLocation(width/8, height/8);
        }
    }
}


help :) in lp

Zgodovina sprememb…



Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Pomoč pri programiranju z javo

Oddelek: Programiranje
203343 (2270) milc
»

[Java] Zasnova shoot em up igre

Oddelek: Programiranje
111107 (786) PecenkA
»

[Java]Vprašanja

Oddelek: Programiranje
242030 (1498) Bela01
»

[NALOGA][Java] Težave pri pisanju slikarja

Oddelek: Programiranje
202145 (1787) l0g1t3ch
»

Programiranje "Šah-a" v Javi

Oddelek: Programiranje
264094 (3610) OwcA

Več podobnih tem