0

enter image description hereI have a JFrame(jf) and in that window I got three JPanels. I have graphics in that JPanels. I want to repaint this graphics when i press right arrow on keyboard. I have added a keyListener to the JFrame. addKeyListener(this) -> JFrame implements KeyListener.

    if (arg0.getKeyCode() == KeyEvent.VK_RIGHT){
        start = System.currentTimeMillis();
        l.czas.addMinuty(1);
        aktualizuj();
    }

In every Panel I call repaint, but the time between this repaint will be called and pressing right arrow is long. When i press many times right keys in the same time the program will freeze and then skip some steps(and graphics between). I measured the time between HITTING AN ARROW and Calling for example string which represents time. Places where there is 0 time are moments when i pressed key many times. Please help me.

Paint component called  1   times
Before superPaintComponent      1734
After superPaintComponent       1734
Before drawing Time     1781
Paint component called  2   times
Before superPaintComponent      2953
After superPaintComponent       2953
Before drawing Time     2953
Paint component called  3   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
Paint component called  4   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
Paint component called  5   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     16
rakowiecka.PNG
Paint component called  6   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
Paint component called  7   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
Paint component called  8   times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     16
placuniilubelskiej.PNG
Paint component called  9   times
Before superPaintComponent      15
After superPaintComponent       15
Before drawing Time     15
Paint component called  10  times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
Paint component called  11  times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
placzbawiciela.PNG
Paint component called  12  times
Before superPaintComponent      0
After superPaintComponent       0
Before drawing Time     0
**IT GOES ON...................**

public void aktualizuj(int nrPrzystanku){
        this.nrPrzystanku = nrPrzystanku;   
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        NR++;
        System.out.println("Paint component called\t" + NR + "\ttimes");
        System.out.println("Before superPaintComponent\t\t" + (System.currentTimeMillis() - GlowneOkno.start));
        super.paintComponent(g);
        System.out.println("After superPaintComponent\t\t" + (System.currentTimeMillis() - GlowneOkno.start));
        int Height = (int) d.getHeight(), Width = (int) d.getWidth();
    //  System.out.println("PAINT W InfoLiniaPanel");
        Font f = new Font(Font.SANS_SERIF,Font.BOLD, (4 *Height/10));
        g.setFont(f);
    //  System.out.println(Height);
        //rysowanie numeru linii
        g.drawString(linia.nr + "", Width/10, Height/3);
        //rysowanie czasu
        Font f1 = new Font(Font.SANS_SERIF,Font.BOLD, 2 * Height/18);
        g.setFont(f1);
        System.out.println("Before drawing Time\t\t" + (System.currentTimeMillis() - GlowneOkno.start));
        g.drawString(linia.czas +" ", Width/10 +  g.getFontMetrics(f).stringWidth(linia.nr+"") + Width/10, Height/3);
        //kierunek
    //  System.out.println(linia.kurs.get(linia.kurs.size() -1 ).kierunek);
        g.setFont( new Font(Font.SANS_SERIF,Font.BOLD,1 *Height/20));
        g.drawString(linia.kurs.get(linia.kurs.size() -1 ).kierunek + "",
                 Width/10 + g.getFontMetrics(f).stringWidth(linia.nr+"") + Width/10,
                 Height/3 - g.getFontMetrics(f1).getAscent() /*g.getFontMetrics(f1).getHeight()*/ );
    //      System.out.println(g.getFontMetrics(f1).getHeight());
        //nastepny przystanek
    //  System.out.println(linia.kurs.get(nrPrzystanku)); //TRZEBA ZMIENIC NA JAKIS INDEKS ZEBY SZLA SYMULKACJA!!!!!!
        //NAJLEPIEJ DAC POLE OBECNY PRZYSTANEK W KLASIE LINIA
        g.drawString("Następny przystanek:" , Width/10, Height/3 + g.getFontMetrics().getHeight() + Height/10);
        g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,1 *Height/18));

        if( nrPrzystanku +1 < Linia.trasa.length)
            g.drawString(linia.kurs.get(nrPrzystanku + 1).nazwa+"", Width/10, Height/3 + g.getFontMetrics().getHeight()*12/6 + Height/10);
        else
            g.drawString("Ostatni postój", Width/10, Height/3 + g.getFontMetrics().getHeight()*12/6 + Height/10);
    }
Yoda
  • 17,363
  • 67
  • 204
  • 344

2 Answers2

0

I wrote up a REALLY quick test. It draws a large image (650x975) and paints some text (the time).

I tried to think of some of the time most time consuming actions I could do in a short time, so drawing an image and painting an transparent component are the two best I could come up with...

It produces the following output

Sample images

(not to scale).

