C ++中的GTK:根据控制台输入更改标签

时间:2016-04-11 18:45:39

标签: c++ io gtk

为了证明我的意思,我写了这段代码而没有大部分的gtk混乱:

//more gtk declaration stuff above
int access;
access = 0;

int tries;
tries = 0;

string input;
input = "";

string code;
code = "";

while(access != 1 && tries < 4){
    directions((gpointer)lbl); //change label to "type 'finger'"
    cin >> input;

    if(input.compare("finger") = 0){
        while(code.compare("1") != 0 && tries < 4){
            fpcheck((gpointer)lbl); //change label "Enter the secret code ('1')"
            cin >> code;
            if(code.compare("1") != 0){
                retry((gpointer) lbl);//change label "Try again!"
                tries ++;       
            }
            else{
                fprecog((gpointer) lbl); //change label "Recognized!"
                access = 1;
            }
        }
    }
}
if(access = 1)
    //change label "Access Granted!"
else
    //change label "No access."

gtk_main();
return 0;

显然这不会完全奏效,因为gtk_main()没有被调用到最后。控制台的东西运行正常,但窗口不会弹出,直到最后,所以用户不知道该怎么做,如果我早期把gtk_main(),程序卡在gtk_main()循环所以什么都不会发生。

这种流程通常如何在GTK中实现?我已经尝试了一些gtk_thread的东西来突破main,但这显然已被弃用,所以我试图不使用它。

输入必须由不是gtk_main()的线程读取,因为输入不是来自GUI。实际上,它将是一个插入beaglebone黑色的设备,但我认为这是一个更简单的类似情况。

将使用的实际输入方法是1)指纹传感器,它通过UART通道根据发送和接收的字节执行操作,2)使用OpenCV方法在BeagleBone Black上运行的usb相机和面部识别脚本Debian,联网到笔记本电脑做强化opencv的东西。目前我只想尝试使用FP传感器。使用我们的接口,我们可以调用FP传感器方法,该方法返回一个int,并根据该int做一些事情。

我需要能够根据返回的int更改GTK标签,然后在标签显示后调用另一个方法。

以下是我正在尝试集成的代码的片段:

while(key != 'x')
    {
        imshow("main_display", welcome);
        key = waitKey(1);  //poll keyboard at active screen

        //key = getkey();  //TODO: poll from TFT instead

        switch(key)
        {
            case 'i': //Identify User
                imshow("main_display", press_finger);
                waitKey(1);
                printf("\n---IDENTIFY USER---\n");
                post_log(1, 0);

                do_reg = true;
                Ret = GT_LED_On(LS);
                printf("\nPress Finger");

                //something to force console text before loop starts...?

                Timer.InitTimer();
                while(GT_IsPressFinger(LS) == 0 && ((Timer.ElapsedTime_ms() < TIMEOUT))) {}
                if(Timer.ElapsedTime_ms() >= TIMEOUT)
                {
                    printf("\nCapture TIMEOUT\n");
                    Ret = GT_LED_Off(LS);
                    post_log(6, user_id);
                    imshow("main_display", fps_timeout);
                    waitKey(1000);
                    do_reg = false;
                    break;  //??????????????????????????? GOTO???
                }
                printf("\nCapturing...Standby...\n");
                imshow("main_display", hold_finger);
                waitKey(1);
                Ret = GT_CaptureFinger(LS, 0);

基本上我们不是使用imshow()而是尝试使用实际的GUI框架,并且由于OpenCV设备已经有GTK,所以坚持使用GTK会很不错。这个控制台问题试图弄清楚如何在简单的上下文中将imshow()替换为gtk窗口的标签更改。

2 个答案:

答案 0 :(得分:1)

我认为您正在寻找的是Glib IO Channel。如果将此绑定到标准输入文件描述符,则在用户按Enter键时会触发该信号。然后你应该能够使用cin来获取文本。

如果您打算获取某种类型的密码,可以考虑使用using a dialog来捕获用户输入。

答案 1 :(得分:0)

好吧,在Blake的帮助下,我想我找到了一个解决方案,但我不知道它是否是最好的解决方案。

为了在gtk_main()发生时获取输入,并在发生这种情况时调用函数,我在标准输入文件描述符上添加了一个glib io调用来检测cin样式输入。我使用其他代码作为回调函数。感谢Blake对这部分的帮助。

然后,为了实际更新这个新的迷你线程中的文本,我创建了一个update()函数来调用main_iteration(),同时循环通过gtk_main()一次。 Here's documentation on that.我不知道这是否安全使用,或者是否有更好的解决方案,但该程序现在可以执行我想要的操作。

以下是完整的代码供将来参考。

#include <gtk/gtk.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <glib.h>


using namespace std;

void update(){
while (gtk_events_pending ())
gtk_main_iteration ();}

void fpcheck(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window) {
    gchar const *text = "<span font='32' weight='bold' color='#DDDDDD'>Enter the Secret\nCode. ('1')</span>";
    gtk_label_set_markup(GTK_LABEL(window), text);
}

void fprecog(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window) {
    gchar const *text2 = "<span font='32' weight='bold' color='#DDDDDD'>Fingerprint Recognized!</span>";
    gtk_label_set_markup(GTK_LABEL(window), text2);
}

void directions(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window){
    gchar const *text3 = "<span font='32' weight='bold' color='#DDDDDD'>Type 'finger'.</span>";
    gtk_label_set_markup(GTK_LABEL(window), text3);
}

void retry(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window){
    gchar const *text4 = "<span font='32' weight='bold' color='#DDDDDD'>Try Again.</span>";
    gtk_label_set_markup(GTK_LABEL(window), text4);
}

void accessed(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window){
    gchar const *text5 = "<span font='32' weight='bold' color='#DDDDDD'>Access Granted!</span>";
    gtk_label_set_markup(GTK_LABEL(window), text5);
}

void denied(/*GtkWidget *widget, GdkEvent *event,*/ gpointer window){
    gchar const *text6 = "<span font='32' weight='bold' color='#DDDDDD'>Access Denied.</span>";
    gtk_label_set_markup(GTK_LABEL(window), text6);
}


gboolean callback(GIOChannel *gio, GIOCondition condition, gpointer lbl){
    int access;
    access = 0;

    int tries;
    tries = 0;

    string input;
    input = "";

    string code;
    code = "";

    while(access != 1 && tries < 4){
        directions((gpointer)lbl); //change label to "type 'finger'"
        update();
        cin >> input;

        if(input.compare("finger") == 0){
            while(code.compare("1") != 0 && tries < 4){
                fpcheck((gpointer)lbl); //change label "Enter the secret code ('1')"
                update();
                cin >> code;
                if(code.compare("1") != 0){
                    retry((gpointer) lbl);//change label "Try again!"
                    update();
                    tries ++;       
                }
                else{
                    fprecog((gpointer) lbl); //change label "Recognized!"
                    update();
                    access = 1;
                }
            }
        }
    }
    if(access == 1)
        accessed((gpointer)lbl);
        //change label "Access Granted!"
    else
        denied((gpointer)lbl);
        //change label "No access."
}


int main(int argc, char *argv[]){

    GtkWidget *window; //main window
    GtkWidget *lbl; //text
    GdkColor color = {0, 0x0, 0x0, 0x0}; //window color

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //init window
    //gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); //window pos on screen
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE); //user cant resize //doesnt work
    //gtk_window_set_default_size(GTK_WINDOW(window), 800, 480); //window size

    gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); //set color to window
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE); //borderless
    gtk_widget_show(window);

    lbl = gtk_label_new(NULL); //label init
    gtk_container_add(GTK_CONTAINER(window), lbl);
    gtk_widget_set_size_request(lbl,800,480); //sets area that text can be //breaks alignment
    gtk_misc_set_alignment(GTK_MISC(lbl), .5, .5); //alignment
    gtk_label_set_line_wrap_mode(GTK_LABEL(lbl), PANGO_WRAP_WORD_CHAR); //sets line wrap on

    gchar const *str = "<span font='32' weight='bold' color='#DDDDDD'>Press Enter to begin.</span>"; //label text, uses pango markup
    gtk_label_set_markup(GTK_LABEL(lbl), str); //add pango str to label
    gtk_label_set_angle(GTK_LABEL(lbl), -90);

    gtk_widget_show(lbl);

    //fpcheck((gpointer)lbl);
    //g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(fpcheck), (gpointer) lbl); //calls fpcheck to change label 
    //g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(fprecog), (gpointer) lbl);     
    //fprecog((gpointer)lbl);

    g_signal_connect(G_OBJECT(window), "destroy",
    G_CALLBACK(gtk_main_quit), NULL);

    //gtk_widget_show_all(window); //build the window all at once

    //label says "Ready"

    GIOChannel *gio;
    gio = g_io_channel_unix_new(STDIN_FILENO);
    guint ret;
    ret = g_io_add_watch(gio, G_IO_IN, callback, (gpointer)lbl);

    gtk_main();

    return 0;
}