将JFrame与连续输入流一起使用 [英] Using JFrame with a Continuous Input Stream
问题描述
我正在尝试实现从红板的串行端口读取的代码,并根据读取的内容重新绘制一个圆圈。这样做的最终目的是使用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) {};
}
}
}
推荐答案
建议:
- 从静态main方法中读取InputStream并将其读取到其自己的类中。
- 此类应扩展
SwingWorker< Void,String>
。您必须阅读 Swing中的并发一个>教程,以充分理解如何使用此类。这将帮助您在后台线程中进行长时间运行的流读取,然后将获取的数据安全地传递到Swing事件线程上的Swing GUI中。 - 所有来自流的读取都应在此类的
doInBackground()
方法内完成。从扫描程序/流获取字符串,然后调用工作程序的publish(...)
方法,将字符串传递给该方法。 - 为您的Swing GUI提供一个公共方法,例如
public void getPortText(String text)
- 在Worker中使用
受保护的无效过程(List< String>块)
方法覆盖。通过for循环遍历List< String>
块,通过调用GUI的getPortText(...)<将数据传递到Swing GUI中/ code>方法。
- 在GUI的getPortText方法中,更改GUI类的字段的状态,velX和velY字段将起作用,然后调用
repaint()
- 在GUI(JPanel)的paintComponent方法重写中,使用velX和velY字段更改绘制的内容。
- 当然,工作人员需要引用可视化的GUI才能正常工作(所有这些都需要正确连接)。
- 您的主要方法其中包含一个Graphics变量。摆脱它,因为它在那个位置很危险。避免在paintComponent方法之外或在paintComponent中调用的方法之外使用Graphics对象。避免给您的班图形字段。主要的例外情况是,如果您使用的是从BufferedImage中提取的Graphics对象。
- Get the reading of the InputStream out of the static main method and into its own class.
- 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. - 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'spublish(...)
method passing the String into this method. - Give your Swing GUI a public method, say
public void getPortText(String text)
- Within the Worker use a
protected void process(List<String> chunks)
method override. Iterate through the chunksList<String>
with a for loop, passing the data into your Swing GUI by calling the GUI'sgetPortText(...)
method. - 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()
- In the GUI's (JPanel's) paintComponent method override, use the velX and velY fields to change what is drawn.
- Of course the Worker will need a reference to the visualized GUI for this to work right (it all needs to be "wired" correctly).
- 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屋!