IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ LazarusConsultez toutes les FAQ

Nombre d'auteurs : 17, nombre de questions : 88, dernière mise à jour : 31 décembre 2023  Ajouter une question

 

Bienvenue dans la FAQ Lazarus.

Cette base de connaissances a essentiellement été construite avec le contenu de l'ancien forum officiel francophone dédié à Lazarus. Elle sera régulièrement alimentée avec le contenu du forum actuel. Les aspects propres au langage Pascal lui-même se trouvent dans la FAQ Pascal.

Cette FAQ collaborative est avant tout la vôtre ! Pour participer à son développement, vous pouvez directement y ajouter de nouvelles questions/réponses ou encore poster des propositions de corrections sur le forum Contribuez.

Bonne lecture !

L'équipe Pascal.

SommaireAndroidComposants Android (13)
précédent sommaire suivant
 

Tous les composants destinés à développer des applications pour Android sont répartis sur cinq palettes :

  • Android Bridges, qui contient la plupart des composants de base ;
  • Android Bridges Extra, qui complète la première palette avec une série de composants plus spécialisés ;
  • Android Bridges AppCompat, avec des composants spécialement conçus pour les thèmes "AppCompat" ;
  • Android Bridges jCenter, pour faire le lien avec des bibliothèques Java externes ;
  • FCL Bridges, pour faire le lien avec les composants natifs de Free Pascal.

Mis à jour le 22 août 2023 Alcatîz

La réponse est non : il faut obligatoirement utiliser les composants des palettes Android Bridges.

La plupart des composants classiques de Lazarus ont un pendant pour Android, par exemple :

  • TMenu -> jMenu ;
  • TLabel -> jTextView ;
  • TButton -> jButton ;
  • TEdit -> jEditText ;
  • TPanel -> jPanel ;
  • TTimer -> jTimer ;
  • ... etc.

Mis à jour le 22 août 2023 Alcatîz

Pour positionner correctement des composants et, surtout, s'assurer qu'ils restent correctement placés si, par exemple, l'application passe du mode portrait au mode paysage sur le smartphone, voici quelques propriétés essentielles communes à à peu près tous les composants visuels :

  • Anchor : il s'agit du composant par rapport auquel s'effectue le positionnement ;
  • LayoutParamHeight et LayoutParamWidth : il s'agit de la taille du composant exprimée relativement à la taille de l'écran ;
  • MarginBottom, MarginLeft, MarginRight et MarginTop : ce sont les marges autour du composant ;
  • PosRelativeToAnchor : c'est la position par rapport au composant défini dans la propriété Anchor ;
  • PosRelativeToParent : c'est la position relative au parent, qui peut être la fenêtre de l'application ou, par exemple, un jPanel.


Prenons un exemple de disposition d'écran :


Dans cet exemple, le haut de l'écran est constitué d'un jPanel (contenant un titre et deux boutons-images) dont les propriétés ont été fixées comme suit :
  • Anchor : rien, il n'y a pas de composant de référence ;
  • PosRelativeToParent : c'est la fenêtre principale qui est le parent, et le panneau est accroché au haut, à gauche et à droite de l'écran. Donc les sous-propriétés rpTop, rpLeft et rpRight sont cochées.


Le panneau contient un jTextView de titre, un bouton-image à gauche et un bouton-image à droite. Le jPanel est donc le parent de ces trois composants. Prenons par exemple le bouton de gauche :
  • Anchor : rien ;
  • PosRelativeToParent : il est centré verticalement et aligné à gauche dans le jPanel et donc seront cochées les sous-propriétés rpCenterVertical et rpLeft.


Sous le panneau figure un petit jTextView "0/0". Il est positionné juste sous le jPanel, qui va donc servir de composant de référence, et est centré à l'écran. Les propriétés suivantes seront définies :
  • Anchor : le jPanel ;
  • PosRelativeToAnchor : raBelow sera cochée, pour indiquer qu'il est sous le composant de référence ;
  • PosRelativeToParent : rpCenterHorizontal, pour indiquer qu'il est centré à l'écran.


