Avatar billede ng-km Nybegynder
07. marts 2003 - 12:14 Der er 13 kommentarer og
1 løsning

Flickerfree JPanel ???

Jeg har lavet et overvågningsprogram med input fra parallelporten, som skal gøres grafisk for brugeren.

Jeg har et JPanel hvorpå der er tegnet et billede (test.gif) og en række linier (ca 5000 korte linier). Disse ting er statiske.

Så har jeg, på samme JPanel, en række linier forholdsvis få (50-100 stk også korte) der er dynamiske, som skal have ændret farve ca 5 gange i sekundet alt efter overågningens input. Overvågningen kører i sin egen tråd.

Hvordan får jeg lavet en grafisk fremstilling der ikke "blinker" ved hver opdatering.

Jeg har for en god ordens skyld placeret hele JPanel-baggrunden i en JScrollPane, da billedet kan skaleres/zoomes.

Jeg har forsøgt at lade den dynamiske del køre i sit eget JPanel og lægge det oven på det statiske, så jeg kun behøver at at lave opdateringen i det dynamiske JPanel. Men jeg kan ikke se det statiske panel igennem det dynamiske(eller omvendt), heller ikke med setOpaque(true). Er der en anden lignende løsning?

Følgende kode viser meget simplificeret min problemstilling. Det startes ved at køre musen ind over GUI'en.

Kan nogen ændre i min kode så der opnås en flickerfree GUI?


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


public class TestJPanel extends JFrame
{
    Baggrund baggrund;
    Random r = new Random();
    Traad traad;
    Vector statiskeStreger;
    Vector dynamiskeStreger;
    boolean startet = false;

    public TestJPanel()
  {
    setSize(800,620);
    setTitle("TestJPanel");

    Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screenSize = toolkit.getScreenSize();
    Dimension selfBounds = getSize();
    setLocation((screenSize.width - selfBounds.width) / 2, (screenSize.height - selfBounds.height) / 2);

        baggrund = new Baggrund();
        baggrund.setLocation(0,0);
        baggrund.addMouseListener(new Mus());
    getContentPane().add(baggrund);
       
        traad = new Traad();
        statiskeStreger = new Vector();
       
        for(int i=0; i<5000; ++i)
            statiskeStreger.add(new Rectangle(randomNumber(20,760), randomNumber(20,560), randomNumber(20,760), randomNumber(20,560)));
           
        dynamiskeStreger = new Vector();
       
        for(int i=0; i<100; ++i)
            dynamiskeStreger.add(new Rectangle(randomNumber(20,760), randomNumber(20,560), randomNumber(20,760), randomNumber(20,560)));
           
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  }
   
    public int randomNumber(int start, int slut)
    {
        if(start > slut)
            return - 1;

        return r.nextInt(slut-start) + start;
    }
   
    //inner class der tegnes på
    public class Baggrund    extends JPanel implements ImageObserver
    {
        public Baggrund()
        {
            super(true);
            setSize(800,600);
        }
       
        public void paint(Graphics g)
        {
            super.paint(g);
           
            Graphics2D g2 = (Graphics2D)g.create();
           
            g2.setColor(new Color(255,255,255));
            g2.fillRect(5,5,780,580);
            g2.setColor(new Color(0,0,0));

            g2.drawLine(10,10, 780,10);
            g2.drawLine(10,10, 10,580);
            g2.drawLine(780,10, 780,580);
            g2.drawLine(10,580, 780,580);

            ImageIcon image = new ImageIcon("test.gif");
            g2.drawImage(image.getImage(),20, 20, 700, 500, this);

            for(int i=0; i<statiskeStreger.size(); ++i)
            {
                Rectangle rec = (Rectangle)statiskeStreger.get(i);   
                g2.drawLine(rec.x, rec.y, rec.width, rec.height);
            }

            for(int i=0; i<dynamiskeStreger.size(); ++i)
            {
                g2.setColor(new Color(randomNumber(0,255),randomNumber(0,255),randomNumber(0,255)));
                Rectangle rec = (Rectangle)dynamiskeStreger.get(i);   
                g2.drawLine(rec.x, rec.y, rec.width, rec.height);
            }
        }

        public boolean imageUpdate(java.awt.Image billede, int nr2, int nr3, int nr4, int nr5, int nr6)
        {
            return false;
        }
    }
   
    //inner class der starter tegningen
    public class Mus extends MouseAdapter
    {
        public void mouseEntered(MouseEvent e)
        {
            if(!startet)//for at undgå exceptions efter start
                traad.start();
        }
    }
       
    //inner class der holder liv i tegningen
    public class Traad extends Thread
    {
        public void run()
        {
            startet = true;
            while(true)
            {
                try
                {
                    baggrund.update(baggrund.getGraphics());
                    sleep(200);
                }
                catch(InterruptedException ie)
                {}
            }
        }
    }
   
    public static void main(String args[])
    {
        TestJPanel testJPanel = new TestJPanel();
        testJPanel.setVisible(true);
    }
}
Avatar billede repsak Nybegynder
08. marts 2003 - 12:02 #1
Generelt er java jo ikke voldsomt hurtig til at optegne grafik ... kan se at du har prøvet med doublebuffering...

