我尝试在 Swing 中绘制一个图表,其中在大量嵌套的 JPanel 中包含大量(数千个)JLabels,所有 JPanel 都具有不同的布局。
我使整个图可缩放,缩放一步时我在图中的所有组件上使用 setPreferedSize() 。
它也是交互式的,通过单击其中一个 JLabel,程序会放大该 JLabel。每个 JLabel 都有一个工具提示,并将鼠标悬停在其上时会改变颜色。
问题是当图表太大时,缩放速度会很慢。有一个 for 循环必须遍历图中的所有 JComponent 并更改它们的首选大小。然后我必须在 JComponents 父级上调用 .revalidate() 。
所以我的问题是:
我是否应该只使用一个具有 null 布局的 JPanel,并在所有 JLabels 上使用 setBounds() 来定位和放大它们,而不是使用具有不同布局的嵌套 JPanel?电脑会更轻吗?
我应该使用其他 GUI 吗?它必须支持以下内容:
- 绘制带有工具提示的矩形标签,可以添加鼠标监听器。
- 可缩放,可以缩放整个图表
- 可以在图表中绘制文本。
- 可滚动,可以将图表添加到 JScrollPane(放大时很重要)
最佳答案
您可以忘记各个 JLabels,而只需在主 JPanel 的 paintComponent
方法中绘制文本项。
您可以使用drawString
来绘制文本项。
此外,您可以保留“缩放级别”值,并根据该缩放级别在不同的位置/大小绘制字符串。
如果我是你,我会敲一个简单的例子来绘制几千个字符串,看看在你的目标规范客户端机器上是否足够快。
编辑:类似这样的:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
/**
* TestPaintComponentZooming
*
* @author davidf
*/
public class TestPaintComponentZooming {
private JFrame f;
private JPanel panel;
private double zoom = 1.0;
public static void main(String[] args) {
TestPaintComponentZooming t = new TestPaintComponentZooming();
t.init();
}
public TestPaintComponentZooming() {
}
public void init() {
JButton b = new JButton();
b.setBackground(Color.red);
b.setBorder(new LineBorder(Color.black, 2));
b.setPreferredSize(new Dimension(600, 10));
panel = new _JPanel();
panel.add(b);
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel, "Center");
f.add(getCheckBoxPanel(), "South");
f.setLocation(200, 200);
f.setSize(400, 400);
f.validate();
f.setVisible(true);
}
private JPanel getCheckBoxPanel() {
JButton zoomIn = new JButton("Zoom in");
zoomIn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
zoomAndRepaint(0.1);
}
});
JButton zoomOut = new JButton("Zoom out");
zoomOut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
zoomAndRepaint(-0.1);
}
});
JPanel panel2 = new JPanel();
panel2.add(zoomIn);
panel2.add(zoomOut);
return panel2;
}
/**
* zoomAndRepaint
*/
protected void zoomAndRepaint(double d) {
zoom += d;
f.repaint();
}
private class _JPanel extends JPanel {
public _JPanel() {
super(null);
}
/**
* @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("Arial", Font.PLAIN, (int) (zoom * 10 + 2)));
for (int x=0; x < 100; x++) {
for (int y=0; y < 100; y++) {
g.drawString("Hello " + x + "," + y, (int) (x * 60 * zoom), (int) (y * 10 * zoom));
}
}
}
}
}
关于用于绘制大型、可缩放、交互式图表的 Java GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11536213/