如何在一个方法中创建的变量可用于类中的所有其他方法?

时间:2016-11-06 03:20:14

标签: java swing

我是一个编码新手,想要学习更多java。我目前正在高中学习入门编程课程,我只是想在课外玩游戏。我正在创建的这个程序应该在控制台中打印出一些指令和问题,我想用扫描仪和变量检索用户输入。该程序的目标是让用户能够基于纯粹的本能创建“绘图”,然后在事实之后显示该绘图。

这是我的问题。我问用户并将信息存储在main方法的原生变量中,但是我需要在paintComponent方法中使用这些信息。

我尝试在变量前面添加静态,例如: static int emptyRectW1 = kboard.nextInt();但这只是显示错误“参数emptyRectW1的非法修饰符;只允许最终。

我知道这是一个很长的尝试,但这是我得到的最好的。

我正在使用Java Eclipse作为我的IDE。 感谢您的帮助,看起来学习的唯一方法就是搞砸了,让其他人指出我的错误! :)

以下是代码:

import java.util.Scanner;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BlindDrawing extends JPanel {
    public static void main (String[] args) {
        Scanner kboard = new Scanner(System.in);
        System.out.println("Welcome to the Blind Drawing Game!");
        System.out.println("In this game, you will be asked questions about how to construct an image using rectangles and ovals. You will be asked the shape's dimensions and position. The origin (0,0) is the top left corner.");
        System.out.println("First you're making an empty rectangle, how wide do you want it to be?");
        int emptyRectW1 = kboard.nextInt();
        System.out.println("What about the height?");
        int emptyRectH1 = kboard.nextInt();

    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawRect(0,0,emptyRectW1, emptyRectH1);
    }
}

4 个答案:

答案 0 :(得分:4)

更新:在评论中请求了一个示例,所以这里只是一个简单的例子。这只是我所谈论的想法的简单演示;它不是基于上面的代码。原因在于,正如其他人所指出的那样,您还需要对该代码的结构进行更正。我不是试着详细地解决它们,或者给出一个鼓励它们的例子,而是只关注我在原始答案中提出的观点:

public class SampleObject {
    private int aValue;

    protected void getVAlue() {
        Scanner kboard = new Scanner(System.in);
        System.out.println("Enter a value:");
        aValue = kboard.nextInt();
    }

    protected void printValue() {
        System.out.println("The value is " + aValue);
    }

    public void processValue() {
        System.out.println("Welcome");
        getValue();
        printValue();
    }

    public static void main(String[] args) {
        SampleObject sampleObject = new SampleObject();
        sampleObject.processValue();
    }

}

某些样式将主要方法放在单独的“应用程序类”中;一些框架有这样的事情,可能有责任处理请求关闭应用程序的外部消息,或者无论如何。

通常,当您的应用程序超越简单的练习时,您将需要的不仅仅是一个类/对象 - 每个类/对象都有不同的职责构成您的应用程序的功能。

但是现在,这应该显示实例数据如何蠕变,以及如何引导对象集合而不是在静态main方法中进行大量处理。

祝你好运!

作为问题的一般答案:在方法中定义的变量不可用于其他方法,这是由语言设计的。 (一些高级功能稍微改变了这个规则,但不是按照你想要的方式;而且那些东西离你不管怎么样。)

要在方法之间共享状态,请将数据成员(有时称为字段)添加到类本身。然后,可以在一个方法中分配值,并在整个类中读取另一个或其他任何值。

然而,只要您尝试使用该建议,您就会遇到另一个问题,因为main()是(并且必须是)static并且您的其他方法不是(也可能不应该)。所以你要做两件事之一来解决这个问题 - 简单的事情或正确的事情。

容易的事情是添加static数据成员 - 使数据属于类而不是对象的实例。非静态方法仍然可以看到这些。但这会导致你走错方向。

正确的做法是在main方法中引导您的应用程序。这意味着,创建可以协作执行程序功能的对象实例,然后设置这些对象。然后所有实际的工作 - 比如提示用户输入等 - 应该在这些对象的(通常是非静态的)方法中发生。

这是一个非常表面的解释,但实际上这不是深入编程课程的地方。如果你的好奇心超前于课程作业,肯定有很好的OO编程和Java在线教程(或者在你当地的书店......虽然我可能正在约会自己的建议)。

祝你好运。

答案 1 :(得分:3)

简单的答案:通过方法或构造函数的参数将main方法中获得的信息传递给BlindDrawing对象。

但是说过你真的不想将线性控制台类型的应用程序与事件驱动的GUI应用程序混合在一起。选择其中一个并坚持下去。如果您需要在启动主GUI应用程序之前获取所需信息,可以通过JOptionPanes获取所需信息,然后再通过构造函数参数将它们再次传递到主GUI应用程序中。

例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import javax.swing.*;

public class BlindDrawing extends JPanel {
    private Rectangle rectangle;

