【问题标题】:Java swing why when i draw a lot of strings in a panel that is inside a JScrollpane they overlap?Java swing 为什么当我在 JScrollpane 内的面板中绘制大量字符串时,它们会重叠?
【发布时间】:2020-04-29 03:16:41
【问题描述】:


我是java swing的新手。
我想画很多里面有数字的矩形。因此,我将扩展 JPanel 的面板放在 JScrollpane 中。
我注意到,如果我有几个矩形,它工作得很好,但如果我画了很多矩形,字符串会相互重叠(见图)。有人可以帮我解决它吗?
谢谢你。

代码:

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:我不明白为什么会有这么多字符串。每个矩形应该有一个。像这样:

【问题讨论】:

  • “我想画很多里面有数字的矩形”我会在JLabel中显示每个数字,添加一个LineBorder,然后将它们放在JPanelGridLayout 中。为什么不这样做?自定义绘画有什么原因吗?
  • 我害怕分配所有 JLabel 所需的内存量。代码应该以大数字运行。
  • 类名应该以大写字符开头。如果事情没有正确绘制,那么你的绘制逻辑是错误的。为什么不从合理数量的字符串开始进行调试。
  • “我害怕内存量” 我建议的方法适用于 just fine 处理 50000 个数字。不过,它确实需要一些时间才能进入屏幕。如果这是一个问题,请使用JTable 来显示它们。还要研究:1)过早的优化,2)What is the XY problem?
  • @camickr 我做了并且它有效,我有高价值的问题。自行尝试,将 for 循环中的 50000 更改为较小的数字,例如 100 或 10。

标签: java swing paint


【解决方案1】:

JTable 将快速轻松地处理和显示 50 个 百万 个数字(使用正确的渲染)。请注意,用作单元格渲染器的JLabel 是用于绘制每个表格单元格的单个组件。

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);
    }
}

【讨论】:

    【解决方案2】:

    您可以使用JLabel 为您绘制。您甚至不必为每个字符串创建单独的标签,而是创建一个并将其用作“画家”,即在标签上调用 #setBounds,然后让它每次都为您绘制字符串。

    class MyPanel extends JPanel {
        private final JLabel stringPainter;
    
        MyPanel() {
            stringPainter = new JLabel();
            stringPainter.setOpaque(false);
            stringPainter.setHorizontalTextPosition(JLabel.CENTER);
            stringPainter.setVerticalTextPosition(JLabel.CENTER);
        }
    
        private void drawCenteredStringInRect(Graphics g, String text, Rectangle rect) {
            Graphics cg = g.create();
            stringPainter.setBounds(rect);
            stringPainter.setText(text);
            stringPainter.paint(cg);
            cg.dispose();
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int hPad = 5;
            int vPad = 5;
            Rectangle rect = new Rectangle(hPad, hPad, 80, 20);
            String num = "2147483648";
            for (int i = 0; i <= 50000; ++i) {
                if (i % 10 == 0) {
                    rect.x = hPad;
                    rect.y += rect.height + vPad;
                }
                rect.x += rect.width + hPad;
                drawCenteredStringInRect(g, num, rect);
            }
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多