Dette bør dog løse dit problem:
//        public void paint(Graphics g){
//            super.paint(g);

          public void paintComponent(Graphics g){
              super.paintComponent(g);
.... resten af din kode

Swing er opbygget op en lidt anden måde end awt så derfor skal du bruge paintComponent istedet for paint!

Har dog også lige disse kommentere: (bare lidt optimering :)

1: JPanel implementerer selv ImageObserver (eller rettere en af JPanels superklasser) så når du extender JPanel behøver du ikke at implemntere interfacet. Så slipper du opså for at definere imageUpdate(...)
2: Der er ingen grund til at kalde super(true) i Baggrunds konstruktøren. super() udfører det samme. (med doublebuffering = true)
Avatar billede ng-km Nybegynder
08. marts 2003 - 16:12 #2
repsak -> Det er helt klart det rette spor, og giver et rigtigt flot billede (så længe det varer). MEN ved at benytte paintComponent(Graphics g) fryser min pc hele tiden efter kort tid. Det er som om al RAM'en bliver suget ud og blokeret, for den eneste løsning er at "hive stikket ud" af min computer 1.1 Ghz med 256 Mb RAM. Jeg har brugt den kode der i mit spørgsmål og ændret til det du foreslog. Hvad gør jeg forkert ?
Avatar billede repsak Nybegynder
08. marts 2003 - 18:46 #3
Hmm det lyder underligt... Java kører jo på en virtuel maskine, og en fordel herved burde jo være at hele comp ikke går ned f.eks ved 'out of memory'. Hvor lang tid går der før at den fryser?
Avatar billede ng-km Nybegynder
08. marts 2003 - 19:53 #4
Der går ca 10-15 sek, men jeg ved jo ikke om det er pga. memory out, men den går som sagt helt i baglås ikke engang ctrl-alt-del virker. Har du prøvet koden selv, den er lige til at compile og køre.
Avatar billede repsak Nybegynder
08. marts 2003 - 20:15 #5
Min comp fryser ikke. Den sletter pludselig de farvede streger, men jeg kender ikke koden nok til at vide om den skal gøre det. Jeg kan bare lukke JVM ved at 'krydse' dos-vinduet... Er din comp på opium...? Eller er min på speed ;-)
Avatar billede ng-km Nybegynder
09. marts 2003 - 12:16 #6
Det er ikke meningen at stregerne skal slettes, - de forsvinder ikke hvis du bruger paint(Graphics g), så et eller andet går der galt med paintComponent(..). Jeg bruger iøvrigt Win98.
Avatar billede repsak Nybegynder
09. marts 2003 - 12:55 #7
Jeg kører også Win98. Det lyder helt galt. Jeg ligger inde med undervisningsmaterialt fra Sun som beskriver den framgangsmåde som jeg har beskrevet... Virker det så hvis du skriver
pv paint(Graphics g){
super.paintComponent(g)
...
}
?
Avatar billede ng-km Nybegynder
09. marts 2003 - 13:47 #8
Hvis jeg følger dit sidste råd, kører det stabilt, men så er vi tilbage ved en blinkende GUI igen.
Avatar billede repsak Nybegynder
09. marts 2003 - 14:12 #9
hmm så er jeg bange for at jeg må melde pas :( Sorry
Avatar billede ng-km Nybegynder
09. marts 2003 - 18:19 #10
Mange tak for hjælpen alligevel :-)
Avatar billede ng-km Nybegynder
20. marts 2003 - 21:25 #11
Jeg lukker...
Avatar billede repsak Nybegynder
21. marts 2003 - 19:05 #12
meget cool måde at få 100 points på...
Avatar billede ng-km Nybegynder
22. marts 2003 - 10:12 #13
repsak >>
Jeg har overhovedet ingen intentioner om at score billige point, men da ingen kan løse mit problem mener jeg ikke at spørgsmålet bare skal stå åbent. Hvordan skal jeg ellers lukke spørgsmålet?

Jeg vil egentligt gerne give dig halvdelen af pointene, for selv om problemet ikke er løst, har du lært mig nogle andre ting alligevel. Men jeg har ingen anelse om hvordan man deler point til flere svar.

Hvis du vil have 50 point opretter jeg gerne et fiktivt spørgsmål du kan svare på. Jeg samler ikke point, jeg har hvad jeg skal bruge, og det sidste jeg ønsker er at snyde nogen der frivilligt hjælper. Jeg vil bare ikke give point for svar der ikke løser mit problem.

Jeg kan mærke at du føler dig lidt snydt, og tro mig, det har på ingen måde været meningen, så jeg håber at du tager imod de 50 point og måske bibeholder lysten til at hjælpe mig i fremtiden.
Avatar billede repsak Nybegynder
22. marts 2003 - 11:20 #14
1. Jeg er da glad for at have lært dig nogle ting.
2. Lad blot være med at oprette fiktive spørgsmål. Jeg vil da gerne hjælpe dig en anden gang hvis jeg kan - også uden de 50 points.
3. Og nej jeg føler mig ikke specielt snydt. Jeg er ikke på eksperten for at opnå mange points. Se blot på statistikken.. Jeg har ikke så mange points og jeg spiller ikke for "at vinde".
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester