Java 为什么当我在 JScrollpane 内的面板中绘制大量字符串时它们会重叠?
Java swing why when i draw a lot of strings in a panel that is inside a JScrollpane they overlap?
我是 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
给你画。您甚至不必为每个字符串创建一个单独的标签,而是创建一个并将其用作 "painter" 即在标签上调用 #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);
}
}
}
A JTable
将快速轻松地处理和显示 50 百万 个数字(正确呈现)。请注意,用作单元格渲染器的 JLabel
是用于绘制每个 table 单元格的单个组件。
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);
}
}
我是 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
给你画。您甚至不必为每个字符串创建一个单独的标签,而是创建一个并将其用作 "painter" 即在标签上调用 #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);
}
}
}
A JTable
将快速轻松地处理和显示 50 百万 个数字(正确呈现)。请注意,用作单元格渲染器的 JLabel
是用于绘制每个 table 单元格的单个组件。
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);
}
}