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

查看:94
本文介绍了将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// <中找到/ a>

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

Arduino继续基于FPGA加速度计系统以 UpLeft, Up, UpRight, Left的形式写入串行,居中,右, DownLeft, Down, DownRight。然后,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()方法。

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.

非常感谢您的宝贵时间! / p>

Thank you very much for your time!

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< Void,String> 。您必须阅读 Swing中的并发教程,以充分理解如何使用此类。这将帮助您在后台线程中进行长时间运行的流读取,然后将获取的数据安全地传递到Swing事件线程上的Swing GUI中。

  3. 所有来自流的读取都应在此类的 doInBackground()方法内完成。从扫描程序/流获取字符串,然后调用工作程序的 publish(...)方法,将字符串传递给该方法。

  4. 为您的Swing GUI提供一个公共方法,例如 public void getPortText(String text)

  5. 在Worker中使用受保护的无效过程(List< String>块)方法覆盖。通过for循环遍历 List< String> 块,通过调用GUI的 getPortText(...)<将数据传递到Swing GUI中/ code>方法。

  6. 在GUI的getPortText方法中,更改GUI类的字段的状态,velX和velY字段将起作用,然后调用 repaint()

  7. 在GUI(JPanel)的paintComponent方法重写中,使用velX和velY字段更改绘制的内容。

  8. 当然,工作人员需要引用可视化的GUI才能正常工作(所有这些都需要正确连接)。

  9. 您的主要方法其中包含一个Graphics变量。摆脱它,因为它在那个位置很危险。避免在paintComponent方法之外或在paintComponent中调用的方法之外使用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天全站免登陆