Considérons à présent le bouton-image (jImageBtn) représentant une flèche. Il est positionné sous le jTextView "0/0" et est centré à l'écran :
  • Anchor : le jTextView ;
  • PosRelativeToAnchor : raBelow (en dessous) ;
  • PosRelativeToParent : rpCenterHorizontal (centré horizontalement).


Continuons notre parcours des composants : le jTextView "Language 1" est situé à gauche du bouton-image et est aligné sur le haut de celui-ci. Les propriétés suivantes seront donc définies :
  • Anchor : le bouton-image ;
  • PosRelativeToAnchor : raToLeftOf (situé à sa gauche) et raAlignTop (aligné avec le dessus).


Terminons avec les trois boutons du dessous (deux boutons classiques jButton et un bouton-image jImageBtn). Étant donné que ces trois boutons se partagent la largeur de l'écran, attribuons-leur à chacun un tiers de l'écran en donnant comme valeur lpOneThirdOfParent à la propriété LayoutParamWidth. Cette propriété, comme LayoutParamHeight, permet de définir des dimensions variables à un composant, par rapport à la taille du parent (l'écran tout entier dans notre exemple). Si l'on bascule le téléphone en mode paysage, le bouton-image restera au milieu de l'écran (et ne changera pas de taille, vu que celle-ci est définie par l'image) et les deux boutons classiques s'étireront chacun de son côté jusqu'à atteindre un tiers de la largeur.
Remarquez que ces deux boutons sont affichés à une certaine distance du bas de l'écran : cette distance a été définie dans leur propriété MarginBottom.

Conclusion :

Pour concevoir votre application, réfléchissez aux composants qui pourront servir de référence pour le placement d'autres composants, ainsi qu'à la possibilité que l'écran bascule en mode paysage, afin que tout reste positionné de manière correcte.

Mis à jour le 24 août 2023 Alcatîz

Pour ajouter une nouvelle fiche de travail, et donc une nouvelle activité (une fenêtre), il ne faut surtout pas recourir au bouton Nouvelle fiche de la barre d'outils de Lazarus ! Car cela crée une fiche de travail de type TForm qui est totalement inutilisable sous Android.

Il faut donc utiliser le menu "Fichier / Nouveau" et choisir "LAMW GUI Android jForm".

Mis à jour le 28 octobre 2023 Alcatîz

Pour créer un menu dans votre application, déposez tout d'abord un composant jMenu (de la palette Android Bridges) sur la fiche de travail.

Si vous souhaitez ajouter des icônes à vos éléments de menu, copiez les images au format png dans le dossier jni/res/drawable de votre projet. Il est conseillé de faire précéder les noms de fichier du préfixe ic_ (par exemple, ic_fileopen.png). La taille des images conditionnera logiquement la hauteur des éléments du menu.

Réglez les propriétés du composant jMenu :

  • dans Options, indiquez les éléments du menu dans l'ordre désiré (un par ligne) ;
  • dans Iconidentifiers, indiquez les noms de fichier des images sans extension, dans l'ordre désiré (également un par ligne) (par exemple, ic_fileopen).

Dans l'inspecteur d'objets, créez deux gestionnaires d'événements pour la fenêtre principale :
  • ClickOptionMenuItem
  • CreateOptionMenu

Pour afficher le menu, complétez la méthode AndroidModule1CreateOptionMenu comme suit :
Code pascal : Sélectionner tout
1
2
3
4
procedure AndroidModule1.AndroidModule1CreateOptionMenu(Sender: TObject; jObjMenu: jObject); 
begin 
  Menu1.ShowOptions(jObjMenu);   (* Sans icônes *) 
end;
ou avec les icônes :
Code pascal : Sélectionner tout
1
2
3
4
procedure AndroidModule1.AndroidModule1CreateOptionMenu(Sender: TObject; jObjMenu: jObject); 
begin 
  Menu1.ShowOptions(jObjMenu, misNever);   (* Avec icônes *) 
end;


