Czy jest jakaś praktyczna alternatywa dla modelu Sygnały i gniazda dla programowania GUI?

9

Większość zestawów GUI korzysta obecnie z modelu Sygnały i gniazda. To pionierem był Qt i GTK +, jeśli się nie mylę.

Wiesz, widżety lub obiekty graficzne (czasami nawet te, które nie są wyświetlane) wysyłają sygnały do procedury obsługi głównej pętli. Program obsługi pętli głównej wywołuje następnie zdarzenia , wywołania zwrotne lub gniazda przypisane do tego widgetu / obiektu graficznego. Zazwyczaj istnieją już domyślne (i w większości przypadków virtual) procedury obsługi zdarzeń już dostarczone przez zestaw narzędzi do obsługi wszystkich predefiniowanych sygnałów, dlatego w przeciwieństwie do poprzednich projektów, w których programista musiał napisać całą pętlę główną i procedurę obsługi dla każdej wiadomości osobno (pomyśl WINAPI), programista musi się martwić tylko o sygnały, na których musi zaimplementować nową funkcjonalność.

O ile mi wiadomo, ten projekt jest używany w większości nowoczesnych zestawów narzędzi. Są Qt, GTK +, FLTK itp. Istnieje Java Swing. C # ma nawet funkcję języka (zdarzenia i delegaci), a Windows Forms został opracowany w tym projekcie. W rzeczywistości w ciągu ostatniej dekady ten projekt programowania GUI stał się rodzajem niepisanego standardu. Ponieważ zwiększa wydajność i zapewnia większą abstrakcję.

Moje pytanie brzmi jednak:

Czy istnieje jakiś alternatywny projekt, który jest równoległy lub praktyczny dla nowoczesnego programowania GUI?

tzn. czy projekt Sygnały + automaty jest jedynym praktycznym w mieście? Czy wykonalne jest programowanie GUI przy użyciu innego projektu? Czy są jakieś nowoczesne (najlepiej udane i popularne) zestawy narzędzi GUI oparte na alternatywnym projekcie?

ApprenticeHacker
źródło
Paradygmat kolejki komunikatów znaleziony w interfejsie API systemu Windows nie przypomina zdarzeń i delegatów. Delegaci nazywane są synchronicznie i natychmiast, jak std::function, nie sygnał asynchroniczny. Ponadto WinAPI ma zapewnić DefWindowProcktóry przetwarza wiadomości Windows jako domyślną implementację. Więc założę, że twoje pytanie opiera się na błędnej logice.
DeadMG
2
QT i GTK + są dalekie od stworzenia pierwszych struktur GUI, które wykorzystywały podejście oparte na zdarzeniach. Koncepcja sięga do Smalltalk-80 ( en.wikipedia.org/wiki/Smalltalk ).
Doc Brown
Ciekawe pytanie, jestem ciekawy, czy ten model zmienia się znacznie w przypadku interfejsów wielodotykowych.
Ben DeMott,
Byłbym hojny i zakładam, że wie o SendMessage, który jest synchroniczny, nie tylko PostMessage. Jednak nadal się myli, ponieważ nigdy nie musiałeś pisać całej pętli obsługi wiadomości dla każdej wiadomości.
gbjbaanb
JavaFx zapewnia podobny mechanizm poprzez interfejsy API Bindings.
inż. Czwartek

Odpowiedzi:

5

To mój ulubiony przedmiot i przez około dekadę (lata 70. – 86) myślałem, że posiadanie GUI składającego się z obiektów reagujących na zdarzenia to po prostu właściwy sposób.

Wtedy natknąłem się na inny sposób to zrobić opisane tutaj iz projektu sourceforge tutaj .

W skrócie, problem z obiektami polega na tym, że obiekty się utrzymują, a jeśli piszesz kod, aby je utworzyć, musisz także napisać kod, aby stopniowo je modyfikować, jeśli potrzebne są zmiany, i jakoś otrzymywać wiadomości do nich i od nich. Czy nie byłoby miło, gdybyś mógł po prostu pomalować to, co chcesz, a następnie odmalować, jeśli chcesz czegoś innego i nie martwić się o trwałość wcześniejszych przedmiotów? Czy nie byłoby miło, gdybyś nigdy nie musiał pisać kodu do obsługi wiadomości, ponieważ wszystko odbywa się pod maską?

Tak właśnie działa ten pakiet. W przypadku prostych okien dialogowych zapisuje rząd wielkości w kodzie. Umożliwia to w przypadku złożonych, dynamicznie zmieniających się okien dialogowych.

PS Zrobiłem to tylko dla interfejsów użytkownika pulpitu i interfejsów zdalnych terminali, a nie interfejsów przeglądarki internetowej. Jestem pewien, że to możliwe, ale nie miałem okazji tego spróbować.

Mike Dunlavey
źródło
+1, ale w jaki sposób można uzyskać dodatkową funkcjonalność, na przykład dane zdefiniowane przez użytkownika?
ApprenticeHacker
@IntermediateHacker: Nie jestem pewien, co rozumiesz przez dane zdefiniowane przez użytkownika. Masz na myśli aplikację do projektowania formularzy?
Mike Dunlavey
2

Cóż, można to zrobić na dwa różne sposoby:

  1. Niech każdy widget ujawnia szczegółowy mechanizm subskrybowania (Sygnał / Gniazdo, Obserwator / Obserwowalny, Zdarzenie / Delegat) i poproś, aby kod klienta subskrybował i odpowiednio działał.
  2. Zbudowano widżet w oparciu o abstrakcję prezentowanych danych i kod klienta zaimplementował tę abstrakcję.

Oto przykład drugiego podejścia:

interface Action {
     void execute();
     Bool isEnabled();
     Null<String> description();//used for tooltip
}
interface LabledAction extends Action {
     String getName();
}

A teraz możesz zbudować kod LabelButtona, LabledActiona kod klienta może go po prostu zaimplementować lub użyć domyślnej implementacji ogólnej, jeśli jest dostępna i odpowiednia.

W pewnym sensie drugie podejście jest mniej elastyczne, ale bardziej sztywne. Nie tylko łączysz widok z modelem za pomocą względnie atomowych środków. Projektujesz odpowiedni GUI w oparciu o twoje wymagania, a następnie implementujesz adaptery między tym GUI a logiką domeny / aplikacji.

back2dos
źródło
Model / Widok / Kontroler jest dobry, ale jest tylko rozszerzeniem wzorca obserwatora, ponieważ część kontrolera jest tylko obserwatorem widżetu, aw części modelu widżet jest obserwatorem modelu, więc jest to ten sam mechanizm na odwrót .
Jan Hudec
1

Kilka systemów typu kontrolnego wykorzystuje podejście bazodanowe - każda kontrolka GUI jest połączona z plikiem w bazie danych, dzięki czemu GUI zawsze odzwierciedla stan bazy danych. Haki DB są używane do wyzwalania funkcji, gdy zmienia się wartość.

Martin Beckett
źródło
4
czy to wciąż nie jest gniazdo sygnału tylko z dodatkową warstwą DB?
maniak zapadkowy
Ostatecznie pod to wszystkie przerwania lub wywołania zwrotne - są to operacje asynchroniczne tylko niski poziom
Martin Beckett