Créer une bibliothèque graphique à partir de zéro - page 3

 
Maxim Kuznetsov:

En bref, à propos de l'ingénierie :

Si l'on souhaite améliorer un certain "A" par un réaménagement, il est nécessaire de préciser ses faiblesses critiques. Il suffit d'en faire la liste et d'expliquer pourquoi ils sont intraitables dans le développement évolutif de "A".

En revanche, personne ne l'interdit. Si vous aimez écrire du code, écrivez-le. Réécrivez "A" mais à votre façon, mais ce sera nouveau.

Max, salut !

J'ai déjà décrit à plusieurs reprises les "défauts" que, de mon point de vue, je vois dans la bibliothèque standard et dans la bibliothèque d'Anatoly.

Ces deux bibliothèques présentent, à mon avis, un inconvénient majeur : l'interface est construite sur des objets graphiques distincts, c'est-à-dire que plus il y a de contrôles dans l'interface, plus il y a d'objets isolés dans le graphique lui-même. D'un côté, cela ne semble pas être un problème, mais d'un autre côté, c'est un problème avec les boîtes de dialogue glisser-déposer, car ce n'est pas un seul objet "formulaire avec éléments" qui est glissé et déposé, mais plusieurs éléments différents. Et cela consomme des ressources supplémentaires.

La bibliothèque d'Anatoly est très chic, mais elle est complexe dans sa composition et difficile à intégrer dans le programme principal. Et la bibliothèque standard est limitée dans les contrôles eux-mêmes, bien que l'architecture originale soit très bonne à mon avis.

En fait, la meilleure solution serait ce que Petr Konov essaie de faire : un constructeur d'interface graphique avec génération de code d'interface graphique, mais avec un modèle d'événement étendu, de sorte que lors de l'intégration avec le programme principal, vous n'auriez pas besoin de vous lancer dans un énorme code d'interface graphique (quelque chose comme l'analogie MVVM), et bien sûr avec des objets que les utilisateurs pourraient développer par eux-mêmes.

 
Алексей Барбашин:

Max, salut !

Eh bien, j'ai déjà décrit à plusieurs reprises les "lacunes" que, de mon point de vue, je vois dans la bibliothèque standard et dans la bibliothèque d'Anatoly.

Ces deux bibliothèques présentent, à mon avis, un inconvénient majeur : l'interface est construite sur des objets graphiques distincts, c'est-à-dire que plus il y a de contrôles dans l'interface, plus il y a d'objets isolés dans le graphique lui-même. D'un côté, cela ne semble pas être un problème, mais d'un autre côté, c'est un problème avec les boîtes de dialogue glisser-déposer, car ce n'est pas un seul objet "formulaire avec éléments" qui est glissé et déposé, mais plusieurs éléments différents. Et cela consomme des ressources supplémentaires.

La bibliothèque d'Anatoly est très chic, mais elle est complexe dans sa composition et difficile à intégrer dans le programme principal. Et la bibliothèque standard est limitée dans les contrôles eux-mêmes, bien que l'architecture originale soit très bonne à mon avis.

En fait, la meilleure solution serait ce que Petr Konov essaie de faire : un constructeur d'interface graphique avec génération de code d'interface graphique, mais avec un modèle d'événement étendu, de sorte que lors de l'intégration avec le programme principal, vous ne devez pas entrer dans un énorme code d'interface graphique, et bien sûr avec des objets que les utilisateurs pourraient étendre par eux-mêmes.

la citation doit être lue de bas en haut. Le bas (ce qui est souligné) est plus important. C'est l'élément déterminant.

Avec tout le développement moderne de toutes les interfaces humaines, il est plutôt surprenant de voir les vues coordonnées et les éléments de formulaire au premier plan.
En même temps, tout le monde utilise des navigateurs avec Rest/Ajax, sait ce qu'est MVC, mais ne pense pas à l'interface entre le conseiller expert et son interface graphique.

Si le modèle est décrit et qu'il existe un protocole pour travailler avec lui, l'interface graphique peut être n'importe quoi et ne dépend pas du conseiller expert. C'est une sorte de chose maléfique, maléfique, maléfique de mettre des fenêtres dans le conseiller expert. Le principal objectif des conseillers experts est de négocier, tout le reste doit être retiré du code principal et être facultatif.

 
Maxim Kuznetsov:

la citation doit être lue correctement de bas en haut. Le bas (ce qui est souligné) est plus important. C'est l'élément déterminant.

Avec tout le développement moderne de l'interface humaine, il est assez surprenant de voir les représentations de coordonnées et les éléments de forme au premier plan.
En même temps, tout le monde utilise des navigateurs avec Rest/Ajax, sait ce qu'est MVC, mais ne pense pas à l'interface entre le conseiller expert et son interface graphique.

Si le modèle est décrit et qu'il existe un protocole pour travailler avec lui, l'interface graphique peut être n'importe quoi et ne dépend pas du conseiller expert. C'est une sorte de mal quand on met une boîte dans le conseiller expert. Le principal objectif des conseillers experts est de négocier, tout le reste doit être retiré du code principal et être facultatif.

Je pense que nous devons supposer que, dès le début, les développeurs n'ont pas pensé au fait que la fonctionnalité des interfaces pourrait être nécessaire. Si vous vous souvenez, au début, il n'y avait même pas de POO dans mql, son but principal était seulement d'écrire des indicateurs et tout était conçu pour cela.

Et maintenant nous voyons que mql a déjà travaillé avec des sockets et des bases de données, même au niveau du noyau... Mais les mécanismes d'interaction entre l'utilisateur et le programme sont laissés de côté.

Les développeurs eux-mêmes ont déclaré il y a presque dix ans que le développement d'interfaces est un mécanisme très important d'interaction entre l'utilisateur et l'application et ont développé une bibliothèque standard pour ce cas, mais seulement son applicabilité aux tâches n'ont pas montré et en fait, même aujourd'hui, de nombreux programmeurs ne sont pas conscients de son existence.

Nous allons essayer d'éliminer les lacunes. Même si les autres participants n'en auront pas besoin, une certaine expérience sera tout de même acquise.

 
Alexandr Andreev:

J'ai commencé avec votre bibliothèque, je vous en remercie, puis je l'ai un peu modifiée, puis un peu plus, puis encore un peu plus)))) tout changé, y compris les fonctions de ligne réécrites, également la fonction de ligne large de la source Kanvas, supprimé les fausses fonctions, mis le stub sur l'événement. pas encore complètement disparu de la structure W, bien qu'il ne reste pas grand chose là non plus. J'ai ajouté le calcul de la barre à gauche et à droite par recherche binaire parmi d'autres éléments et j'ai également ajouté la recherche binaire elle-même avec la possibilité de choisir une valeur plus grande ou plus petite. J'ai également ajouté la possibilité de construire à partir de tableaux de toutes sortes (séries temporelles/communes) et j'en suis arrivé à la conclusion que je devais modifier construct)))))).

