0

我用 C 语言编写了一个程序,通过蓝牙将电脑与设备连接起来。程序从终端运行,接收到的数据也显示在终端中。到现在为止还挺好。

现在我在 qt 中创建了一个 gui,其主要目的是呈现之前在终端中显示的信息,现在在 qwtplots 中。

好吧,到目前为止,我可以通过 gui 将设备与 pc 连接,但是当我从设备请求信息时,它显示在终端中,但 gui 开始无响应。

这是从设备请求信息的插槽:

// Main Bluetooth
void gui::main_b()
{
    // BLUETOOTH STUFF
    int status, bytes_read;
    int conta = 0;
    FILE *data = NULL;

    fd_set readmask;
    struct timeval tv;
    char buf[101];
    int v, v1, v2;

    tv.tv_sec = 0;
    tv.tv_usec = 100000;

    // Standard messages
    char *startstr = "@START,0060,FF,12;";

    write (sock, startstr, strlen (startstr));

    data = fopen ("data.txt", "w");
    while (conta < 100)
    {
        int i;
        memset (buf, 0, 100);
        FD_ZERO (&readmask);
        FD_SET (sock, &readmask);
        if (select (255, &readmask, NULL, NULL, &tv) > 0)
        {
            if (FD_ISSET (sock, &readmask))
            {
                int numb;
                numb = read (sock, buf, 100);

                // 12 bits
                if (ui->comboBox->currentIndex() == 1)
                {
                    if (numb == 14)
                    {
                        conta++;
                        //printf ("received %d bytes:\n", numb);
                        // print of counter
                        //printf ("%d,", buf[0]);
                        fprintf (data, "%d,", buf[0]);
                        for (i = 1; i < numb-1; i += 3)
                        {
                            v1 = buf[i] | ((buf[i + 1] & 0x0F) << 8);
                            v2 = buf[i + 2];
                            v2 = (v2 << 4) | ((buf[i + 1] & 0xf0) >> 4);
                            printf ("%d,%d,", v1, v2);
                            //fprintf (data, "%d,%d,", v1, v2);
                        }

                        printf ("\n");
                        //fprintf (data, "\n");
                    }
                }
            }
        }
    }
    fclose (data);
}

所以,当我点击调用这个插槽的按钮时,它永远不会让我再次使用 gui。

这适用于终端。

提前致谢。

4

2 回答 2

2

而不是您自己的select,您应该使用QSocketNotifier类并为 Qt 事件循环提供您自己的文件句柄。

您还可以使用此 QFile::open 重载将您的套接字转换为 QIODevice 实例。

第三种选择是将自己的select循环放入不同的线程中,这样就不会阻塞 Qt 主事件循环。但这会带来很多额外的复杂性,所以我只会作为最后的手段。

于 2013-02-11T18:10:59.770 回答
1

您正在while与 GUI 相同的线程中运行循环,因此事件队列被阻塞。你有两个选择:

  • 在循环期间,调用QCoreApplication::processEvents(). 这会强制处理事件队列。
  • 将 while 循环逻辑分离到它自己的线程中。

第一个简单,但通常被认为效率低下,因为几乎所有计算机都有多个内核。

于 2013-02-11T17:32:44.157 回答