0

I'm drawing a JTextFields matrix (15 X 15) on JFrame's container (null layout). The problem is that I see each JTextField being drawn one by one, slowly. And the JTextFields only is shown if I put at least one character in its (setText). How to speed up the code for everyone to be displayed at once and be shown without put character ?

cell = new Cell[lin][col];

    for (int l = 0; l < lin; l++) {
        for (int c = 0; c < col; c++) {
            cell[l][c] = new Cell();
            cell[l][c].setBounds(iniLeftTop.getX(), iniLeftTop.getY(), sideCell, sideCell);
            cell[l][c].setText("A"); // without this line JTextField is not shown
            container.add(celula[l][c]);
            iniLeftTop.x = iniLeftTop.x + sideCell + 1;
        }
        iniLeftTop.x = iniLeft;
        iniLeftTop.y = iniLeftTop.y + sideCell + 1;
    }

Thanks a lot for any help.

  • 1
    possible duplicate http://stackoverflow.com/questions/1097366/java-swing-revalidate-vs-repaint – WalterM Oct 09 '15 at 16:02
  • 2
    `I'm drawing a JTextFields matrix (15 X 15) on JFrame's container (null layout).` - why would you use a null layout??? Swing was designed to be used with layout managers.. Just use a [GridLayout](http://docs.oracle.com/javase/tutorial/uiswing/layout/grid.html) – camickr Oct 09 '15 at 16:14
  • 2
    The comment "without this line JTextField is not shown" is suspicious. Where exactly does this code reside? 225 text fields aren't that many, I have seen scroll panes containing 30k UI elements and it was still *useable*. Also, Swing is double buffered, so you should *never* see the elements being drawn "one by one". I suspect you do something weird, like calling that piece of code many times... show a self contained example demonstrating the problem. – Durandal Oct 09 '15 at 17:06
  • I'm not using layout managers because JTextFields should always be the same size (crosswords game) and the amount of TextFields (rows and columns) is in charge of user (he can create the size of grid he wants). And the validate() and repaint() makes the code run a bit faster. What about Runnable? Any idea ? – Adalberto José Brasaca Oct 09 '15 at 17:33
  • @user3151927, `JTextFields should always be the same size` - you create the text field using `new JTextField(1)` and the text field will be sized to fit one character. Then you add all the text fields to a panel using a GridLayout. Then you add this panel to the NORTH of the frame and pack the frame and all the text fields will be the proper size. Learn to use layout managers effectively to save time and create fewer problems. `makes the code run a bit faster.` - using a null layout will not make the code run faster. – camickr Oct 09 '15 at 19:03
  • Why not use a 15x15 JTable? – Bon Oct 11 '15 at 03:53

2 Answers2

0

I created the following GUI. It appeared in less than 300 milliseconds.

Crossword Puzzle

The whole example was 66 lines of code. I created a model class to hold the characters of the crossword puzzle and a GUI class to display the 225 JTextFields.

Here's the runnable, testable code.

package com.ggl.testing;

import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class JTextFieldTest implements Runnable {

    private GridModel model;

    private JFrame frame;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JTextFieldTest());
    }

    public JTextFieldTest() {
        this.model = new GridModel();
    }

    @Override
    public void run() {
        frame = new JFrame("Crossword Puzzle");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createGrid());

        frame.pack();
        frame.setVisible(true);
    }

    private JPanel createGrid() {
        JPanel panel = new JPanel();
        char[][] grid = model.getGrid();
        panel.setLayout(new GridLayout(0, grid.length));

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                JTextField field = new JTextField(2);
                field.setText(Character.toString(grid[i][j]));
                panel.add(field);
            }
        }

        return panel;
    }

    public class GridModel {

        private char[][] grid;

        public GridModel() {
            this.grid = new char[15][15];
        }

        public char[][] getGrid() {
            return grid;
        }

    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • Gilbert... You use the Runnable interface inside "public static void main" (on program load). So when the window appears the grid is already there. I have to draw the grid later, through the parameters of another window. – Adalberto José Brasaca Oct 09 '15 at 18:08
  • @user3151927: As you've been asked, provide code that's a runnable example of your problem. I drew 225 JTextFields in less than 300 milliseconds, which was your title question. – Gilbert Le Blanc Oct 09 '15 at 18:46
0

The code you posted most likely executes very quickly (you could measure it by comparing System.currentTimeMillis() at the start and the end of your code block).

If the measured time is low, your GUI is probably not updating for these reasons:

  • The code should be executed on the Swing thread, use SwingUtilites.invokeLater()
  • revalidate() and repaint() should be called after your code block (and also on the swing thread)
Chris K
  • 1,703
  • 1
  • 14
  • 26
  • Exactly where I should put the invokeLater method together with revalidate() and repaint() ? I only saw this method inside "private static void main". How to use it outside this method ? Thank you. – Adalberto José Brasaca Oct 09 '15 at 23:07