Voici un exemple de code de la méthode AndroidModule1ClickOptionMenuItem qui ne fait qu'afficher le libellé de l'élément de menu choisi :
Code Pascal : Sélectionner tout
1
2
3
4
procedure AndroidModule1.AndroidModule1ClickOptionMenuItem(Sender: TObject; jObjMenuItem: jObject; itemID: integer; itemCaption: string; checked: boolean); 
begin 
  ShowMessage(itemCaption); 
end;


Il faut que la propriété ActionBarTitle de la fenêtre principale ait la valeur abtDefault, sinon votre menu ne s'affichera pas.

Mis à jour le 20 août 2023 Alcatîz

Il n'y a pas de composant TMemo disponible dans les palettes Android Bridges mais ce composant peut être remplacé par un jEditText dont les propriétés sont adaptées :

  • InputTypeEx = itxMultiLine ;
  • LayoutParamHeight et LayoutParamWidth = lpMatchParent (mais d'autres valeurs peuvent convenir) ;
  • ScrollBarStyle = scrlinsideInset ;
  • MaxTextLength = -1 ;
  • WrappingLine = True ;
  • MaxLines = un nombre suffisamment grand.

Mis à jour le 22 août 2023 Alcatîz

Le composant jDialogYN présent sur la palette Android Bridges Extra est très simple à utiliser. Il apparaîtra par défaut au bas de votre application.

Une fois le composant déposé sur la fiche de travail, vous pouvez définir quelques propriétés dans l'inspecteur d'objets :

  • Title : le titre du dialogue ;
  • TitleAlign : l'alignement du titre - par défaut aligné à gauche ;
  • Msg : le texte affiché dans le dialogue ;
  • Yes : le texte affiché dans le bouton d'acceptation - par défaut "Yes" ;
  • No : le texte affiché dans le bouton de refus - par défaut "No".


Avant l'affichage du dialogue, vous pouvez définir les couleurs de fond et de texte du titre et du message à comme dans cet exemple :
Code pascal : Sélectionner tout
1
2
3
4
dlgConfirm.SetColorBackgroundTitle(colbrNavy);   // Fond du titre 
dlgConfirm.SetColorTitle(colbrWhite);   // Couleur de texte du titre 
dlgConfirm.SetColorBackground(colbrNavy);   // Fond du message 
dlgConfirm.SetColorText(colbrBeige);   // Couleur de texte du message


Pour réagir à la pression d'un des deux boutons, dans l'inspecteur d'objets créez un gestionnaire d'événement qui répondra à l'événement OnClickYN :
Code pascal : Sélectionner tout
1
2
3
4
5
6
procedure TfrmMain.dlgConfirmClickYN(Sender : TObject; YN : TClickYN); 
begin 
  if YN = ClickYes   // Pour l'autre bouton la valeur est ClickNo 
     then 
       { . . . } 
end;


L'affichage du dialogue se fait à l'aide de la méthode Show (plusieurs variantes existent, vous permettant de définir ou pas certaines propriétés) :
Code pascal : Sélectionner tout
1
2
3
dlgConfirm.Show; 
// autre exemple : 
dlgConfirm.Show('Confirmation', 'Le fichier a été modifié', 'Enregistrer', 'Annuler');

Mis à jour le 27 août 2023 Alcatîz

Il est possible de créer un dialogue personnalisé, contenant des contrôles d'édition, des boîtes combo, des boutons radio, des cases à cocher, etc. à partir du composant jCustomDialog, disponible dans la palette Android Bridges.

Déposez tout d'abord ce composant sur la fiche de travail, puis déposez ensuite les contrôles de votre choix directement sur la surface du jCustomDialog. Celui-ci sera le parent de tous ces contrôles, et d'ailleurs ils apparaîtront en tant que contrôles enfants dans l'inspecteur d'objets, sous le dialogue et en retrait.

Commencez par régler les différentes propriétés du dialogue (couleurs, dimensions, etc.). Positionnez les contrôles à l'aide des propriétés PosRelativeToParent, pour définir la position de certains d'entre eux dans le dialogue, et/ou PosRelativeToAnchor pour en positionner d'autres par rapport à ceux que vous avez déjà positionnés, en sélectionnant ces derniers dans la propriété Anchor. Cela fonctionne exactement comme le positionnement des composants sur la fiche de travail (voir le lien ci-dessous). Jouez également avec les propriétés LayoutParamWidth et LayoutParamHeight pour dimensionner les contrôles à l'intérieur du dialogue (par exemple, la valeur lpOneThirdOfParent pour LayoutParamWidth dimensionnera le contrôle au tiers de la largeur du dialogue).

Le dialogue jCustomDialog est affiché grâce à sa méthode Show, dont il existe plusieurs variantes pour éventuellement en définir certaines propriétés à la volée. Les contrôles peuvent être initialisés dans le gestionnaire répondant à l'événement OnShow du dialogue. Vous devez créer des gestionnaires d'événements individuellement pour chacun des contrôles contenus dans le dialogue (par exemple, pour l'événement OnClick d'un bouton jButton, OnLostFocus d'un jEditText, etc.).

Mis à jour le 27 août 2023 Alcatîz

Pour créer une collection d'images utilisables par certains composants de votre application, il faut déposer n'importe où sur la fiche de travail un composant jImageList (disponible dans la palette Android Bridges). Les images de la collection doivent être disponibles dans le répertoire assets du projet ; une bonne méthode pour les y placer est d'utiliser l'utilitaire d'importation (lien ci-dessous). Les images sont idéalement au format png, ce format supportant la transparence et offrant un bon compromis entre la qualité et la compression.

Dans l'inspecteur d'objets, cliquez sur les trois points en regard de la propriété Images et ajoutez les images que vous souhaitez en utilisant le bouton Add. Les images ajoutées s'affichent en noir tandis que les autres s'affichent en gris. Il suffit ensuite de cliquer sur OK.

Remarque : le composant jImageList peut recevoir des images lors de la phase de conception du projet, mais pas au cours de l'exécution de l'application.

Mis à jour le 3 septembre 2023 Alcatîz

Un bouton-image est un bouton comportant un pictogramme au lieu d'un texte. Il existe sur internet des tas de pictogrammes destinés aux applications pour mobiles (attention cependant à leur licence d'utilisation) mais vous pouvez aussi les créer vous-mêmes, avec un simple éditeur d'images, au format png - qui supporte la transparence, idéal pour par exemple faire un pictogramme rond.

L'image (ou les images, vous comprendrez pourquoi plus bas) de votre bouton doit être disponible dans un composant jImageList (voyez le lien ci-dessous).

Déposez sur la fiche de travail un jImageBtn, disponible dans la palette Android Bridges. Il est inutile d'en définir la taille car celle-ci sera fixée par la taille de l'image.
Dans l'inspecteur d'objets, affectez l'identificateur du jImageList à la propriété Images. Il s'agit à présent de choisir une image pour le bouton dans son état normal et une lorsqu'il est pressé. Par exemple, une image claire pour le bouton dans son état normal et une version plus sombre pour quand il sera pressé. La même image peut évidemment être utilisée pour les deux états (mais il serait dommage de vous priver d'un petit effet sympa, non ?). Sélectionnez les deux images dans la liste déroulante de ces deux propriétés :

  • IndexImageUp pour le bouton dans son état normal ;
  • IndexImageDown pour le bouton pressé.