Cool.

Oui, les bibliothèques doivent être soit universelles pour les programmeurs novices, soit plus ciblées pour les plus avancés.

J'ai moi-même plusieurs versions de mon propre iCanvas pour différents usages.

C'est pourquoi j'ai commencé à dresser une liste d'intentions et d'objectifs, ou du moins à indiquer la direction à suivre. Et mettez cette liste dans le premier message tant qu'elle est disponible pour l'édition.

 
//whats TD (template define)? because TT is busy
//почемуто этот код в шаблонах на мкл не хочет компилироваться поэтому через дефайн - это Плохо надо бы через шаблоны как то придумать.... привет метаквотам
#define  TD1 int
#define  TD2 double 
#define  EMPY -1 
#define  GET this.operator>> 
#define  SET this.operator<< 
class CCoordD; 
class CSizeD;
class CCoordBaseD //полностью внутрений класс
   {
   private:
   #define  ME CCoordBaseD 
   TEMPL1(T)
   bool Chek(T *a)                  {return CheckPointer(a)!=POINTER_INVALID;}
   TEMPL1(T)
   bool Chek(T a)                   {return a!=(T)EMPY;}
   TD1 Error()                      {Print(__FUNCTION__," ",__LINE__," POINTER_INVALID size"); int a[]; a[0]=0; return (TD1)EMPY;};//wtf??? =P CRASH Error
   TD1 GetA()                       {return c.GetA()+ar;}
   TD1 GetP()                       {return c.Result() + size.GetP()*(TD1)pr;}
   public:
   ME()                                   {Init();} 
   ME(TD1 a)                              {Init(a);} 
   ME(TD1 a,CCoordD &b)                   {Init(a,b);} 
   ME(TD1 a,CCoordD &b,CSizeD &x)         {Init(a,b,x);} 
   ME(TD2 a,CSizeD &b)                    {Init(a,b);} 
   ME(TD2 a,CCoordD &b,CSizeD &x)         {Init(a,b,x);} 
   CCoordD *c;//one coord
   CSizeD *size;//size 
   TD1 ar;
   TD2 pr;//percent проценты
   void Init()                            {ar=(TD1)EMPY; pr=(TD2)EMPY; }  
   TD1 Result()                           {return Chek(ar)?Chek(c)?GetA():ar:Chek(pr)?Chek(size)?GetP():Error():(TD1)EMPY;}
   ME *GetMe()                            {return &this;}
   ME *GetCoorBase()                      {return c;}
   ME *GetSizeBase()                      {return size;} 
   CCoordD *GetCoor()                     {return c;}
   CSizeD *GetSize()                      {return size;} 
   void Init(TD1 a)                       {Init(); SET(a);}
   void Init(TD1 a,CCoordD &b)            {Init(); SET(a); SET(b);}
   void Init(TD1 a,CCoordD &b,CSizeD &x)  {Init(); SET(a); SET(b); SET(x);}
 //  void Init(TD2 p)                     {Init(); pr=p_;}
   void Init(TD2 a,CSizeD &b)             {Init(); SET(a); SET(b);}
   void Init(TD2 a,CCoordD &b,CSizeD &x)  {Init(); SET(a); SET(b); SET(x);}
   void operator >> (TD1 &a)              {a=ar;} 
   void operator >> (TD2 &a)              {a=pr;}  
   void operator >> (CCoordD &a)          {a=GetPointer(c);}  
   void operator >> (CSizeD &s)           {s=GetPointer(size);}  
   void operator << (TD1 &a)              {ar=a;} 
   void operator << (TD2 &a)              {pr=a;}  
   void operator << (CCoordD &a)          {c=GetPointer(a);}  
   void operator << (CSizeD &s)           {size=GetPointer(s);}  
   void operator << (ME &a)               {a>>c; a>>ar; a>>pr; a>>size;}  
   void operator = (CCoordD &a)           {SET(a);}
   void operator = (CSizeD &a)            {SET(a);}
   void operator = (ME &a)                {SET(a);} 
   #undef  ME
   #undef  TD1
   #undef  TD2
   #undef  GET 
   #undef  SET
   };
   
