图形用户界面冻结。当我按下关闭按钮时,我想连续发送到串行端口"1"



我使用的是Processing and Control IP5库,我的代码有问题。当我按下关闭按钮时,我想以3秒的延迟连续发送到串行端口"1",当我按下打开按钮时,我们想再向串行端口"2"发送3秒,但在关闭按钮后,GUI冻结,我无法再按下任何按钮。

import controlP5.*;
import processing.serial.*;
ControlP5 cp5;
Textlabel myTextlabelA;
String serial_list;                // list of serial ports
int serial_list_index = 0;         // currently selected serial port 
int num_serial_ports = 0;  
Serial serial_port = null;        // the serial port
Button b1,b2;
void setup() {
size(800,600);
noStroke();
 cp5 = new ControlP5(this); 
// get the list of serial ports on the computer
serial_list = Serial.list()[serial_list_index];
// get the number of serial ports in the list
 num_serial_ports = Serial.list().length;
myTextlabelA = cp5.addTextlabel("label")
                .setText("Close-Open")
                .setPosition(430,15)
                .setColorValue(0xffffff00)
                .setFont(createFont("Georgia",20))
                ;
Button b1=cp5.addButton("Close")
 .setValue(128)
 .setPosition(400,50)
 .setSize(40, 20)
 .updateSize()
 ;
 Button b2=cp5.addButton("Open")
 .setValue(128)
 .setPosition(500,50)
 .setSize(40, 20)
 .updateSize()
 ;
  Button bUP=cp5.addButton("^") //Up arrow
 .setValue(128)
 .setPosition(140,10)
 .setSize(40, 20)
 .updateSize()
 ;
 Button bDOWN=cp5.addButton("v") //Down arrow
 .setValue(128)
 .setPosition(140,50)
 .setSize(40, 20)
 .updateSize()
 ;
  Button bCONNECT=cp5.addButton("Connect") //Connect button
 .setValue(128)
 .setPosition(190,10)
 .setSize(100, 25)
 .updateSize()
 ;
 Button bDISCONNECT=cp5.addButton("Disconnect") //Disconnect button
 .setValue(128)
 .setPosition(190,45)
 .setSize(100, 25)
 .updateSize()
 ;
 Button bREFRESH=cp5.addButton("Refresh") //Resresh button
 .setValue(128)
 .setPosition(190,80)
 .setSize(100, 25)
 .updateSize()
 ;    
b1.setColorBackground( color( 255,0,0 ) );    //initial b1 color
b2.setColorBackground( color( 128,0,0 ) );   //initial b2 color
bREFRESH.setColorBackground( color (128,128,0) ); //initial Refresh color
b1.setSwitch(true); //convert button to switch 
b1.setOff(); //set True or False
}
 void draw() {
   background(0);
DrawTextBox("Select Port", serial_list, 10, 10, 120, 60);
}
public void controlEvent(ControlEvent theEvent) {
println("Button Pressed:"+theEvent.getController().getName());
if(theEvent.controller().getName()=="^") 
if (serial_list_index > 0) {
  // move one position up in the list of serial ports
  serial_list_index--;
  serial_list = Serial.list()[serial_list_index];
}
if(theEvent.controller().getName()=="v") 
if (serial_list_index > 0) {
  // move one position up in the list of serial ports
  serial_list_index--;
  serial_list = Serial.list()[serial_list_index];
}
 if(theEvent.controller().getName()=="Connect") 
  if (serial_port == null) {
  // connect to the selected serial port
  serial_port = new Serial(this, Serial.list()[serial_list_index], 9600);
  println("Connection Succesfull");
}
if(theEvent.controller().getName()=="Disconnect") 
 if (serial_port != null) {
  // disconnect from the serial port
  serial_port.clear();
  serial_port.stop();
  serial_port = null;
  println("Disonnection Succesfull");
}
if(theEvent.controller().getName()=="Refresh") {
serial_list = Serial.list()[serial_list_index];
num_serial_ports = Serial.list().length;
println("Refresh Succesfull");
}     
if(theEvent.controller().getName()=="Close") 
     if (serial_port != null) {
       while (theEvent.controller().getName()=="Close"){
  // Send 1 to serial port
  serial_port.write(49);
   println("sent 1");
   delay(3000);}
}
if(theEvent.controller().getName()=="Open") 
if (serial_port != null) {
  // Send 2 to serial port
  serial_port.write(50);
   println("sent 2");
}
}
 void DrawTextBox(String title, String str, int x, int y, int w, int h)
{
fill(255);
rect(x, y, w, h);
fill(0);
textAlign(LEFT);
textSize(14);
text(title, x + 10, y + 10, w - 20, 20);
textSize(12);  
text(str, x + 10, y + 40, w - 20, h - 10);
}

编辑:所以@KevinWorkman先生我得出了这样的结论:我从public void controlEvent(ControlEvent theEvent)中提取了代码的一部分,并将其放入draw()中,所以我有了这个:

 void draw() {
 background(0);
 if (mousePressed) {
  timeClicked = millis();
 }
 if (millis() < timeClicked + 1000) {
   // Send 1 to serial port
        serial_port.write(49);
        println("sent 1");
 }
 DrawTextBox("Select Port", serial_list, 10, 10, 120, 60);
 }

但当我尝试连接时,GUI没有响应。我想在mousePressed()中我会命名我想要的事件,但如何做到呢?

从UI线程发送命令。在其他线程中调用发送函数。

您正在冒险进入线程的世界。这是一个相当大的主题,但我会为您简化它:

线程视为一个一次只能做一件事的工作者

处理使用单个线程来绘制内容并处理用户交互。这通常是一件好事,因为这意味着你可以根据用户交互来绘制东西。

但是,您调用的是delay(),它告诉线程等待它在等待时不能做任何其他事情这就是为什么您不能单击任何按钮,并且在等待时屏幕上不会显示任何内容。

最好的办法是重构代码,使其不再依赖于delay()函数。试着使用millis()函数来计时,这样就不会在UI线程上等待了。

您也可以尝试创建另一个线程来在UI线程执行其任务时进行等待,但我不建议您这样做,除非您知道自己在做什么。

编辑:以下是一个使用millis()函数在每次单击时显示1秒椭圆的示例:

int timeClicked = - 10000;
void draw() {
  if (mousePressed) {
    timeClicked = millis();
  }
  background(0);
  if (millis() < timeClicked + 1000) {
    ellipse(50, 50, 50, 50);
  }
}

您必须修改代码以使用类似的逻辑来执行延迟。尝试一下,如果你陷入困境,再问一个问题——别忘了附上MCVE。

最新更新