Trois événements vous permettent de réagir à l'action du bouton :
  • OnClick, lorsqu'il est actionné ;
  • OnDown, lorsqu'il entre dans son état "pressé" ;
  • OnUp lorsqu'il est relâché.

Mis à jour le 3 septembre 2023 Alcatîz

L'environnement dans lequel s'exécute une application sous Android étant bien isolé, le fait que le SGBD SQLite ne soit pas (ou peu) sécurisé n'est pas gênant.

Deux composants présents sur la palette Android Bridges Extra permettent de gérer aisément une base de données SQLite :

  • jSqliteDataAccess ;
  • jSqliteCursor.


Déposez-les n'importe où sur la fiche de travail et définissez le jSqliteCursor dans la propriété Cursor du jSqliteDataAccess.

Mis à jour le 31 décembre 2023 Alcatîz

Différentes méthodes permettent de gérer complètement une base de données SQLite. En voici les plus courantes.

Méthodes du composant jSqliteCursor :

  • MoveToFirst : ramène le curseur au début de la liste des éléments sélectionnés ;
  • MoveToLast : positionne le curseur à la fin de la liste des éléments sélectionnés ;
  • MoveToNext : passe à l'élément suivant ;
  • MoveToPrev : passe à l'élément précédent ;
  • MoveToPosition : déplace directement le curseur vers une position bien précise ;
  • BOF : teste si l'on est au début de la liste ;
  • EOF : teste si l'on est à la fin de la liste ;
  • GetColumnCount : détermine le nombre de colonnes dans une table ;
  • GetColumName : détermine le nom d'une colonne d'une table ;
  • GetRowCount : détermine le nombre d'éléments dans une table ;
  • GetValueAsInteger : retourne une valeur sous forme de nombre entier ;
  • GetValueAsFloat : retourne une valeur sous forme de nombre réel ;
  • GetValueAsString : retourne une valeur sous forme de chaîne de caractères.