    public BlindDrawing(Rectangle rectangle) {
        setPreferredSize(new Dimension(1000, 800));
        this.rectangle = rectangle;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (rectangle != null) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(Color.RED);
            g2.draw(rectangle);
        }
    }

    private static void createAndShowGui(Rectangle rect) {
        BlindDrawing mainPanel = new BlindDrawing(rect);

        JFrame frame = new JFrame("BlindDrawing");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        String message = "Enter 4 numbers for X, Y, Width, and Height, separated by a space";
        String title = "Get Rectangle Coordinates";
        int messageType = JOptionPane.PLAIN_MESSAGE;
        String input = JOptionPane.showInputDialog(null, message, title, messageType);
        String[] tokens = input.split("\\s+");
        if (tokens.length == 4) {
            int x = Integer.parseInt(tokens[0]);
            int y = Integer.parseInt(tokens[1]);
            int width = Integer.parseInt(tokens[2]);
            int height = Integer.parseInt(tokens[3]);
            Rectangle rect = new Rectangle(x, y, width, height);
            SwingUtilities.invokeLater(() -> createAndShowGui(rect));
        }
    }
}

编辑

你在评论中提问:

  

我不明白的是那些有令牌的底部。我真的不明白这些代币的作用,如果你能澄清一下,那就太好了!

对我而言,问题是:我们如何才能最轻松地允许用户输入ining以在Swing应用程序中使用,但是为了进一步细分,我们可以要求提供最容易为提供的解决方案编码器用户最容易的解决方案。一般来说,你会更喜欢追求后者。

编码器最简单的方法是创建一个简单的控制台应用程序,让用户使用字符串提示和已初始化为标准输入或System.in的Scanner对象输入数字。正如我所提到的,虽然编码器很容易,但它对用户来说效果不佳,因为控制台应用程序和GUI应用程序不能很好地协同工作,因为一个是以线性方式构建的,而另一个是更自由流动和事件驱动。如果您希望稍后在程序运行时获取数据,并且您再次让用户通过控制台输入信息,则可能会冻结Swing应用程序,使其无效,或者在后台线程中不适当地更新Swing应用程序。

我上面的解决方案是一种妥协,我们使用JOptionPane.showInputDialog(...)提示用户输入单个字符串。这将为用户提供提示,并允许他在文本字段中输入单个String。在这里,我要求用户输入四个分隔的numbrers,每个numbrers用空格分隔,我认为你理解这部分,但是它有一个问题是,一旦你得到那个我称之为input的String,怎么做你从中提取出四个数字。

一种方法是使用String的tokens方法将String拆分为一个字符串数组(我称之为split(...))。一个简单的方法就是这样:

String[] tokens = input.split(" ");

这将通过在单个空间上拆分将输入String拆分为子串数组。如果用户在他的号码之间意外使用了多个空格,或者如果他使用不同的白色空间"那么它不能很好地工作。分开数字。我改为使用:

String[] tokens = input.split("\\s+");

这使用了一种叫做正则表达式的东西,或者" regex"简而言之就是拆分String。 \\s表示任何空格字符,+表示我们将在一个或更多空白字符上拆分。因此,如果用户在他的数字之间放置2或3个空格,这仍然有用。

分割此String的另一种可能方法是将其放入扫描仪,然后扫描"为了整数。在这里,我们不使用System.in扫描标准输入,而是扫描输入的字符串,此处为input。例如:

// get our line of input same as we did before
String input = JOptionPane.showInputDialog(null, message, title, messageType);

// create a Scanner object that scans through the line
Scanner inputScanner = new Scanner(input);

// extract the four numbers from the line
int x = inputScanner.nextInt();
int y = inputScanner.nextInt();
int width = inputScanner.nextInt();
int height = inputScanner.nextInt();

// close the Scanner so we don't waste resources
inputScanner.close();

这仍然存在问题,因为如果用户输入2或3个数字而不是4,或者如果用户输入非数字输入,所有这些解决方案都会失败,并且还有其他方法可以检查并纠正,例如使用JSpinner或JComboBox将用户的选择限制为允许的数字,或者使用try / catch块捕获无效输入,然后提示用户输入更正确的内容。

答案 2 :(得分:0)

您可以将它们初始化为实例变量,以便各种其他方法可以使用它们,如:

public class BlindDrawing extends JPanel {
    private int emptyRectW1;
    private int emptyRectH1;

    public static void main (String[] args) {
        new BlindDrawing().run();
    }

    private void run() {
        Scanner kboard = new Scanner(System.in);
        System.out.println("Welcome to the Blind Drawing Game!");
        System.out.println("In this game, you will be asked questions about how to construct an image using rectangles and ovals. You will be asked the shape's dimensions and position. The origin (0,0) is the top left corner.");
        System.out.println("First you're making an empty rectangle, how wide do you want it to be?");
        emptyRectW1 = kboard.nextInt();
        System.out.println("What about the height?");
        emptyRectH1 = kboard.nextInt();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawRect(0, 0, emptyRectW1, emptyRectH1);
    }
}

答案 3 :(得分:-2)

实际上,在方法中声明的变量是局部变量。

请在main方法之前扩展两个变量的范围。请参阅下面的代码。

static int emptyRectW1, emptyRectH1;
public static void main (String[] args) {

然后操纵后面的代码以避免重复的变量声明,如下所示。

    emptyRectW1 = kboard.nextInt();
    System.out.println("What about the height?");
    emptyRectH1 = kboard.nextInt();

我希望这会有所帮助。