Search code examples
javaswingpaint

Java swing why when i draw a lot of strings in a panel that is inside a JScrollpane they overlap?



I'm new in java swing.
I want to do draw a lot of rectangles that inside have a number. Because of this i put the panel that extends JPanel in a JScrollpane.
I noticed that if i have few rectangles it works pretty well but if i draw a lot of rectangles the strings overlap each other (see the image). Can someone help me to fix it?.
Thank you.

enter image description here Code:

import java.util.*; 
import java.io.*;
import javax.swing.*;
import java.awt.*;
class drawing extends JFrame
{
    private myPanel gg=new myPanel();
    drawing(){
        setLayout(new BorderLayout());
        add(new JLabel("HELLO"), "North");
        add(new JScrollPane(gg), "Center");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setExtendedState(MAXIMIZED_BOTH);
    }
    public static void main(String argv[]){
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                drawing prova=new drawing();
                prova.setVisible(true);
            }
        });
        return;
    }
}
class myPanel extends JPanel
{
    private void drawCenteredStringInRect(Graphics2D g2d, String text, int base, int height, int xRect, int yRect){
        FontMetrics fm = g2d.getFontMetrics();
        int x=xRect+((base-fm.stringWidth(text))/2);
        int y=yRect+(((height-fm.getHeight())/2)+ fm.getAscent());
        System.out.print(x+" "+y+"\n");
        g2d.drawString(text, x, y); //(string, x, y)
        return;
    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d=(Graphics2D)g;
        int base=80, height=20, xRect=5, yRect=5;
        String num="2147483648";
        //x1 y1, x2 y2
        for(int i=0;i<=50000;++i){
            if(i%10==0){
                xRect=5;
                yRect+=height+10;
            }
            xRect+=base+5;
            g2d.drawRect(xRect, yRect, base, height); //(x, y, base, height)
            drawCenteredStringInRect(g2d, Integer.toString(i), base, height, xRect, yRect);        
        }
        return;
    }
    public Dimension getPreferredSize() {
            return new Dimension(500, 10000000);
    }
}

EDIT_1: i don't understand why there are so many strings. There should be one per rectangle. Like so:
enter image description here


Solution

  • A JTable will handle & display 50 million numbers quickly and easily (with correct rendering). Note that the JLabel used as the cell renderer is a single component used to paint every table cell.

    enter image description here

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import javax.swing.border.*;
    
    public class FiftyMillionNumbersInTable {
    
        private JComponent ui = null;
    
        FiftyMillionNumbersInTable() {
            initUI();
        }
    
        public final void initUI() {
            if (ui!=null) return;
    
            ui = new JPanel(new BorderLayout(4,4));
            ui.setBorder(new EmptyBorder(4,4,4,4));
            int maxNum = 5000000;
            int colNum = 10;
            Integer[] cols = {1,2,3,4,5,6,7,8,9,10};
            Integer[][] numbers = new Integer[maxNum/colNum][colNum];
            for (int ii=0; ii<maxNum; ii++) {
                numbers[ii/colNum][(ii%colNum)] = ii;
            }
            JTable table = new JTable(numbers, cols);
            table.setDefaultRenderer(Object.class, new CenterCellRenderer());
            ui.add(new JScrollPane(table));
        }
    
        class CenterCellRenderer extends DefaultTableCellRenderer {
    
            @Override
            public Component getTableCellRendererComponent(
                    JTable table, Object value, 
                    boolean isSelected, boolean hasFocus, 
                    int row, int column) {
                Component c = super.getTableCellRendererComponent(table, value, 
                        isSelected, hasFocus, row, column);
                JLabel l = (JLabel)c;
                l.setHorizontalAlignment(SwingConstants.CENTER);
                return l;
            }
        }
    
        public JComponent getUI() {
            return ui;
        }
    
        public static void main(String[] args) {
            Runnable r = () -> {
                FiftyMillionNumbersInTable o = new FiftyMillionNumbersInTable();
    
                JFrame f = new JFrame(o.getClass().getSimpleName());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);
    
                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());
    
                f.setVisible(true);
            };
            SwingUtilities.invokeLater(r);
        }
    }