Méthodes du composant jSqliteDataAccess :
  • OpenOrCreate : crée une nouvelle base de données ou ouvre une base de données existante ;
  • CreateTable : crée une nouvelle table dans la base de données ;
  • InsertIntoTable : ajoute des données dans une table ;
  • UpdateTable : modifie des données dans une table ;
  • DeleteFromTable : supprime des données dans une table ;
  • ExecSQL : exécute n'importe quelle requête SQL.


Pour ce qui suit, nous partons du principe que le nom de la base de données a été défini dans la propriété DataBaseName du composant jSqliteDataAccess et que la base de données est située dans le dossier requis. Le nom de ce dossier peut être récupéré grâce à ce code :
Code pascal : Sélectionner tout
Dossier_bases_de_donnees := Self.GetEnvironmentDirectoryPath(dirDatabase);


Créer ou ouvrir une base de données
Code pascal : Sélectionner tout
sqliteDataAccess.OpenOrCreate(sqliteDataAccess.DataBaseName);

Créer une table

Le code suivant crée une table T_MATABLE contenant les champs suivants :
  • F_MATABLEID : la clé primaire (autoincrémentée) ;
  • F_MATABLENOM : le nom de l'élément ;
  • F_MATABLEQUANTITE : la quantité de cet élément.

Code pascal : Sélectionner tout
sqliteDataAccess.CreateTable('CREATE TABLE IF NOT EXISTS T_MATABLE (F_MATABLEID INTEGER PRIMARY KEY, F_MATABLENOM TEXT NOT NULL, F_MATABLEQUANTITE INTEGER);');


Modifier une table

Le code suivant rajoute une colonne F_MATABLECATEGORIE, de type entier :
Code pascal : Sélectionner tout
sqliteDataAccess.ExecSQL('ALTER TABLE T_MATABLE ADD COLUMN F_MATABLECATEGORIE INTEGER;');


Récupérer la structure d'une table

Le code suivant affiche tous les champs de la table T_MATABLE :
Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function StructureTable : String; 
var 
  LColCount, LColIndex : Integer; 
begin   
  sqliteDataAccess.Select('SELECT * FROM T_MATABLE;'); 
  LColCount := sqliteDataAccess.Cursor.GetColumnCount; 
  Result := ''; 
  for LColIndex := 0 to (LColCount - 1) do 
    begin 
      Result := Result + sqliteDataAccess.Cursor.GetColumName(LColIndex) + ': '; 
      case sqliteDataAccess.Cursor.GetColType(LColIndex) of 
        ftInteger : Result := Result + 'INTEGER'; 
        ftFloat : Result := Result + 'FLOAT'; 
        ftString : Result := Result + 'TEXT'; 
        ftBlob : Result := Result + 'BLOB'; 
        ftNull : Result := Result + 'NULL'; 
      end; 
      Result := Result + LineEnding; 
    end; 
end;


Parcourir les données d'une table

