我在将星形居中时遇到问题。问题是我对每个坐标的点进行了硬编码。问题是,尽管我创造了完美的 5 星,但我没有得到正确的位置。更多的问题是,如果我想通过单击按钮来重新调整形状以使其变大或变小怎么办? 这是我的代码。
public void run() {
DifferentShapes panel = new DifferentShapes();
JFrame frame = new JFrame("Different Shapes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setVisible(true);
frame.add(panel);
frame.setJMenuBar(panel.getMenuBAr());
}
public void star(Graphics shape) {
// int sizeReq = 1;
int [] starX = new int[] {250, 262, 304, 268, 278, 250, 222, 232, 196, 238};
int []starY = new int[] {200, 236, 236, 254, 296, 272, 296, 254, 236, 236};
shape.fillPolygon(starX, starY, starX.length);
}
最佳答案
没有 Shapes API
您可能会花费大量时间手动平移多边形数组,但更好的解决方案可能是将多边形平移为 0x0
,以便顶部/左上角位于 0x0
基本上,我计算了每个数组的最小/最大值,然后从所有值中减去“最小值”...
protected static int[] minMax(int[] values) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int value : values) {
min = Math.min(min, value);
max = Math.max(max, value);
}
return new int[]{min, max};
}
protected static int[] normalise(int[] values, int min) {
for (int index = 0; index < values.length; index++) {
values[index] = values[index] - min;
}
return values;
}
所以从...开始
[250, 262, 304, 268, 278, 250, 222, 232, 196, 238]
[200, 236, 236, 254, 296, 272, 296, 254, 236, 236]
翻译成...
[54, 66, 108, 72, 82, 54, 26, 36, 0, 42]
[0, 36, 36, 54, 96, 72, 96, 54, 36, 36]
绘制后,看起来像......
你现在可能在想,好吧,这不太好,我希望它位于中心,但为了到达中心,我们需要多边形的宽度和高度
为了实现这一目标,我获取了翻译后的数组,并将它们传递给 minMax
方法,并使用返回值的第二个元素,这给了我一个值 108x96
(宽度
x高度
),现在我们有了使形状居中所需的信息
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics copy = g.create();
int x = (getWidth() - maxWidth) / 2;
int y = (getHeight() - maxHeight) / 2;
copy.translate(x, y);
copy.fillPolygon(starX, starY, starX.length);
copy.dispose();
}
基本上,这一切都是使用 maxWidth
和 maxHeight
值来计算当前组件内的中心位置,翻译 Graphics
上下文到适当的偏移并绘制多边形。平移会移动原点位置(Graphics
上下文的 0x0
点),从而允许更改多边形的绘制位置。
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Arrays;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
protected static int[] minMax(int[] values) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int value : values) {
min = Math.min(min, value);
max = Math.max(max, value);
}
return new int[]{min, max};
}
protected static int[] normalise(int[] values, int min) {
for (int index = 0; index < values.length; index++) {
values[index] = values[index] - min;
}
return values;
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int starX[];
private int starY[];
private int maxWidth, maxHeight;
public TestPane() {
starX = new int[]{250, 262, 304, 268, 278, 250, 222, 232, 196, 238};
starY = new int[]{200, 236, 236, 254, 296, 272, 296, 254, 236, 236};
int[] minMaxX = minMax(starX);
int[] minMaxY = minMax(starY);
starX = normalise(starX, minMaxX[0]);
starY = normalise(starY, minMaxY[0]);
minMaxX = minMax(starX);
minMaxY = minMax(starY);
maxWidth = minMaxX[1];
maxHeight = minMaxY[1];
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics copy = g.create();
int x = (getWidth() - maxWidth) / 2;
int y = (getHeight() - maxHeight) / 2;
copy.translate(x, y);
copy.fillPolygon(starX, starY, starX.length);
copy.dispose();
}
}
}
因此,您应该了解为形状使用 0x0
原点的重要性。
看看2D Graphics和 Transforming Shapes, Text, and Images了解更多详情
缩放...
可以通过Graphics2D#scale
来完成缩放...
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D copy = (Graphics2D) g.create();
double scale = slider.getValue() / 100d;
int x = (getWidth() - maxWidth) / 2;
int y = (getHeight() - maxHeight) / 2;
copy.translate(x, y);
copy.scale(scale, scale);
copy.fillPolygon(starX, starY, starX.length);
copy.dispose();
}
但这会缩放像素,这可能不会给出您想要的结果。
在有人跳入我的喉咙之前,如果您想让它再次居中,您还需要缩放 maxWidth
和 maxHeight
值
使用 Shapes API
正如我过去所说,使用 2D 形状 API 您将获得更好的结果,它们是独立的,易于移动,并且在缩放时您将获得更好的结果
例如,使用上面的“翻译”值,您应该创建一个很好的自定义、可重用类...
public class StarShape extends Path2D.Double {
public StarShape() {
moveTo(54, 0);
lineTo(66, 36);
lineTo(108, 36);
lineTo(75, 54);
lineTo(82, 96);
lineTo(54, 72);
lineTo(26, 96);
lineTo(36, 54);
lineTo(0, 36);
lineTo(42, 36);
closePath();
}
}
知道,我不了解你,但这更容易阅读,你可以轻松地将其绘制在一些方格纸上。
现在,通过做一些简单的事情就可以轻松地填补它,例如......
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.fill(new StarShape());
g2d.dispose();
}
但是,等等,我们希望它居中,一切都很容易......
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = starShape.getBounds();
int x = (getWidth() - bounds.width) / 2;
int y = (getHeight() - bounds.height) / 2;
g2d.fill(starShape.createTransformedShape(AffineTransform.getTranslateInstance(x, y)));
g2d.dispose();
}
嗯,这比非形状 API 方法少了很多代码......
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class StarShape extends Path2D.Double {
public StarShape() {
moveTo(54, 0);
lineTo(66, 36);
lineTo(108, 36);
lineTo(75, 54);
lineTo(82, 96);
lineTo(54, 72);
lineTo(26, 96);
lineTo(36, 54);
lineTo(0, 36);
lineTo(42, 36);
closePath();
}
}
public class TestPane extends JPanel {
private StarShape starShape;
public TestPane() {
starShape = new StarShape();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = starShape.getBounds();
int x = (getWidth() - bounds.width) / 2;
int y = (getHeight() - bounds.height) / 2;
g2d.fill(starShape.createTransformedShape(AffineTransform.getTranslateInstance(x, y)));
g2d.dispose();
}
}
}
缩放
一般来说,缩放使用与翻译相同的过程,但是,您得到的好处是您可以缩放 Shape
然后单独翻译它,从而获得 独立缩放的
边界。它还缩放 vector (点)而不是像素,这将为您提供更好的结果......Shape
的矩形
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double scale = slider.getValue() / 100d;
Shape shape = starShape.createTransformedShape(AffineTransform.getScaleInstance(scale, scale));
Rectangle bounds = shape.getBounds();
int x = (getWidth() - bounds.width) / 2;
int y = (getHeight() - bounds.height) / 2;
GeneralPath path = new GeneralPath();
path.append(shape.getPathIterator(AffineTransform.getTranslateInstance(x, y)), true);
g2d.fill(path);
g2d.dispose();
}
所以,简短的答案是,使用 Shapes API,详细的答案是,使用 Shapes API,您无需为遇到的每个问题重新发明轮子
关于java - 如何使用 getWidth() 和 getHeight() 在 java 中使星形居中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35074888/