I'm having problem centering the star shape. The problem is that I hard coded the points for each coordinate. And the problem with this is that Im not getting the right position although I created a perfect 5 star. On more problem is that what if I want to rescale the shape to make it bigger or small by clicking a button? Here's my code.
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);
}
Run Code Online (Sandbox Code Playgroud)
您可能会花费大量时间手动转换多边形数组,但更好的解决方案可能是将多边形转换为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;
}
Run Code Online (Sandbox Code Playgroud)
所以开始...
[250, 262, 304, 268, 278, 250, 222, 232, 196, 238]
[200, 236, 236, 254, 296, 272, 296, 254, 236, 236]
Run Code Online (Sandbox Code Playgroud)
翻译成……
[54, 66, 108, 72, 82, 54, 26, 36, 0, 42]
[0, 36, 36, 54, 96, 72, 96, 54, 36, 36]
Run Code Online (Sandbox Code Playgroud)
涂漆时,看起来像……
你现在可能在想,嗯,这不太好,我想要它在中心,但要进入中心,我们需要多边形的宽度和高度
为了实现这一点,我将转换后的数组传递给minMax方法并使用返回值的第二个元素,它给了我一个值108x96( widthx height),现在我们有了使形状居中所需的信息
@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();
}
Run Code Online (Sandbox Code Playgroud)
基本上,所有这些都是使用maxWidth和maxHeight值来计算当前组件内的中心位置,将Graphics上下文转换为适当的偏移量并绘制多边形。平移移动原点位置(上下文的0x0点Graphics),这允许使用更改多边形的绘制位置。
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以,关于知道,你应该看到0x0为你的形状使用原点的重要性。
查看2D 图形和变换形状、文本和图像以了解更多详细信息
缩放可以通过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();
}
Run Code Online (Sandbox Code Playgroud)
但这会缩放像素,这可能不会给出您想要的结果。
在有人跳下我的喉咙之前,如果你想让它再次居中,你还需要缩放maxWidth和maxHeight值
正如我在过去所说的,使用 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();
}
}
Run Code Online (Sandbox Code Playgroud)
知道,我不了解你,但这更容易阅读,你可以轻松地在一些方格纸上绘制它。
现在它很容易通过做一些简单的事情来填充......
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.fill(new StarShape());
g2d.dispose();
}
Run Code Online (Sandbox Code Playgroud)
但是,等等,我们希望它居中,一切都那么简单......
@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();
}
Run Code Online (Sandbox Code Playgroud)
嗯,这比非形状 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
一般来说,缩放使用与翻译相同的过程,但是,您得到的好处是您可以缩放 aShape然后单独翻译它,允许您独立获得Rectangle缩放的边界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();
}
Run Code Online (Sandbox Code Playgroud)
所以,简短的回答是,使用 Shapes API,长的回答是,使用 Shapes API,你不需要为你面临的每个问题重新发明轮子
| 归档时间: |
|
| 查看次数: |
1601 次 |
| 最近记录: |