如何在 BorderLayout.SOUTH 中添加一个矩形?
How can I add a rectangle in BorderLayout.SOUTH?
我正在尝试在我的 swing 音乐播放器应用程序中添加类似 this 的内容。
我试图向 BorderLayout.SOUTH
添加一个矩形,但它从未出现在屏幕上。这是我做了什么:
public class MyDrawPanel extends JPanel {
@Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillRect(200,200,200,200);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
MyDrawPanel a = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH,a);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000,1000);
frame.setVisible(true);
}
}
我只是没有尝试 200,200,200,200,但我尝试了很多值,即使在 for 循环的帮助下,但它从未出现在屏幕上。如果我使用 CENTER
而不是 SOUTH
它就会出现。我阅读了文档以检查 fillRect
是如何工作的,但它只是说它添加了 x+width 和 y+height。 (0,0)
点是左上角。我通过向 CENTER
布局添加一个矩形来检查。我是怎么做到的?
我没有分享输出,因为它只是一个空白屏幕。
您给 fillRect
的值是错误的。前两个是左上角的坐标,相对于您正在绘制的组件;在你的例子中 MyDrawPanel
。使用您发布的代码,此绘图区域位于放置面板的容器之外。您想要做的
g.fillRect(0,0,200,200);
注意:您通常希望在添加完所有组件后调用 frame.pack()
,以便它可以自行布局。在您的情况下,这会导致 window 很小,因为系统不知道它应该有多大。您可能想添加一个方法
public Dimension getPreferredSize() {
System.out.println("getting pref size");
return new Dimension(200, 200);
}
确保它始终足够大以绘制整个矩形。
还有,你应该先打电话给frame.getContentPane().setLayout(new BorderLayout())
。您可以在不设置的情况下将其打印出来,以查看它是否不是默认设置。编辑:正如 VGR 指出的那样,文档说它实际上是一个 BorderLayout
。我无法确认是这种情况 - 它实际上是 RootLayout
。不过,这似乎表现得像 BorderLayout
。
我认为这可能会成为一个快速的小项目。这是我想出的电平表。
重要的部分是 DrawingPanel
和 LevelMeterModel
。 DrawingPanel
从 LevelMeterModel
获取信息并在 JPanel
.
上绘制条形图
LevelMeterModel
是一个整型数组,包含最低级别和最高级别。可以计算最大音量,但我假设音乐有一定的音量和频率范围。
JFrame
持有DrawingPanel
。 Swing Timer
会随机改变级别。随机数在一个小范围内,因此条形高度不会突然改变。
这是完整的可运行代码。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class LevelMeterGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new LevelMeterGUI());
}
private final DrawingPanel drawingPanel;
private final LevelMeterModel model;
public LevelMeterGUI() {
this.model = new LevelMeterModel();
this.drawingPanel = new DrawingPanel(model);
}
@Override
public void run() {
JFrame frame = new JFrame("Level Meter GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println("Frame size: " + frame.getSize());
Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.setRandomLevels();
drawingPanel.repaint();
}
});
timer.start();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int drawingWidth, drawingHeight, margin, rows;
private final Dimension barDimension;
private final LevelMeterModel model;
public DrawingPanel(LevelMeterModel model) {
this.model = model;
this.margin = 10;
this.rows = 20;
this.barDimension = new Dimension(50, 10);
int columns = model.getLevels().length;
drawingWidth = columns * barDimension.width + (columns + 1) * margin;
drawingHeight = rows * barDimension.height + (rows + 1) * margin;
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(drawingWidth, drawingHeight));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int maximum = model.getMaximumLevel();
double increment = (double) maximum / rows;
int peak = rows * 75 / 100;
int x = margin;
for (int level : model.getLevels()) {
int steps = (int) Math.round((double) level / increment);
int y = drawingHeight - margin - barDimension.height;
for (int index = 0; index < steps; index++) {
if (index < peak) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.RED);
}
g.fillRect(x, y, barDimension.width, barDimension.height);
y = y - margin - barDimension.height;
}
x += margin + barDimension.width;
}
}
}
public class LevelMeterModel {
private final int minimumLevel, maximumLevel;
private int[] levels;
private final Random random;
public LevelMeterModel() {
this.minimumLevel = 100;
this.maximumLevel = 999;
this.levels = new int[8];
this.random = new Random();
setRandomLevels();
}
public void setRandomLevels() {
for (int index = 0; index < levels.length; index++) {
levels[index] = getRandomLevel(levels[index]);
}
}
private int getRandomLevel(int level) {
if (level == 0) {
return random.nextInt(maximumLevel - minimumLevel) + minimumLevel;
} else {
int minimum = Math.max(level * 90 / 100, minimumLevel);
int maximum = Math.min(level * 110 / 100, maximumLevel);
return random.nextInt(maximum - minimum) + minimum;
}
}
public int[] getLevels() {
return levels;
}
public int getMinimumLevel() {
return minimumLevel;
}
public int getMaximumLevel() {
return maximumLevel;
}
}
}
我正在尝试在我的 swing 音乐播放器应用程序中添加类似 this 的内容。
我试图向 BorderLayout.SOUTH
添加一个矩形,但它从未出现在屏幕上。这是我做了什么:
public class MyDrawPanel extends JPanel {
@Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillRect(200,200,200,200);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
MyDrawPanel a = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH,a);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000,1000);
frame.setVisible(true);
}
}
我只是没有尝试 200,200,200,200,但我尝试了很多值,即使在 for 循环的帮助下,但它从未出现在屏幕上。如果我使用 CENTER
而不是 SOUTH
它就会出现。我阅读了文档以检查 fillRect
是如何工作的,但它只是说它添加了 x+width 和 y+height。 (0,0)
点是左上角。我通过向 CENTER
布局添加一个矩形来检查。我是怎么做到的?
我没有分享输出,因为它只是一个空白屏幕。
您给 fillRect
的值是错误的。前两个是左上角的坐标,相对于您正在绘制的组件;在你的例子中 MyDrawPanel
。使用您发布的代码,此绘图区域位于放置面板的容器之外。您想要做的
g.fillRect(0,0,200,200);
注意:您通常希望在添加完所有组件后调用 frame.pack()
,以便它可以自行布局。在您的情况下,这会导致 window 很小,因为系统不知道它应该有多大。您可能想添加一个方法
public Dimension getPreferredSize() {
System.out.println("getting pref size");
return new Dimension(200, 200);
}
确保它始终足够大以绘制整个矩形。
还有,你应该先打电话给frame.getContentPane().setLayout(new BorderLayout())
。您可以在不设置的情况下将其打印出来,以查看它是否不是默认设置。编辑:正如 VGR 指出的那样,文档说它实际上是一个 BorderLayout
。我无法确认是这种情况 - 它实际上是 RootLayout
。不过,这似乎表现得像 BorderLayout
。
我认为这可能会成为一个快速的小项目。这是我想出的电平表。
重要的部分是 DrawingPanel
和 LevelMeterModel
。 DrawingPanel
从 LevelMeterModel
获取信息并在 JPanel
.
LevelMeterModel
是一个整型数组,包含最低级别和最高级别。可以计算最大音量,但我假设音乐有一定的音量和频率范围。
JFrame
持有DrawingPanel
。 Swing Timer
会随机改变级别。随机数在一个小范围内,因此条形高度不会突然改变。
这是完整的可运行代码。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class LevelMeterGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new LevelMeterGUI());
}
private final DrawingPanel drawingPanel;
private final LevelMeterModel model;
public LevelMeterGUI() {
this.model = new LevelMeterModel();
this.drawingPanel = new DrawingPanel(model);
}
@Override
public void run() {
JFrame frame = new JFrame("Level Meter GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println("Frame size: " + frame.getSize());
Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
model.setRandomLevels();
drawingPanel.repaint();
}
});
timer.start();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int drawingWidth, drawingHeight, margin, rows;
private final Dimension barDimension;
private final LevelMeterModel model;
public DrawingPanel(LevelMeterModel model) {
this.model = model;
this.margin = 10;
this.rows = 20;
this.barDimension = new Dimension(50, 10);
int columns = model.getLevels().length;
drawingWidth = columns * barDimension.width + (columns + 1) * margin;
drawingHeight = rows * barDimension.height + (rows + 1) * margin;
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(drawingWidth, drawingHeight));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int maximum = model.getMaximumLevel();
double increment = (double) maximum / rows;
int peak = rows * 75 / 100;
int x = margin;
for (int level : model.getLevels()) {
int steps = (int) Math.round((double) level / increment);
int y = drawingHeight - margin - barDimension.height;
for (int index = 0; index < steps; index++) {
if (index < peak) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.RED);
}
g.fillRect(x, y, barDimension.width, barDimension.height);
y = y - margin - barDimension.height;
}
x += margin + barDimension.width;
}
}
}
public class LevelMeterModel {
private final int minimumLevel, maximumLevel;
private int[] levels;
private final Random random;
public LevelMeterModel() {
this.minimumLevel = 100;
this.maximumLevel = 999;
this.levels = new int[8];
this.random = new Random();
setRandomLevels();
}
public void setRandomLevels() {
for (int index = 0; index < levels.length; index++) {
levels[index] = getRandomLevel(levels[index]);
}
}
private int getRandomLevel(int level) {
if (level == 0) {
return random.nextInt(maximumLevel - minimumLevel) + minimumLevel;
} else {
int minimum = Math.max(level * 90 / 100, minimumLevel);
int maximum = Math.min(level * 110 / 100, maximumLevel);
return random.nextInt(maximum - minimum) + minimum;
}
}
public int[] getLevels() {
return levels;
}
public int getMinimumLevel() {
return minimumLevel;
}
public int getMaximumLevel() {
return maximumLevel;
}
}
}