class CSizeD : public CCoordBaseD
   {
   public:
   CSizeD(){};
   };
   
class CCoordD : public CCoordBaseD
   {
   public:
   CCoordD(){};
   };

class CTX {public:CTX(){}}; 
class CTY {public:CTY(){}};
class CTZ {public:CTZ(){}};
TEMPL(T)
class CCoordA : public T
   {
   public:
   CCoordA() {};
   CSizeD size;
   CCoordD ar; 
   void operator <<(CSizeD &a)   {return ;}
   void operator <<(CCoordD &a)  {return ;}
   };
   
class CCoord
   {  
   public: 
   CCoordA<CTX> X;
   CCoordA<CTY> Y; 
   CCoord ()                              {} 
   bool MouseOn(CMouse &mouse)//px
      {
      //return X.ar.Result()<=mouse.X && X.ar.Result()+X.size.Result()>=mouse.X && GetY()<=mouse.Y && GetY()+GetH()>=mouse.Y;
      return false;
      }
   };  
 

Quoi qu'il en soit, soit je fais quelque chose de mal, soit les modèles de déclaration de classe (vides) ne veulent pas fonctionner. Ce qui fait que le code n'est pas particulièrement pratique.

Je pense changer

 
Un si beau code serait une bonne idée pour l'emmener à une exposition. On ne sait pas à quoi il sert, comment et ce qu'il résout, mais il est très beau...
 
Les gars, puisque vous m'avez appris, laissez-moi vous apprendre.

Vous devez d'abord comprendre le fonctionnement des mécanismes de l'interface graphique, puis commencer à écrire du code. Vous devez connaître la structure et le comportement des éléments, leurs réactions dans différentes situations. D'abord, les présenter comme des modèles, puis créer des instances sur une base technique préparée, comprenant le modèle d'événement, les gestionnaires d'état, les phénomènes, les coordonnées, les liaisons et le dessin. À la fin, vous disposerez d'une bibliothèque graphique brute sur toile. Il sera loin d'être un langage de balisage. Sans parler d'un éditeur. Mais, vas-y.

Si vous pensez que vous allez simplement prendre quelque chose de tout fait et l'élever à un niveau supérieur, alors vous n'avez jamais rien développé de sérieux.
 
Реter Konow:
Les gars, puisque vous m'avez appris, laissez-moi vous apprendre.

Vous devez d'abord comprendre le fonctionnement des mécanismes de l'interface graphique, puis commencer à écrire du code. Vous devez connaître la structure et le comportement des éléments, leurs réactions dans différentes situations. D'abord, les présenter comme des modèles, puis créer des instances sur une base technique préparée, comprenant le modèle d'événement, les gestionnaires d'état, les phénomènes, les coordonnées, les liaisons et le dessin. À la fin, vous disposerez d'une bibliothèque graphique brute sur toile. Il sera loin d'être un langage de balisage. Sans parler d'un éditeur. Mais, vas-y.

Si vous pensez que vous allez simplement prendre quelque chose de tout fait et le faire monter d'un cran, alors vous n'avez jamais rien développé de sérieux.

Attendez pour juger - ce n'est même pas plus que l'essentiel. Et le fait que je finisse l'interface graphique est peu probable - c'est ce que j'ai dit au début. Quant aux grands projets - je le dis dans vos lignes de code ne sont pas suffisantes pour rivaliser avec les grands projets......


maintenant la question est de savoir pourquoi le tour ne fonctionne pas

class CB; 
class CC;

class CBx{public: CBx(){};};
class CBy{public: CBy(){};};
TEMPL(T) 
class CA : public T
   {
   public:
   CA(){}
   CB<T> *b;
   CC<T> *c;
   };
    
TEMPL(T) 
class CB : public CA<T>
   {
   public:
   CB(){}
   };
    
TEMPL(T) 
class CC : public CA<T>
   {
   public:
   CC(){}
   }; 

CB<CBy> cc;
 
Alexandr Andreev:

...

Maintenant, la question est de savoir pourquoi cette astuce ne fonctionne pas.

Qui sait pourquoi ça ne marche pas...

Il convient d'abord de créer le schéma de la bibliothèque, puis d'écrire les codes. C'est comme ça que ça se passe habituellement.