将 JFrame 与连续输入流一起使用 [英] Using JFrame with a Continuous Input Stream

查看:17
本文介绍了将 JFrame 与连续输入流一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement code which reads from my redboard's serial port and based on what it reads have it repaint a circle. The end goal of this is to use the Robot class to achieve actual cursor control, but I first want to learn more about Java along the way and so I'm trying to achieve it with some basic graphics first.

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

To summarize my issue, I do not know how to use JFrame with a continuously changing input from a static method.

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

The serial port accessing JAR can be found at http://fazecast.github.io/jSerialComm/

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

The Arduino continuously writes to the serial based on an FPGA-accelerometer system in the form "UpLeft", "Up", "UpRight", "Left", "Center", "Right", "DownLeft", "Down", "DownRight". The Java program should then grab this and repaint a circle accordingly.

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

I am able to open COMM3 and print the correct direction received from my hardware, but whenever I try to apply JFrame I get lost. I've found many ActionListener tutorials, but this implementation should be continuous and not dependent on mouse or keyboard events. Thus, I don't know how to use the paintComponent() and painter() methods since the main method is static.

非常感谢您的时间!

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) {};
        }
    }
}

推荐答案

建议:

  1. 从静态 main 方法中读取 InputStream 并读取到它自己的类中.
  2. 这个类应该扩展SwingWorker.您必须阅读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 chunks) 方法覆盖.使用 for 循环遍历块 List,通过调用 GUI 的 getPortText(...) 方法将数据传递到 Swing GUI.
  6. 在GUI的getPortText方法中,改变GUI类某个字段的状态,velX和velY字段会起作用,然后调用repaint()
  7. 在 GUI (JPanel) 的paintComponent 方法覆盖中,使用velX 和velY 字段来更改绘制的内容.
  8. 当然,Worker 需要引用可视化 GUI 才能正常工作(这一切都需要正确连接").
  9. 您的主要方法中有一个 Graphics 变量.摆脱它,因为它在那个位置很危险.避免在paintComponent 方法或从paintComponent 内部调用的方法之外使用Graphics 对象.避免为您的类提供 Graphics 字段.对此的主要例外是,如果您使用从 BufferedImage 中提取的 Graphics 对象.
  1. Get the reading of the InputStream out of the static main method and into its own class.
  2. This class should extend SwingWorker<Void, String>. You MUST read the Concurrency in Swing tutorial to understand fully how to use this class. It will help you do the long-running stream reading within a background thread and then safely pass the data obtained into the Swing GUI on the Swing event thread.
  3. All the reading from the stream should be done within this class's doInBackground() method. Get the String from the Scanner/Stream, and call the worker's publish(...) method passing the String into this method.
  4. Give your Swing GUI a public method, say public void getPortText(String text)
  5. Within the Worker use a protected void process(List<String> chunks) method override. Iterate through the chunks List<String> with a for loop, passing the data into your Swing GUI by calling the GUI's getPortText(...) method.
  6. In the GUI's getPortText method, change the state of a field of the GUI class, the velX and velY fields would work, and then call repaint()
  7. In the GUI's (JPanel's) paintComponent method override, use the velX and velY fields to change what is drawn.
  8. Of course the Worker will need a reference to the visualized GUI for this to work right (it all needs to be "wired" correctly).
  9. Your main method has a Graphics variable within it. Get rid of it as it's dangerous in that location. Avoid using a Graphics object outside of a paintComponent method or method called from within paintComponent. Avoid giving your class Graphics fields. The main exception to this is if you're using a Graphics object extracted from a BufferedImage.

成功

这篇关于将 JFrame 与连续输入流一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