当我缩小外圈时,有没有办法让一个圆盖住里面的另一个圆
Is there a way to make a circle cover up another circle inside when I shrink the outer circle
我正在尝试制作一只眼睛,因为为什么不呢,所以我正在尝试制作一个闪烁的动画。
我没有关闭“眼睑”圆圈,而是选择沿 y 轴缩小巩膜(白色位),这样看起来就像眼睛正在闭合。
现在我在中心添加了彩色角膜,但是当我尝试在巩膜和角膜的 y 值相遇时缩小角膜时,角膜看起来很奇怪,就像被压扁了。
有什么方法可以使我缩小巩膜环时,当外环小于内环时,角膜环会消失吗?
基本上就像将 JPanel 的大小调整为小于组件时发生的情况。它们只是消失在框架的边界之下,而不是出现在框架的边界之外。
代码:
class 面板:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.Timer;
public class EyePanel extends JPanel implements ActionListener{
private int width;
private int height;
private int timeStep = 10;
private Timer timer;
private Random random;
Eye eye;
EyePanel(int width, int height){
this.width = width;
this.height = height;
eye = new Eye(width, height, timeStep);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(width, height));
frame.add(this);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
timer = new Timer(timeStep, this);
random = new Random();
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(255,255,255));
draw(g);
}
public void draw(Graphics g) {
eye.draw(g);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
class眼睛:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.*;
import javax.swing.*;
public class Eye {
private int width;
private int height;
private int timeStep;
private int lidDiameter;
private int sclDiameter;
private int corDiameter;
//lid coordinates
private int lidX;
private int lidY;
//sclera coordinates
private int sclX;
private int sclY;
private int sclU; //upper level
private int sclB; //bottom level
private int sclC; //y-level at which eyes are closed
//cornea coordinates
private int corX;
private int corY;
private int corU; //upper level
private int corB; //bottom level
private int corC; //y-level at which eyes are closed
private int blinkDelay = 3; //delay in seconds preset
private int blinkTime; //time till next blink
private int rate = 20; //rate of eye close&open
private boolean closed = false;
Eye(int width, int height, int timeStep){
this.width = width;
this.height = height;
this.timeStep = timeStep;
blinkTime = blinkDelay*(1000/timeStep);
//setup eye variables
if(width>height) lidDiameter = height - (height/10);
else if(height>width) lidDiameter = width - (width/10);
else lidDiameter = width - (height/10);
sclDiameter = lidDiameter-(lidDiameter/10);
corDiameter = sclDiameter/3;
//lid location
lidX = (int)((width-lidDiameter)/2);
lidY = (int)((height-lidDiameter)/2);
//lid location
//sclera location
sclX = (int)(lidX + (lidDiameter-sclDiameter)/2);
sclY = (int)(lidY + (lidDiameter-sclDiameter)/2);
sclU = sclY;
sclB = sclDiameter;
sclC = (int)(sclY+sclDiameter/2);
//sclera location
//cornea location
corX = (int)(sclX + (sclDiameter-corDiameter)/10);
corY = (int)(sclY + (sclDiameter-corDiameter)/10);
corU = corY;
corB = corDiameter;
corC = (int)(corY+corDiameter/2);
//cornea location
//setup eye variables
}
public void close() {
if(sclU != sclC)
sclU+= rate;
if(sclB != sclC)
sclB-= rate*2; //bottom limit must rise by (required amt + rate of upper limit fall)
if(sclU >= sclC && sclB <= sclC)
closed = true;
}
public void open() {
if(sclU != sclY)
sclU+= -rate;
if(sclB != sclDiameter)
sclB-= -rate*2; //bottom limit must rise by (required amt + rate of upper limit fall)
if(sclU == sclY && sclB == sclDiameter) {
closed = false;
blinkTime = blinkDelay*(1000/timeStep);
}
}
public void blink() {
if(blinkTime == 0) {
if(!closed)
close();
if(closed)
open();
}
else
blinkTime--;
}
public void draw (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//eyelid
g2d.setColor(Color.pink);
g2d.fillOval(lidX, lidY, lidDiameter, lidDiameter);
//sclera
g2d.setColor(Color.white);
g2d.fillOval(sclX, sclU, sclDiameter, sclB);
g2d.setColor(Color.black);
g2d.drawLine(sclX, sclC, sclX + sclDiameter, sclC);
//cornea
g2d.setColor(Color.cyan);
g2d.fillOval(corX, corU, corDiameter, corB);
g2d.setColor(Color.red);
g2d.drawLine(corX, corC, corX + corDiameter, corC);
//trigger blink
blink();
}
}
启动一切的主要class:
public class Main {
public static void main(String[] args) {
new EyePanel(600, 600);
}
}
在任何情况下,绘画方法都不应调用任何形式的改变对象状态的逻辑。绘画是由系统事件触发的,您几乎无法控制其时间。 (此类事件的示例是用户移动 window、降低或升高 window、取消 window 图标、解锁屏幕,甚至将鼠标移动到 window .)
所以,您要做的第一件事就是从 Eye 中删除它 class:
//trigger blink
blink();
…并将其添加到您的 actionPerformed 方法中:
@Override
public void actionPerformed(ActionEvent e) {
eye.blink();
repaint();
}
几乎所有 Swing 方法和构造函数 must be run on the AWT event dispatch thread,因此请更改您的 main
方法来做到这一点:
public static void main(String[] args) {
EventQueue.invokeLater(() -> new EyePanel(600, 600));
}
您的代码并不完全符合您的要求(cornea/iris 不在中心),但我认为您的问题是可以回答的。 Area class 可用于检查形状是否相交:
public void draw (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//eyelid
g2d.setColor(Color.pink);
g2d.fillOval(lidX, lidY, lidDiameter, lidDiameter);
//sclera
Area sclera = new Area(
new Ellipse2D.Float(sclX, sclU, sclDiameter, sclB));
g2d.setColor(Color.white);
g2d.fill(sclera);
g2d.setColor(Color.black);
g2d.drawLine(sclX, sclC, sclX + sclDiameter, sclC);
//cornea
Area cornea = new Area(
new Ellipse2D.Float(corX, corU, corDiameter, corB));
Area hiddenCornea = (Area) cornea.clone();
hiddenCornea.subtract(sclera);
if (hiddenCornea.isEmpty()) {
g2d.setColor(Color.cyan);
g2d.fill(cornea);
g2d.setColor(Color.red);
g2d.drawLine(corX, corC, corX + corDiameter, corC);
}
}
如果角膜的任何部分被隐藏(不与巩膜相交),这将跳过绘制角膜。
我正在尝试制作一只眼睛,因为为什么不呢,所以我正在尝试制作一个闪烁的动画。
我没有关闭“眼睑”圆圈,而是选择沿 y 轴缩小巩膜(白色位),这样看起来就像眼睛正在闭合。
现在我在中心添加了彩色角膜,但是当我尝试在巩膜和角膜的 y 值相遇时缩小角膜时,角膜看起来很奇怪,就像被压扁了。
有什么方法可以使我缩小巩膜环时,当外环小于内环时,角膜环会消失吗?
基本上就像将 JPanel 的大小调整为小于组件时发生的情况。它们只是消失在框架的边界之下,而不是出现在框架的边界之外。
代码: class 面板:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.Timer;
public class EyePanel extends JPanel implements ActionListener{
private int width;
private int height;
private int timeStep = 10;
private Timer timer;
private Random random;
Eye eye;
EyePanel(int width, int height){
this.width = width;
this.height = height;
eye = new Eye(width, height, timeStep);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(width, height));
frame.add(this);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
timer = new Timer(timeStep, this);
random = new Random();
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(255,255,255));
draw(g);
}
public void draw(Graphics g) {
eye.draw(g);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
class眼睛:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.*;
import javax.swing.*;
public class Eye {
private int width;
private int height;
private int timeStep;
private int lidDiameter;
private int sclDiameter;
private int corDiameter;
//lid coordinates
private int lidX;
private int lidY;
//sclera coordinates
private int sclX;
private int sclY;
private int sclU; //upper level
private int sclB; //bottom level
private int sclC; //y-level at which eyes are closed
//cornea coordinates
private int corX;
private int corY;
private int corU; //upper level
private int corB; //bottom level
private int corC; //y-level at which eyes are closed
private int blinkDelay = 3; //delay in seconds preset
private int blinkTime; //time till next blink
private int rate = 20; //rate of eye close&open
private boolean closed = false;
Eye(int width, int height, int timeStep){
this.width = width;
this.height = height;
this.timeStep = timeStep;
blinkTime = blinkDelay*(1000/timeStep);
//setup eye variables
if(width>height) lidDiameter = height - (height/10);
else if(height>width) lidDiameter = width - (width/10);
else lidDiameter = width - (height/10);
sclDiameter = lidDiameter-(lidDiameter/10);
corDiameter = sclDiameter/3;
//lid location
lidX = (int)((width-lidDiameter)/2);
lidY = (int)((height-lidDiameter)/2);
//lid location
//sclera location
sclX = (int)(lidX + (lidDiameter-sclDiameter)/2);
sclY = (int)(lidY + (lidDiameter-sclDiameter)/2);
sclU = sclY;
sclB = sclDiameter;
sclC = (int)(sclY+sclDiameter/2);
//sclera location
//cornea location
corX = (int)(sclX + (sclDiameter-corDiameter)/10);
corY = (int)(sclY + (sclDiameter-corDiameter)/10);
corU = corY;
corB = corDiameter;
corC = (int)(corY+corDiameter/2);
//cornea location
//setup eye variables
}
public void close() {
if(sclU != sclC)
sclU+= rate;
if(sclB != sclC)
sclB-= rate*2; //bottom limit must rise by (required amt + rate of upper limit fall)
if(sclU >= sclC && sclB <= sclC)
closed = true;
}
public void open() {
if(sclU != sclY)
sclU+= -rate;
if(sclB != sclDiameter)
sclB-= -rate*2; //bottom limit must rise by (required amt + rate of upper limit fall)
if(sclU == sclY && sclB == sclDiameter) {
closed = false;
blinkTime = blinkDelay*(1000/timeStep);
}
}
public void blink() {
if(blinkTime == 0) {
if(!closed)
close();
if(closed)
open();
}
else
blinkTime--;
}
public void draw (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//eyelid
g2d.setColor(Color.pink);
g2d.fillOval(lidX, lidY, lidDiameter, lidDiameter);
//sclera
g2d.setColor(Color.white);
g2d.fillOval(sclX, sclU, sclDiameter, sclB);
g2d.setColor(Color.black);
g2d.drawLine(sclX, sclC, sclX + sclDiameter, sclC);
//cornea
g2d.setColor(Color.cyan);
g2d.fillOval(corX, corU, corDiameter, corB);
g2d.setColor(Color.red);
g2d.drawLine(corX, corC, corX + corDiameter, corC);
//trigger blink
blink();
}
}
启动一切的主要class:
public class Main {
public static void main(String[] args) {
new EyePanel(600, 600);
}
}
在任何情况下,绘画方法都不应调用任何形式的改变对象状态的逻辑。绘画是由系统事件触发的,您几乎无法控制其时间。 (此类事件的示例是用户移动 window、降低或升高 window、取消 window 图标、解锁屏幕,甚至将鼠标移动到 window .)
所以,您要做的第一件事就是从 Eye 中删除它 class:
//trigger blink
blink();
…并将其添加到您的 actionPerformed 方法中:
@Override
public void actionPerformed(ActionEvent e) {
eye.blink();
repaint();
}
几乎所有 Swing 方法和构造函数 must be run on the AWT event dispatch thread,因此请更改您的 main
方法来做到这一点:
public static void main(String[] args) {
EventQueue.invokeLater(() -> new EyePanel(600, 600));
}
您的代码并不完全符合您的要求(cornea/iris 不在中心),但我认为您的问题是可以回答的。 Area class 可用于检查形状是否相交:
public void draw (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//eyelid
g2d.setColor(Color.pink);
g2d.fillOval(lidX, lidY, lidDiameter, lidDiameter);
//sclera
Area sclera = new Area(
new Ellipse2D.Float(sclX, sclU, sclDiameter, sclB));
g2d.setColor(Color.white);
g2d.fill(sclera);
g2d.setColor(Color.black);
g2d.drawLine(sclX, sclC, sclX + sclDiameter, sclC);
//cornea
Area cornea = new Area(
new Ellipse2D.Float(corX, corU, corDiameter, corB));
Area hiddenCornea = (Area) cornea.clone();
hiddenCornea.subtract(sclera);
if (hiddenCornea.isEmpty()) {
g2d.setColor(Color.cyan);
g2d.fill(cornea);
g2d.setColor(Color.red);
g2d.drawLine(corX, corC, corX + corDiameter, corC);
}
}
如果角膜的任何部分被隐藏(不与巩膜相交),这将跳过绘制角膜。