I basically added a "right key" action to the image pane and sent a repaint request through when the key was pressed..

Which outputs this...

Update
[ImagePane] Time since paint request: 0:0:0.49
[TimePane] Time since paint request: 0:0:0.58
Update
[ImagePane] Time since paint request: 0:0:0.0
[TimePane] Time since paint request: 0:0:0.1
Update
.
.
.

Basically:

  • Update is printed from the action event of the keystroke.
  • ImagePane is dumped at the end of the paintComponent method of the ImagePane
  • TimePane is dumped at the end of the paintComponent method of the TimePane

Durations are calculated from the time the action event occurs, ie before anything else

From my timings, I can't see a massive problem, in fact I could press the right key several times between time updates

This is the test code...

The frame:

public class TestFrame extends JFrame {

    public TestFrame() {

        setLayout(new BorderLayout());
        ImagePane imagePane = new ImagePane();
        imagePane.setLayout(new BorderLayout());
        imagePane.add(new TimePane());
        imagePane.setFocusable(true);

        add(imagePane);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        InputMap im = imagePane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        ActionMap am = imagePane.getActionMap();
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "Right");
        am.put("Right", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println("Update");

                Test.isTesting = true;
                Test.startTime = new DateTime();

                invalidate();
                repaint();

            }

        });

        imagePane.requestFocusInWindow();

    }

    public static void main(String[] args) {
        TestFrame jf = new TestFrame();

    }
}

The ImagePane...

public class ImagePane extends JPanel {

    private BufferedImage background;


    public ImagePane() {

        try {
            background = ImageIO.read(getClass().getResource("/1246.jpg"));
        } catch (IOException ex) {

            ex.printStackTrace();

        }

    }

    @Override
    public Dimension getPreferredSize() {

        return new Dimension(background.getWidth(), background.getHeight());

    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        int width = getWidth() - 1;
        int height = getHeight() - 1;

        int x = (width - background.getWidth()) / 2;
        int y = (height - background.getHeight()) / 2;

        g2d.drawImage(background, x, y, this);

        if (Test.isTesting) {

            DateTime endTime = new DateTime();
            Duration duration = new Duration(Test.startTime, endTime);

            System.out.println("[ImagePane] Time since paint request: " + Test.toString(duration));

        }

    }

}

The TimePane...

public class TimePane extends JPanel {

    public TimePane() {

        setOpaque(false);

    }

    @Override
    public Dimension getPreferredSize() {

        FontMetrics fm = getFontMetrics(getFont());
        String text = DateFormat.getTimeInstance().format(new Date());

        return new Dimension(fm.stringWidth(text), fm.getHeight());
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        FontMetrics fm = g2d.getFontMetrics();

        String text = DateFormat.getTimeInstance().format(new Date());

        int width = getWidth() - 1;
        int height = getHeight() - 1;

        int x = (width - fm.stringWidth(text)) / 2;
        int y = ((height - fm.getHeight()) / 2) + fm.getAscent();

        g2d.setColor(Color.WHITE);
        g2d.drawString(text, x, y);

        if (Test.isTesting) {

            DateTime endTime = new DateTime();
            Duration duration = new Duration(Test.startTime, endTime);

            System.out.println("[TimePane] Time since paint request: " + Test.toString(duration));

        }

    }
}

And the Test utility class

public class Test {

    public static final PeriodFormatter PERIOD_FORMATER = new PeriodFormatterBuilder().printZeroAlways().
                    appendHours().appendSeparator(":").
                    appendMinutes().appendSeparator(":").
                    appendSeconds().appendSeparator(".").
                    appendMillis().toFormatter();

    public static DateTime startTime;
    public static boolean isTesting = false;

    static String toString(Duration duration) {

        return duration == null ? "[invalid duration]" : duration.toPeriod().toString(PERIOD_FORMATER);

    }
}

Now, I use Joda Time to calculate the duration (sorry, I had ready made code for it)

Obviously, you'll need to get your own image.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • But still I don't know why my (NOT IMAGE CONATINING LEFT PANEL) is updating so slow(even if I turn off those 2 left). I added invalidate() at the begginning of update()->aktualizuj() and paintComponent(g) methods. – Yoda Aug 18 '12 at 05:49
  • Sorry, been racking my brains. The previous example you had was missing some code which was allowing the example to run without issue. I'd start by diagnosing that part of the code (start by commenting out the part you left out of the example) – MadProgrammer Aug 18 '12 at 10:25
0

Firstly
try to comment every unnecessary System.out.println or any unnecessary statement which performs any console printing as such statements also slows down the application, I have encountered such situations where printing statements raise application response time.

Secondly
try worker threads and swing worker

Harmeet Singh
  • 2,555
  • 18
  • 21