Własne pola wprowadzania tekstu i ich dziwna synchronizacja.

0

Cześć!
Napisałem własny obiekt tworzący pole wprowadzania tekstu. Wszystko fajnie działa dopóki mam tylko jedno takie pole w oknie, gdy dodam drugie i więcej zaczyna się dziać coś dziwnego - bez względu na to, w którym oknie wprowadzam tekst, w tym samym czasie wprowadza się on samoistnie do pozostałych (czarne "1" i "0" pokazują, czy pole jest aktywne)
user image

Przejechałem kod wzdłuż i wszerz, ale modyfikacje nic nie dały. Myślałem, że to problem z kolejką event-ów, ale czyszczenie jej pomiędzy wyświetleniami pól nic nie daje. W dodatku nie jest to chyba problem funkcji show(),bo po zakomentowaniu jej wywoływania w polu dodanym jako drugie i o różnych stanach początkowych tj. pierwsze pole = "aa", drugie = "pp", to i tak pierwsze pole zmienia się na "pp".
Nie mam już pomysłów, może Wy na coś wpadniecie. Z góry dzięki.

Text_Input.h:

///***IMPORTANT***///
//requires al_init_font_addon(void) & al_init_ttf_addon(void) initialised
//installs mouse if not already installed

#pragma once
#include <allegro5/allegro.h>
#include <string>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <png.h>
#include "Simple_Button.h"
#include "Fatal_Error_Message_Box.h"
#include "C11String.h"

using namespace std;

class Text_Input{
    string text, limit;
    Simple_Button *enter=NULL;
    bool is_active=false, letter_insert=true, cursor_beep, too_many_characters=false, too_long=false, enter_active;
    int Width, Height, Max_lines, Line=0, Font_Size, _is_shown=1;
    unsigned Limit_of_characters, shown_text_shift=0;
    ALLEGRO_FONT *font;
    ALLEGRO_FONT *font_mini;
    ALLEGRO_USTR *input;
    ALLEGRO_COLOR bg_color=al_map_rgb(227,231,230);
    ALLEGRO_COLOR frame_and_button;
    ALLEGRO_MOUSE_STATE ms_state;
    ALLEGRO_TIMER *timer=NULL;
    ALLEGRO_EVENT_QUEUE *event_queue = NULL;
    ALLEGRO_EVENT event0;
    void add_char();
public:
    Text_Input(int width, int haight, ALLEGRO_COLOR FrameAndButtonColor, string Font_path,unsigned character_limit, string AlreadyInside, bool Enter_Active, bool EnterButton);
    ~Text_Input();
    void show(int PosX, int PosY);
    string Text_return();
};
///***IMPORTANT***///
//requires al_init_font_addon(void) & al_init_ttf_addon(void) initialised
//installs mouse if not already installed

#include "Text_Input.h"

Text_Input::Text_Input(int width=0, int height=0, ALLEGRO_COLOR FrameAndButtonColor=al_map_rgb(0,0,255), string Font_path="arial.ttf",unsigned character_limit=0, string AlreadyInside="", bool Enter_Active=false, bool EnterButton=true){
    enter_active=Enter_Active;
    frame_and_button=FrameAndButtonColor;
    input = al_ustr_new(AlreadyInside.c_str());
    Limit_of_characters=character_limit;
    limit= "Limit znaków: "+to_string(character_limit);
    Width=width;
    Height=height;

    if(EnterButton==true) enter=new Simple_Button(30, Height+0.5, "►", frame_and_button, al_map_rgb(255,255,255), "arial.ttf", 24 ,&_reverse, &_is_shown, NULL);

    font=al_load_font(Font_path.c_str(), Height-8, 0);
    font_mini=al_load_font(Font_path.c_str(), 10, 0);
    if(!font || !font_mini){
      throw Fatal_Error_Message_Box("Problem z ładowaniem "+Font_path);
    }

    Font_Size=al_get_font_line_height(font);

    al_ustr_to_buffer(input,(char*)text.c_str(), Limit_of_characters+1);

    event_queue = al_create_event_queue();
    al_register_event_source(event_queue, al_get_keyboard_event_source());
    timer=al_create_timer(0.1);
    al_start_timer(timer);
}

