paintPaint中的println打印出497971。在JPanel的视图中,根据该数字对,红线的左上点应该位于JPanel的中间附近,但实际上并非如此。是由坐标系引起的转换?
提前致谢。
代码如下所示:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ClockFrame extends JFrame {
JPanel panel;
public ClockFrame(){
panel = new JPanel();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
setSize(1000, 1000);
panel.setSize(getWidth(), getHeight());
//panel.setLayout(null);//!important
panel.setLayout(new GridLayout());
setVisible(true);
setResizable(false);
panel.setBackground(Color.BLACK);
Hand sHand=new Hand(panel);
panel.add(sHand);
}
class Hand extends JComponent{
private Timer timer;
public Hand(Object o){
setLocation(500,500);
((JPanel)o).add(this);
timer = new Timer(800, new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);System.out.println(panel.getWidth()/2 +" "+panel.getHeight());
g2d.drawLine(panel.getWidth()/2, panel.getHeight()/2, 30, 30);
g2d.dispose();
}
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
}
public static void main(String[] a) {
ClockFrame c=new ClockFrame();
}
}
最佳答案
g2d.drawLine(0, 0, 100, 50);
g2d.setColor(Color.WHITE); // no good setting the color now!
应该:
g2d.setColor(Color.WHITE); // correct
g2d.drawLine(0, 0, 100, 50);
其他提示:
添加所有组件后,最好
pack()
框架。然后,将是正确的尺寸来显示它们。在大多数情况下,将顶级容器设置为可见应该是构造函数中的最后一件事。setSize(1000, 1000);
组件的位置最好由布局管理器,填充和边框确定。
public Hand(Object o){
setLocation(500,500);
如果需要将组件添加到容器中,最好将其作为容器传递。话虽如此,最好不要完全在构造函数中传递容器,而要在实例化之后立即在代码中
add(..)
。public Hand(Object o){
// ..
((JPanel)o).add(this);
其中一些概念在下面的代码中实现。确保运行它以查看效果。
特别注意:
/* Note that this is translating further drawing operations
to the middle of the Hand container based on its preferred size,
which is (layout manager not withstanding) also its actual size.
All co-ordinates in custom painting are relative to the component
being painted. */
g2d.translate(middle, middle);
码
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.util.Calendar;
import java.util.Date;
import javax.swing.*;
public class ClockFrame extends JFrame {
public ClockFrame() {
JPanel panel = new JPanel();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
panel.setSize(getWidth(), getHeight());
//panel.setLayout(null);//!important
panel.setLayout(new GridLayout());
setResizable(false);
panel.setBackground(Color.BLACK);
Hand sHand = new Hand(panel);
panel.add(sHand);
pack();
setVisible(true);
}
class Hand extends JComponent {
private Timer timer;
private Dimension preferredSize = new Dimension(600, 600);
private Calendar currentTime;
public Hand(Object o) {
setLocation(500, 500);
((JPanel) o).add(this);
currentTime = Calendar.getInstance();
timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentTime.setTime(new Date(System.currentTimeMillis()));
repaint();
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("x: " + this.getX() + " y: " + this.getY() + " w: " + this.getWidth() + " h: " + this.getHeight());
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.WHITE);
double angle = (currentTime.get(Calendar.SECOND)*2*Math.PI)/60d;
double middle = preferredSize.getWidth() / 2d;
/* Note that this is translating further drawing operations
to the middle of the Hand container based on its preferred size,
which is (layout manager not withstanding) also its actual size.
All co-ordinates in custom painting are relative to the component
being painted. */
g2d.translate(middle, middle);
Line2D.Double secondHand = new Line2D.Double(0, 0,
middle*.9*Math.cos(angle),
middle*.9*Math.sin(angle));
g2d.draw(secondHand);
g2d.dispose();
}
public Dimension getPreferredSize() {
return preferredSize;
}
}
public static void main(String[] a) {
ClockFrame c = new ClockFrame();
}
}
编辑:包括分针和时针
我发现如果增加分针,则在秒针之后,我的面板将变宽两倍-我认为这是因为图形无法叠加...-而我得到的是两个graphics2D彼此分开并重新绘制..解决这个问题的好主意吗?
因为很无聊,所以我玩了一些代码。我发现角度不对,所以要偏移一些以进行校正。然后,我将分针和时针添加到了相同的自定义组件中。我认为后者是您描述问题的原因(如果没有,请显示您的最新代码-尽管可能是一个新问题)。
尝试使用此版本(请注意,秒针,分针和时针均已量化为各自的时间单位):
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.io.IOException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ClockFrame extends JFrame {
public ClockFrame() {
JPanel panel = new JPanel();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
panel.setSize(getWidth(), getHeight());
panel.setLayout(new GridLayout());
setResizable(false);
panel.setBackground(Color.MAGENTA.darker().darker());
Hand sHand = new Hand(panel);
panel.add(sHand);
pack();
setVisible(true);
}
class Hand extends JComponent {
private Timer timer;
private Dimension preferredSize = new Dimension(600, 600);
private Calendar currentTime;
private Image clockFace;
public Hand(Object o) {
setLocation(500, 500);
((JPanel) o).add(this);
currentTime = Calendar.getInstance();
try {
clockFace = ImageIO.read(new URL(
"http://www.clipartbest.com/cliparts/LTK/kBp/LTKkBpRGc.png"));
} catch (IOException ex) {
Logger.getLogger(ClockFrame.class.getName()).log(Level.SEVERE, null, ex);
}
timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentTime.setTime(new Date(System.currentTimeMillis()));
repaint();
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
g2d.setColor(Color.LIGHT_GRAY);
int size = preferredSize.width;
g2d.fillOval((int)(size*.01), (int)(size*.01), (int)(size*.98), (int)(size*.98));
if (clockFace!=null) {
g2d.drawImage(clockFace, 0, 0, this);
}
double middle = size / 2d;
/* Note that this is translating further drawing operations
to the middle of the Hand container based on its preferred size,
which is (layout manager not withstanding) also its actual size.
All co-ordinates in custom painting are relative to the component
being painted. */
g2d.translate(middle, middle);
g2d.setColor(Color.CYAN.darker().darker());
double angleHour = ((currentTime.get(Calendar.HOUR)*2*Math.PI)/12d)-(Math.PI/2);
g2d.setStroke(new BasicStroke(6.5f));
Line2D.Double hourHand = new Line2D.Double(0, 0,
middle*.83*Math.cos(angleHour),
middle*.83*Math.sin(angleHour));
g2d.draw(hourHand);
g2d.setColor(Color.CYAN.darker());
double angleMin = ((currentTime.get(Calendar.MINUTE)*2*Math.PI)/60d)-(Math.PI/2);
g2d.setStroke(new BasicStroke(4.5f));
Line2D.Double minuteHand = new Line2D.Double(0, 0,
middle*.85*Math.cos(angleMin),
middle*.85*Math.sin(angleMin));
g2d.draw(minuteHand);
g2d.setColor(Color.CYAN);
double angleSec = ((currentTime.get(Calendar.SECOND)*2*Math.PI)/60d)-(Math.PI/2);
g2d.setStroke(new BasicStroke(2.5f));
Line2D.Double secondHand = new Line2D.Double(0, 0,
middle*.87*Math.cos(angleSec),
middle*.87*Math.sin(angleSec));
g2d.draw(secondHand);
g2d.dispose();
}
public Dimension getPreferredSize() {
return preferredSize;
}
}
public static void main(String[] a) {
ClockFrame c = new ClockFrame();
}
}
关于java - JComponent相对于JPanel的坐标系,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42266729/