Le code suivant affiche le contenu de la table T_MATABLE :
Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function ContenuTable : String; 
begin 
  sqliteDataAccess.Select('SELECT * FROM T_MATABLE;'); 
  sqliteDataAccess.Cursor.MoveToFirst; 
  while not sqliteDataAccess.Cursor.EOF do 
    begin 
      Result := Result + IntToStr(sqliteDataAccess.Cursor.GetValueAsInteger(F_MATABLEID)) + 
               ' - ' + sqliteDataAccess.Cursor.GetValueAsString(F_MATABLENOM) + 
               ' - ' + IntToStr(sqliteDataAccess.Cursor.GetValueAsInteger(F_MATABLECATEGORIE)) + 
               ' - ' + IntToStr(sqliteDataAccess.Cursor.GetValueAsInteger(F_MATABLEQUANTITE)) + 
               LineEnding; 
      sqliteDataAccess.Cursor.MoveToNext; 
    end; 
end;


Sélectionner des données dans une table

Le code suivant sélectionne les données de la table T_MATABLE qui correspondent à la catégorie 1 :
Code pascal : Sélectionner tout
sqliteDataAccess.Select('SELECT * FROM T_MATABLE WHERE F_MATABLECATEGORIE = 1;');


Ajouter un élément à une table

Le code suivant ajoute un élément à la table T_MATABLE :
Code pascal : Sélectionner tout
1
2
sqliteDataAccess.InsertIntoTable('INSERT INTO T_MATABLE(F_MATABLENOM, F_MATABLECATEGORIE, F_MATABLEQUANTITE) VALUES (' + 
                                 QuotedStr('Nouvel élément') + ', 1, 10);');

Notez l'utilisation de la fonction QuotedStr : elle permet, pour les champs de type texte, d'automatiquement encadrer de quotes les chaînes de caractères et d'échapper les éventuelles quotes y contenues.

Modifier un élément dans une table

Le code suivant modifie un élément dont l'index est connu :
Code pascal : Sélectionner tout
sqliteDataAccess.UpdateTable('UPDATE T_MATABLE SET F_MATABLEQUANTITE = 20 WHERE F_MATABLEID = 3;');


Supprimer un élément

Le code suivant supprime de la table T_MATABLE l'élément de nom 'Un élément' :
Code pascal : Sélectionner tout
sqliteDataAccess.DeleteFromTable('DELETE FROM T_MATABLE WHERE F_MATABLENOM = ' + QuotedStr('Un élément') + ';');

Mis à jour le 31 décembre 2023 Alcatîz

Il est possible de faire en sorte que l'écran de votre application soit composé de plusieurs pages, que l'on peut feuilleter à la manière d'un livre, à l'aide du composant jsViewPager, disponible sur la palette Android Bridges AppCompat.

Il faut que votre application soit convertie au thème AppCompat. Pour ce faire, allez dans le menu Outils / [LAMW] Android Project Options / Convert the project to AppCompat theme.

Déposez un composant jsViewPager sur votre fiche de travail. Si vous décidez que les pages de l'application doivent prendre tout l'écran, vous pouvez fixer les propriétés LayoutParamWidth et LayoutParamHeight à lpMatchParent. La propriété PagerStrip permet de décider où seront placés les titres des pages, et donc dans quel sens le feuilletage de celles-ci s'effectuera ; par exemple, psTabTop placera les titres en haut et les pages défileront comme dans un livre.

Déposez ensuite sur la fiche de travail tous les composants qui feront partie des pages de l'application. Certains vont peut-être se superposer mais ce n'est pas grave : au démarrage de l'application, chaque page retrouvera ses propres contrôles, grâce à ce qui suit.

Dans le gestionnaire d'événement correspondant à la création des composants Android (l'événement onJNIPrompt de la fenêtre principale), ajoutez les lignes suivantes (dans cet exemple, chaque page de l'application possède un composant jListView) :

Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender : TObject); 
begin 
  ViewPager1.SetClipToPadding(False); 
  ViewPager1.AddPage(ListView1.View, 'Page 1'); 
  ViewPager1.AddPage(ListView2.View, 'Page 2'); 
  ViewPager1.AddPage(ListView3.View, 'Page 3'); 
  { . . . } 
end;

Mis à jour le 31 décembre 2023 Alcatîz

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.