JFrame 程序和 运行 另一个 class in Java
JFrame program and running another class in Java
所以目前我想使用一个 jframe 程序,它将 运行 另一个 class 在 window.
一个工作示例:
Jframe:
import javax.swing.JFrame;
public class FaceJFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("A Rectangle Object in a JFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Face aRectangle = new Face();
frame.add(aRectangle);
frame.setVisible(true);
}
}
程序:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import javax.swing.JComponent;
public class Face extends JComponent
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// Construct face and eyes
Rectangle face = new Rectangle(0, 0, 50, 50);
Rectangle eye = new Rectangle(5, 5, 15, 15);
Rectangle eye2 = new Rectangle(25, 5, 15, 15);
//make some lines for the mouth
Line2D mouth1 = new Line2D.Double(15, 30, 15, 35);
Line2D mouth2 = new Line2D.Double(15, 35, 35, 35);
Line2D mouth3 = new Line2D.Double(35, 35, 35, 30);
// draw the rectangle
g2.draw(face);
g2.draw(eye);
g2.draw(eye2);
g2.draw(mouth1);
g2.draw(mouth2);
g2.draw(mouth3);
}
}
使用这两个代码片段,运行在 cmd 中使用 Jframe 会弹出一个window,上面有一张小脸。
我想用下面的代码做同样的事情:
Jframe:
import javax.swing.JFrame;
public class Car_JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("a car");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Car aRectangle = new Car();
frame.add(aRectangle);
frame.setVisible(true);
}
}
和主要 class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class Car
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle body = new Rectangle(0, 10, 60, 20);
Line2D roof1 = new Line2D.Double(10, 10, 20, 0);
Line2D roof2 = new Line2D.Double(20, 0, 40, 0);
Line2D roof3 = new Line2D.Double(40, 0, 50, 10);
Ellipse2D.Double wheel1 = new Ellipse2D.Double(15, 25, 10,10);
Ellipse2D.Double wheel2 = new Ellipse2D.Double(45, 25, 10,10);
// draw the rectangle
g2.draw(body);
g2.draw(roof1);
g2.draw(roof2);
g2.draw(roof3);
g2.draw(wheel1);
g2.draw(wheel2);
}
}
它不会产生相同的结果。其实cmd中运行ning car_jframe会输出人脸程序。 (他们在同一个 blueJ 项目中)
我该怎么办?
您的主要问题是您的 Car class 没有扩展 JPanel 或 JComponent 或任何派生自它们的 class,因此无法将其添加到您的 JFrame 中,并且任何尝试这样做所以会导致编译错误。您有两个主要可能的解决方案:
- 通过扩展 JPanel(或 JComponent,但我推荐 JPanel)使 Car 成为真正的组件。
- 或者,如果您希望 Car 是逻辑 class 而不是组件 class,则创建一个包含 Car 对象的 JPanel 并通过直接调用该对象的 paintComponent 来绘制 Car 对象JPanel 自己的 paintComponent 方法中的方法。
其他说明:
- 您几乎总是想在覆盖中调用
super.paintComponent(g)
方法,以便 JPanel 可以进行内务处理。
- 您总是希望在您认为是带有
@Override
注解的重写方法的任何方法前加上这样的方法,如果您的假设不正确,编译器会警告您.
例如,
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.*;
import javax.swing.*;
public class TestCar {
private static void createAndShowGui() {
Car mainPanel = new Car();
JFrame frame = new JFrame("A Car");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start all code on the Swing event thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Car extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private static final Rectangle BODY = new Rectangle(0, 10, 60, 20);
private static final Line2D ROOF_1 = new Line2D.Double(10, 10, 20, 0);
private static final Line2D ROOF_2 = new Line2D.Double(20, 0, 40, 0);
private static final Line2D ROOF_3 = new Line2D.Double(40, 0, 50, 10);
private static final Ellipse2D WHEEL_1 = new Ellipse2D.Double(15, 25, 10,10);
private static final Ellipse2D WHEEL_2 = new Ellipse2D.Double(45, 25, 10,10);
public Car() {
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// draw the rectangle
g2.draw(BODY);
g2.draw(ROOF_1);
g2.draw(ROOF_2);
g2.draw(ROOF_3);
g2.draw(WHEEL_1);
g2.draw(WHEEL_2);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
如果你想要真正的花哨,使用 Path2D 对象、AffineTransform 和 Swing Timer 并给你的 GUI 一点动画:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Car2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private static final Rectangle BODY = new Rectangle(0, 10, 60, 20);
private static final Line2D ROOF_1 = new Line2D.Double(10, 10, 20, 0);
private static final Line2D ROOF_2 = new Line2D.Double(20, 0, 40, 0);
private static final Line2D ROOF_3 = new Line2D.Double(40, 0, 50, 10);
private static final Ellipse2D WHEEL_1 = new Ellipse2D.Double(15, 25, 10,
10);
private static final Ellipse2D WHEEL_2 = new Ellipse2D.Double(45, 25, 10,
10);
private static final int TIMER_DELAY = 30;
private static final int CAR_DELTA_X = 1;
private static final int CAR_DELTA_Y = CAR_DELTA_X;
private Path2D path2D = new Path2D.Double();
public Car2() {
path2D.append(BODY, false);
path2D.append(ROOF_1, false);
path2D.append(ROOF_2, false);
path2D.append(ROOF_3, false);
path2D.append(WHEEL_1, false);
path2D.append(WHEEL_2, false);
new Timer(TIMER_DELAY, new CarTimerListener()).start();;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.draw(path2D);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
class CarTimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
path2D.transform(AffineTransform.getTranslateInstance(CAR_DELTA_X, CAR_DELTA_Y));
repaint();
}
}
}
您的应用程序中应该只有一个主要方法。我会像下面这样更改它,让用户 select 在 运行 应用程序时打印哪个形状。
import javax.swing.JFrame;
public class DrawFrame {
public static void main(String[] args) {
if(args[0].equals("face") {
paintFace()
}
else if(args[0].equals("car") {
paintCar();
}
else {
System.out.println("No Shape Selected to Print");
}
}
private static paintFace() {
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("A Rectangle Object in a JFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Face face = new Face();
frame.add(face);
frame.setVisible(true);
}
private static paintCar() {
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("a car");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Car car = new Car();
frame.add(car);
frame.setVisible(true);
}
}
你的车也没有扩展组件。不行。
更正为
public class Car extends JComponent { ... }
所以目前我想使用一个 jframe 程序,它将 运行 另一个 class 在 window.
一个工作示例:
Jframe:
import javax.swing.JFrame;
public class FaceJFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("A Rectangle Object in a JFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Face aRectangle = new Face();
frame.add(aRectangle);
frame.setVisible(true);
}
}
程序:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import javax.swing.JComponent;
public class Face extends JComponent
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// Construct face and eyes
Rectangle face = new Rectangle(0, 0, 50, 50);
Rectangle eye = new Rectangle(5, 5, 15, 15);
Rectangle eye2 = new Rectangle(25, 5, 15, 15);
//make some lines for the mouth
Line2D mouth1 = new Line2D.Double(15, 30, 15, 35);
Line2D mouth2 = new Line2D.Double(15, 35, 35, 35);
Line2D mouth3 = new Line2D.Double(35, 35, 35, 30);
// draw the rectangle
g2.draw(face);
g2.draw(eye);
g2.draw(eye2);
g2.draw(mouth1);
g2.draw(mouth2);
g2.draw(mouth3);
}
}
使用这两个代码片段,运行在 cmd 中使用 Jframe 会弹出一个window,上面有一张小脸。
我想用下面的代码做同样的事情:
Jframe:
import javax.swing.JFrame;
public class Car_JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("a car");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Car aRectangle = new Car();
frame.add(aRectangle);
frame.setVisible(true);
}
}
和主要 class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class Car
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle body = new Rectangle(0, 10, 60, 20);
Line2D roof1 = new Line2D.Double(10, 10, 20, 0);
Line2D roof2 = new Line2D.Double(20, 0, 40, 0);
Line2D roof3 = new Line2D.Double(40, 0, 50, 10);
Ellipse2D.Double wheel1 = new Ellipse2D.Double(15, 25, 10,10);
Ellipse2D.Double wheel2 = new Ellipse2D.Double(45, 25, 10,10);
// draw the rectangle
g2.draw(body);
g2.draw(roof1);
g2.draw(roof2);
g2.draw(roof3);
g2.draw(wheel1);
g2.draw(wheel2);
}
}
它不会产生相同的结果。其实cmd中运行ning car_jframe会输出人脸程序。 (他们在同一个 blueJ 项目中)
我该怎么办?
您的主要问题是您的 Car class 没有扩展 JPanel 或 JComponent 或任何派生自它们的 class,因此无法将其添加到您的 JFrame 中,并且任何尝试这样做所以会导致编译错误。您有两个主要可能的解决方案:
- 通过扩展 JPanel(或 JComponent,但我推荐 JPanel)使 Car 成为真正的组件。
- 或者,如果您希望 Car 是逻辑 class 而不是组件 class,则创建一个包含 Car 对象的 JPanel 并通过直接调用该对象的 paintComponent 来绘制 Car 对象JPanel 自己的 paintComponent 方法中的方法。
其他说明:
- 您几乎总是想在覆盖中调用
super.paintComponent(g)
方法,以便 JPanel 可以进行内务处理。 - 您总是希望在您认为是带有
@Override
注解的重写方法的任何方法前加上这样的方法,如果您的假设不正确,编译器会警告您.
例如,
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.*;
import javax.swing.*;
public class TestCar {
private static void createAndShowGui() {
Car mainPanel = new Car();
JFrame frame = new JFrame("A Car");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start all code on the Swing event thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Car extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private static final Rectangle BODY = new Rectangle(0, 10, 60, 20);
private static final Line2D ROOF_1 = new Line2D.Double(10, 10, 20, 0);
private static final Line2D ROOF_2 = new Line2D.Double(20, 0, 40, 0);
private static final Line2D ROOF_3 = new Line2D.Double(40, 0, 50, 10);
private static final Ellipse2D WHEEL_1 = new Ellipse2D.Double(15, 25, 10,10);
private static final Ellipse2D WHEEL_2 = new Ellipse2D.Double(45, 25, 10,10);
public Car() {
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// draw the rectangle
g2.draw(BODY);
g2.draw(ROOF_1);
g2.draw(ROOF_2);
g2.draw(ROOF_3);
g2.draw(WHEEL_1);
g2.draw(WHEEL_2);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
如果你想要真正的花哨,使用 Path2D 对象、AffineTransform 和 Swing Timer 并给你的 GUI 一点动画:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Car2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private static final Rectangle BODY = new Rectangle(0, 10, 60, 20);
private static final Line2D ROOF_1 = new Line2D.Double(10, 10, 20, 0);
private static final Line2D ROOF_2 = new Line2D.Double(20, 0, 40, 0);
private static final Line2D ROOF_3 = new Line2D.Double(40, 0, 50, 10);
private static final Ellipse2D WHEEL_1 = new Ellipse2D.Double(15, 25, 10,
10);
private static final Ellipse2D WHEEL_2 = new Ellipse2D.Double(45, 25, 10,
10);
private static final int TIMER_DELAY = 30;
private static final int CAR_DELTA_X = 1;
private static final int CAR_DELTA_Y = CAR_DELTA_X;
private Path2D path2D = new Path2D.Double();
public Car2() {
path2D.append(BODY, false);
path2D.append(ROOF_1, false);
path2D.append(ROOF_2, false);
path2D.append(ROOF_3, false);
path2D.append(WHEEL_1, false);
path2D.append(WHEEL_2, false);
new Timer(TIMER_DELAY, new CarTimerListener()).start();;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.draw(path2D);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
class CarTimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
path2D.transform(AffineTransform.getTranslateInstance(CAR_DELTA_X, CAR_DELTA_Y));
repaint();
}
}
}
您的应用程序中应该只有一个主要方法。我会像下面这样更改它,让用户 select 在 运行 应用程序时打印哪个形状。
import javax.swing.JFrame;
public class DrawFrame {
public static void main(String[] args) {
if(args[0].equals("face") {
paintFace()
}
else if(args[0].equals("car") {
paintCar();
}
else {
System.out.println("No Shape Selected to Print");
}
}
private static paintFace() {
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("A Rectangle Object in a JFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Face face = new Face();
frame.add(face);
frame.setVisible(true);
}
private static paintCar() {
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("a car");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Car car = new Car();
frame.add(car);
frame.setVisible(true);
}
}
你的车也没有扩展组件。不行。
更正为
public class Car extends JComponent { ... }