【问题标题】:Using JFrame with a Continuous Input Stream将 JFrame 与连续输入流一起使用
【发布时间】:2018-04-09 02:11:33
【问题描述】:

我正在尝试实现从我的红板串行端口读取的代码,并根据它读取的内容重新绘制一个圆圈。这样做的最终目标是使用 Robot 类来实现实际的光标控制,但我首先想了解更多关于 Java 的知识,所以我试图先用一些基本的图形来实现它。

总结一下我的问题,我不知道如何将 JFrame 与来自静态方法的不断变化的输入一起使用。

串口访问JAR可以在http://fazecast.github.io/jSerialComm/找到

Arduino 以“UpLeft”、“Up”、“UpRight”、“Left”、“Center”、“Right”、“DownLeft”、“Down”的形式连续写入基于 FPGA 加速度计系统的串行", "右下角"。然后 Java 程序应该抓取它并相应地重新绘制一个圆圈。

我能够打开 COMM3 并打印从我的硬件接收到的正确方向,但是每当我尝试应用 JFrame 时,我都会迷路。我找到了很多 ActionListener 教程,但是这个实现应该是连续的,并且不依赖于鼠标或键盘事件。因此,我不知道如何使用paintComponent() 和painter() 方法,因为main 方法是静态的。

非常感谢您的宝贵时间!

import java.awt.Color;
import java.awt.Graphics;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import com.fazecast.jSerialComm.*;

public class Main extends JPanel{

    public void paintComponent(Graphics g, int x, int y) {
        super.paintComponent(g);
        g.setColor(Color.MAGENTA);
        g.fillOval(x, y, 20, 20);
    }
    public void painter(int x, int y, int velx, int vely){
        x = x + velx;
        y = y + vely;
        repaint();
    }

    public static void main(String[] args) {
        int x = 0, y = 0, velx = 0, vely = 0;
        SerialPort ports[] = SerialPort.getCommPorts();
        System.out.println("Select a Port:");
        SerialPort port = ports[1];
        Graphics g;

        if(port.openPort()){
            System.out.println("Successfully opened the port.");
        } else {
            System.out.println("Unable to open the port.");
        }
        port.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
        JFrame jf = new JFrame();
        Main main = new Main();

        jf.setTitle("Window");
        jf.setSize(600, 400);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.add(main);

        Scanner data = new Scanner(port.getInputStream());
        while(data.hasNextLine()) {
            System.out.println(data.nextLine());
            try{String dir = data.nextLine();
                if(dir.equals("UpLeft")) {
                    velx = -1;
                    vely = -1;
                }
                if(dir.equals("Up")) {
                    velx = 0;
                    vely = -1;
                }
                if(dir.equals("UpRight")) {
                    velx = 1;
                    vely = -1;
                }
                if(dir.equals("Left")) {
                    velx = -1;
                    vely = 0;
                }
                if(dir.equals("Center")) {
                    velx = 0;
                    vely = 0;
                }
                if(dir.equals("Right")) {
                    velx = 1;
                    vely = 0;
                }
                if(dir.equals("DownLeft")) {
                    velx = -1;
                    vely = 1;
                }
                if(dir.equals("Down")) {
                    velx = 0;
                    vely = 1;
                }
                if(dir.equals("DownRight")) {
                    velx = 1;
                    vely = 1;
                }
                System.out.println(velx);
                System.out.println(vely);
            }           
            catch(Exception e) {};
        }
    }
}

【问题讨论】:

    标签: java swing concurrency arduino actionlistener


    【解决方案1】:

    建议:

    1. 将 InputStream 的读数从静态 main 方法中取出并放入它自己的类中。
    2. 这个类应该扩展SwingWorker<Void, String>。您必须阅读Concurrency in Swing 教程以完全了解如何使用这个类。它将帮助您在后台线程中执行长时间运行的流读取,然后将获得的数据安全地传递到 Swing 事件线程上的 Swing GUI。
    3. 从流中读取的所有内容都应在此类的doInBackground() 方法中完成。从 Scanner/Stream 中获取 String,并调用 worker 的 publish(...) 方法,将 String 传递给该方法。
    4. 给你的 Swing GUI 一个公共方法,比如public void getPortText(String text)
    5. 在 Worker 中使用 protected void process(List<String> chunks) 方法覆盖。使用 for 循环遍历块 List<String>,通过调用 GUI 的 getPortText(...) 方法将数据传递到 Swing GUI。
    6. 在GUI的getPortText方法中,改变GUI类的一个字段的状态,velX和velY字段都会起作用,然后调用repaint()
    7. 在 GUI 的(JPanel 的)paintComponent 方法覆盖中,使用 velX 和 velY 字段来更改绘制的内容。
    8. 当然,Worker 需要对可视化 GUI 的引用才能正常工作(这一切都需要正确“连接”)。
    9. 您的 main 方法中有一个 Graphics 变量。摆脱它,因为它在那个位置很危险。避免在paintComponent 方法或从paintComponent 中调用的方法之外使用Graphics 对象。避免给你的班级提供图形字段。主要的例外情况是,如果您使用的是从 BufferedImage 中提取的 Graphics 对象。

    成功

    【讨论】:

    • 您能否扩展建议的第 4 步和第 5 步?我开发了一个新类 SwingWorker,但不确定如何格式化受保护的 void 进程(List 块)循环或 getPortText GUI 方法。
    • @JLag:一个相关的例子见here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    相关资源
    最近更新 更多