void Text_Input::show(int PosX, int PosY){
    if(!al_is_mouse_installed()) al_install_mouse();
    al_get_mouse_state(&ms_state);

    al_draw_text(font, al_color_name("black"), Width+PosX+40,PosY, 0,to_string(is_active).c_str()); //test aktywności pola

    if(_is_shown==true){
        al_draw_filled_rectangle(PosX+0.5, PosY+0.5, Width+PosX+0.5, Height+PosY+0.5,bg_color);
        al_draw_rectangle(PosX+0.5, PosY+0.5, Width+PosX+0.5, Height+PosY+0.5,frame_and_button, 1);
        al_draw_text(font, al_map_rgb(0,0,0), PosX+1, (Height-Font_Size)/2+PosY+1, ALLEGRO_ALIGN_LEFT, text.c_str());

        if(is_active==true){
            al_get_next_event(event_queue, &event0);
            add_char();

            if(too_many_characters==true)
                al_draw_text(font_mini, al_map_rgb(195,68,68), PosX+1, PosY+Height, ALLEGRO_ALIGN_LEFT, limit.c_str());
            else if(too_long==true)
                al_draw_text(font_mini, al_map_rgb(195,68,68), PosX+1, PosY+Height, ALLEGRO_ALIGN_LEFT, "Tekst zbyt długi!");

            if(al_get_timer_count(timer)<=5 || event0.type==ALLEGRO_EVENT_KEY_CHAR) cursor_beep=true;
            else if(al_get_timer_count(timer)>10){
                al_set_timer_count(timer, 0);
                cursor_beep=false;
            }
            else cursor_beep=false;

            if(cursor_beep==true) al_draw_line(PosX+al_get_text_width(font, text.c_str())+1+0.5, PosY+1+0.5, PosX+al_get_text_width(font, text.c_str())+1+0.5, PosY+Height-2+1+0.5, al_map_rgb(0,0,0), 1);
        }

        if(ms_state.buttons==1 && ms_state.x>PosX && ms_state.x<PosX+Width && ms_state.y>PosY && ms_state.y<PosY+Height)
            is_active=true;
        else if(ms_state.buttons==1) is_active=false;

        if(text[0]==0 && enter!=NULL) enter->is_active=false;
        else if(enter!=NULL) if(enter->is_active==false) enter->is_active=true;

        if(enter!=NULL)enter->show(PosX+Width+1, PosY);
    }
    else is_active=0; //Jesli nie jest widoczny to nie jest tez aktywny
}

void Text_Input::add_char(){
        if(event0.type==ALLEGRO_EVENT_KEY_CHAR){

            int unichar = event0.keyboard.unichar;

            if((al_get_text_width(font, text.c_str())+al_get_text_width(font, "W"))>Width){
                too_long=true;
                bg_color=al_map_rgb(195,68,68);
            }

            if(event0.keyboard.keycode==ALLEGRO_KEY_BACKSPACE && letter_insert==true){
                if(al_ustr_get(input, al_ustr_size(input)-1)<0) //usuwanie znakow spoza ASCII
                    al_ustr_remove_range(input, al_ustr_size(input)-2, al_ustr_size(input));
                else al_ustr_remove_chr(input, al_ustr_size(input)-1); //zwyklae usuwanie

                too_many_characters=false;
                too_long=false;
            }
            else if(event0.keyboard.keycode==ALLEGRO_KEY_ENTER && letter_insert==true && enter_active==true){
                _is_shown=false;
                too_many_characters=false;
                too_long=false;
            }
            else if (unichar >= 32 && al_ustr_size(input)<Limit_of_characters && too_long==false && letter_insert==true){
                too_many_characters=false;
                al_ustr_append_chr(input, unichar);
            }
            else if(al_ustr_size(input)+1>Limit_of_characters){
                too_many_characters=true;
                bg_color=al_map_rgb(195,68,68);
            }
            text.clear();
            al_ustr_to_buffer(input,(char*)text.c_str(), Limit_of_characters+1);
            letter_insert=false;
        }
        else bg_color=al_map_rgb(227,231,230); //pole czerwone podczas naciskania klawisza i osiągnietego limitu znakow

        if(event0.type!=ALLEGRO_EVENT_KEY_CHAR){
            letter_insert=true;
        }
}

Text_Input::~Text_Input(){
    delete enter;
    al_destroy_font(font);
    al_destroy_font(font_mini);
    al_destroy_timer(timer);
    al_ustr_free(input);
    al_destroy_event_queue(event_queue);
}

string Text_Input::Text_return(){
    return text;
}
0

Ok udało mi się (w razie gdyby ktoś miał ten sam problem). Nie wiem dlaczego, ale było to powodowane eksportowaniem ALLEGRO_USTR do string-a i dopiero wtedy wyświetlaniem. Usunięcie string-a i operowanie wyłącznie na ALLEGRO_USTR naprawiło błąd, chociaż do tej pory nie wiem dlaczego tak się działo ;)

0

ale krzaki :O
niestety kursy allegro uczą takiego złego stylu kodowania.
dobra rada: dziel metody/funkcje na mniejsze, zawierające maksymalnie 3 instrukcje sterujące (najlepiej jakbyś się mieścił w 15 linijkach).

0

Faktycznie jakiś czas po napisaniu jakiegoś bardziej złożonego kodu trudno się w nim połapać, spróbuję dzielić na mniejsze :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1