目标是在 JPanel 上绘制一堆圆圈(每个圆圈都是一个单独的 JComponent 实例),并且能够在任何方向上滚动足够远以查看所有圆圈。
这是“主要”代码:
JFrame frame = new JFrame();
JPanel panel = new JPanel(new BorderLayout());
panel.add(new Circle(-100, 0, 200));
panel.add(new Circle(-25, 0, 650));
JScrollPane scrollPane = new JScrollPane (panel);
frame.add(scrollPane);
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
这是 Circle 类:
public class Circle extends JComponent {
private int x;
private int y;
private int width;
public Circle(int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(this.x, this.y, this.width, this.width);
}
}
有几个我似乎无法解决的问题:
希望这是可以理解的,我对 Swing 非常陌生。任何想法都将受到高度赞赏!
诊断: 第一个问题是没有考虑到尺寸 您正在使用的屏幕。 第二个问题是您将 JScrollPane 分配给 Frame 而不是 JPanel,JPanel 必须滚动才能显示绘制的对象。 第三个问题是使用BorderLayout,它限制你只能表示中心的对象,这一点已被一位同事在他的评论中提到。虽然这可能是最不严重的。
为什么要考虑屏幕尺寸? 因为你必须想象你有一张纸或画布,你想在上面画一个圆圈,所述布的尺寸为 1x1 米,而你的圆圈的半径为 0.75 米,这将得到 1.50 米的直径,这显然是它不会完全适合纸张或画布。
正如您所解释的,您是新手,我建议将对象(JFrame、JPanel 和 Circle)分成不同的类,以便您更轻松地识别任何问题、使用元素的值并了解其中每一个如何他们有效。 。 这种类的分离不是强制性的,但强烈建议这样做,尤其是当您的项目不断增长时。请放心,您不想遇到执行很多操作(包括让您感到困惑)的庞大类。
考虑到这一点,我写了一个解决方案,希望对你有帮助:
主课
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import circlepanel.CirclePanel;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Circles in a JPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CirclePanel circlePanel = new CirclePanel();
JScrollPane scrollPane = new JScrollPane(circlePanel);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
圆形面板类
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import circle.Circle;
public class CirclePanel extends JPanel {
private static final long serialVersionUID = 6595277960964126231L;
private List<Circle> circles;
public CirclePanel() {
circles = new ArrayList<>();
// Examples of circles
circles.add(new Circle(50, 50, 30));
circles.add(new Circle(150, 100, 20));
circles.add(new Circle(800, 800, 650));
/*
// Calculate panel size based on circles and window size
int maxX = circles.stream().mapToInt(c -> c.getX() + c.getRadius()).max().orElse(0);
int maxY = circles.stream().mapToInt(c -> c.getY() + c.getRadius()).max().orElse(0);
int preferredWidth = Math.max(maxX + 10, 1800); // Adjust the width to 1880 depending on the desired window size
int preferredHeight = Math.max(maxY + 10, 1400); // Adjust the height to 1400 according to the desired window size
setPreferredSize(new Dimension(preferredWidth, preferredHeight));
*/
// Calculate panel size based on circles and window size
int maxX = 0;
int maxY = 0;
for (Circle circle : circles) {
maxX = Math.max(maxX, circle.getX() + circle.getRadius());
maxY = Math.max(maxY, circle.getY() + circle.getRadius());
}
int preferredWidth = Math.max(maxX + 10, 1880); // Adjust the width to 1880 depending on the desired window size
int preferredHeight = Math.max(maxY + 10, 1400); // Adjust the height to 1400 according to the desired window size
setPreferredSize(new Dimension(preferredWidth, preferredHeight));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw the circles
for (Circle circle : circles) {
g.drawOval(circle.getX() - circle.getRadius(), circle.getY() - circle.getRadius(),
2 * circle.getRadius(), 2 * circle.getRadius());
g.setColor(Color.RED);
g.fillOval(circle.getX() - circle.getRadius(), circle.getY() - circle.getRadius(), 2 * circle.getRadius(), 2 * circle.getRadius());
}
}
}
圆班
public class Circle {
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getRadius() {
return radius;
}
}
在 CirclePanel 类中,有一部分注释代码,被紧随其后的代码替换。 注释代码正在通过更高效的 Lambda 表达式查找所有示例圆的最大半径、x 轴和 Y 轴尺寸。下面的代码有些更传统,使用 FOR 迭代包含定义为示例的圆形对象的 ArrayList。
希望对你有帮助,作为一个提示,请查阅你所使用的Java版本的API,以对你要使用的组件有更完整的了解,如果可能的话,在你的空闲时间查阅它,将会有很大帮助。扩大你的视野。 .
最后,不要忘记最大化 JFrame,以便出现两个滚动面板。