Bonjour j'aimerais savoir si il est possible de faire du java responsive en javafx et si oui comment, car j'ai rechercher ici et la mais je n'est pas trouver comment faire .
Merci d'avance de vos réponses.
Cordialement.
Bonjour j'aimerais savoir si il est possible de faire du java responsive en javafx et si oui comment, car j'ai rechercher ici et la mais je n'est pas trouver comment faire .
Merci d'avance de vos réponses.
Cordialement.
Non ou en tout cas pas dans le sens ou ça se fait en web actuellement. Certains ont fait des tests il y a quelques années.
Perso, je pense que c'est a la fois une combinaison de la création d'un conteneur parent plus flexible que ceux dispos par défaut dans l'UI (ex : un contrôle qui va changer sa mise en page interne de BorderPane ou GridPane sur desktop vers VBox ou FlowPane quand on met l’écran vertical ou qu'on réduit la taille et les proportions de la fenêtre) et de CSS appropriées pour les différentes sous-tailles et orientations (ex: quand la largeur devient trop petite on réduit toutes les tailles des polices de .2em) et/ou périphériques autres (tablettes, mobiles). Bref ça demande du temps de codage et de tests. Et je ne parle pas des animations s'il vaut voir les contrôles se déplacer et se redimensionner au vol (évidement ça sera plus rapide a coder sans animations).
Merci de penser au tagquand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.
suivez mon blog sur Développez.
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook
J'oubliais, pour rester plus sur le CSS. Tu peux jouer avec les pseudo-classes pour avoir plusieurs définitions de propriétés CSS pour un même composant.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 private static final PseudoClass TRUC_PSEUDO_CLASS = PseudoClass.getPseudoClass("truc"); myNode.pseudoClassStateChanged(TRUC_PSEUDO_CLASS, true);
Code CSS : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 #myNode { [...] } #myNode:truc { [...] }
Et tu peux aussi bien sur ajouter/retirer/composer des feuilles de style au vol sur la scène ou les parents (mais pas les noeuds basiques) eux meme. Et en inline (setStyle()) aussi bien sur. Il te faudra du code Java dans le contrôleur ou dans un composant custom pour gérer tout ca bien sur.
Merci de penser au tagquand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.
suivez mon blog sur Développez.
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook
D'accord donc des variable tel que ":small-device " qui présente dans ce site : " http://www.guigarage.com/2014/11/res...bJG46O4esaMY8E " n'existe pas ?
L'utilisation de pseudo classe pourrez donc résoudre mon problème ? Si oui comment lui donner cette notion de "largeur" et "hauteur" d'écran ?
Pour small-device a priori c'est une pseudo-classe définie par l'utilisateur dans son code.
Pour les proprietes normales de taille (width, height, etc.) seules sont supportées les valeurs absolues (en divers unites) et les pourcentages. Voir guide. Et encore j'ai un peu de mal avec les pourcentages car dans l'API ces valeurs ont tendance a devenir des valeurs absolues.
Apres c'est plus des valeurs a donner par rapport au conteneur que par rapport a l'ecran.
Si on prend, par exemple, le test fourni sur w3schools. Dans cet exemple, en mettant en parallèle le contenu HTML/CSS et JavaFX, on semble avoir un BorderPane ou un Vbox contenant un GridPane a 1 ligne et 12 colonnes (pour rester sur le principe de présentation de Boostrap). On peut voir que le cœur du document est dans un sous-composant car le cœur de l'affichage, le GridPane, a une bordure (padding) qui fait que son contenu n'est pas aligne sur le header et le footer.
- En mode large, on semble avoir:
- Les labels de gauche occupent les colonnes 1-3
- Le corps occupe les colonnes 3-9 (ce contenu prend 2x plus de place que les autres)
- Le menu a droite occupe les colonnes 9-12
- En mode moyen, on a :
- Dans le GridPane, on passe a un affichage sur 2 lignes
- En ligne 1, les labels de gauche occupent les colonnes 1-3
- En ligne 1, le corps semble occuper les colonnes 3-12 (quand on réduit la taille, la proportion de la partie centrale reste toujours bien plus grande que celle des labels)
- En ligne 2, le menu de droite semble occuper les colonnes 1-12
- En mode étroit, on a :
- Dans le GridPane, on passe a un affichage sur 3 lignes
- En ligne 1, les labels de gauche occupent les colonnes 1-12
- En ligne 2, Le corps semble occuper les colonnes 1-12
- En ligne 3, Le menu semble occuper les colonnes 1-12
Merci de penser au tagquand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.
suivez mon blog sur Développez.
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook
Voici un exemple, code extremement rapidement, de ce que peut donner un test d'adaption de cette page web/CSS responsive en JavaFX pur (c-a-d sans Webview, ni HTML/CSS) :
strings.properties
Code text : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 title=Chania resize.browser.message=Resize the browser window to see how the content respond to the resizing. menu.flight.label=The Flight menu.city.label=The City menu.island.label=The Island nenu.flood.label=The Food body.title=The City body.description=Chania is the capital of the Chania region on the island of Crete. The city can be divided in two parts, the old town and the modern city. side.what.label=What? side.what.description=Chania is a city on the island of Crete. side.where.label=Where? side.where.description=Crete is a Greek island in the Mediterranean Sea. side.how.label=How? side.how.description=You can reach Chania airport from all over Europe.
Container.css
Code CSS : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 .container { -fx-background-color: white; -fx-fit-to-width: true; } .container:medium, .container:large { -fx-fit-to-height: true; } .container .box { } .container .box .header { -fx-padding: 15px; -fx-min-height: 10px; -fx-pref-height: 100px; -fx-background-color: #9933cc; } .container .box .footer { -fx-padding: 15px; -fx-min-height: 10px; -fx-pref-height: 100px; -fx-background-color: #0099cc; } .container .box .body { -fx-min-height: 100px; /*-fx-grid-lines-visible: true;*/ -fx-border-color: limegreen; -fx-border-width: 5px; } .header .h1 { -fx-text-fill: white; -fx-font-size: 3.5em; -fx-font-weight: bold; } .footer .label { -fx-text-fill: white; -fx-text-alignment: center; -fx-wrap-text: true; -fx-font-size: 0.9em; } .body:small { -fx-max-width: infinity; } .menu { -fx-padding: 8px 8px 7px 8px; -fx-min-width: 75px; -fx-pref-width: 200px; -fx-max-width: 300px; -fx-border-color: yellow; -fx-border-width: 5px; -fx-fit-width: true; -fx-spacing: 10px; } .menu:small { -fx-max-width: infinity; } .menu .button { -fx-max-width: infinity; -fx-background-color: #33b5e5; -fx-background-radius: 0px; -fx-text-fill: white; -fx-alignment: center-left; -fx-font-size: 1.4em; -fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.5), 5, 0.3, 1, 2); } .menu .button:hover { -fx-background-color: #0099cc; } .side { -fx-padding: 10px; -fx-min-width: 75px; -fx-pref-width: 200px; -fx-max-width: 300px; -fx-background-color: #33b5e5; -fx-alignment: center; } .side:small { -fx-max-width: infinity; } .side .label { -fx-text-fill: white; -fx-text-alignment: center; -fx-wrap-text: true; } .side .main { -fx-font-size: 2em; -fx-font-weight: bold; } .text-content .title { -fx-font-size: 3em; -fx-font-weight: bold; } .text-content .description { -fx-font-size: 1.2em; -fx-alignment: justify; }
Container.fxml
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.ScrollPane?> <?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.text.Text?> <?import javafx.scene.text.TextFlow?> <ScrollPane fx:id="container" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" styleClass="container" stylesheets="@Container.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="layout.responsive.ContainerController"> <content> <VBox styleClass="box"> <children> <StackPane fx:id="header" styleClass="header" VBox.vgrow="NEVER"> <children> <Label styleClass="h1" text="%title" StackPane.alignment="CENTER_LEFT" /> </children></StackPane> <GridPane fx:id="body" styleClass="body" VBox.vgrow="ALWAYS"> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> </columnConstraints> <rowConstraints> <RowConstraints vgrow="ALWAYS" /> </rowConstraints> <children> <VBox fx:id="menu" styleClass="menu" GridPane.columnSpan="3"> <children> <Button mnemonicParsing="false" text="%menu.flight.label" /> <Button mnemonicParsing="false" text="%menu.city.label" /> <Button mnemonicParsing="false" text="%menu.island.label" /> <Button mnemonicParsing="false" text="%nenu.flood.label" /> </children> </VBox> <TextFlow fx:id="textContent" prefHeight="200.0" prefWidth="200.0" styleClass="text-content" GridPane.columnIndex="3" GridPane.columnSpan="6"> <children> <Text fx:id="title" strokeType="OUTSIDE" strokeWidth="0.0" styleClass="title" text="%body.title" /> <Text strokeType="OUTSIDE" strokeWidth="0.0" text=" " /> <Text fx:id="description" strokeType="OUTSIDE" strokeWidth="0.0" styleClass="description" text="%body.description" /> </children> </TextFlow> <VBox fx:id="side" styleClass="side" GridPane.columnIndex="9" GridPane.columnSpan="3"> <children> <Label styleClass="main" text="%side.what.label" /> <Label text="%side.what.description" /> <Label styleClass="main" text="%side.where.label" /> <Label text="%side.where.description" /> <Label styleClass="main" text="%side.how.label" /> <Label text="%side.how.description" /> </children></VBox> </children> </GridPane> <StackPane styleClass="footer" VBox.vgrow="NEVER"> <children> <Label text="%resize.browser.message" /> </children></StackPane> </children> </VBox> </content> </ScrollPane>
ContainerController.java
Main.java
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 package layout.responsive; import javafx.css.PseudoClass; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.ScrollPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.RowConstraints; import java.net.URL; import java.util.ResourceBundle; public final class ContainerController implements Initializable { @FXML private ScrollPane container; @FXML private GridPane body; @FXML private Node menu; @FXML private Node textContent; @FXML private Node side; @Override public void initialize(URL url, ResourceBundle resourceBundle) { body.widthProperty().addListener((observable, oldValue, newValue) -> doLayout(newValue.doubleValue())); } private static final int LARGE_SIZE = 600; private static final int MEDIUM_SIZE = 300; private enum Display { SMALL, MEDIUM, LARGE } private Display currentDisplay = Display.LARGE; private static final PseudoClass SMALL_PSEUDO_CLASS = PseudoClass.getPseudoClass("small"); private static final PseudoClass MEDIUM_PSEUDO_CLASS = PseudoClass.getPseudoClass("medium"); private static final PseudoClass LARGE_PSEUDO_CLASS = PseudoClass.getPseudoClass("large"); private void doLayout(double currentSize) { System.out.printf("doLayout(%.2f);%n", currentSize); if (currentSize == -1) { return; } var newDisplay = Display.LARGE; if (currentSize < MEDIUM_SIZE) { newDisplay = Display.SMALL; } else if (currentSize >= MEDIUM_SIZE && currentSize < LARGE_SIZE) { newDisplay = Display.MEDIUM; } System.out.printf("Display %s -> %s%n", currentDisplay, newDisplay); if (currentDisplay == newDisplay) { return; } currentDisplay = newDisplay; GridPane.clearConstraints(menu); GridPane.clearConstraints(textContent); GridPane.clearConstraints(side); menu.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, false); textContent.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, false); side.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, false); container.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, false); container.pseudoClassStateChanged(MEDIUM_PSEUDO_CLASS, false); container.pseudoClassStateChanged(LARGE_PSEUDO_CLASS, false); final int currentRows = body.getRowCount(); int newRows = 1; switch (newDisplay) { case SMALL: { newRows = 3; break; } case MEDIUM: { newRows = 2; break; } case LARGE: default: { newRows = 1; } } System.out.printf("rows %d -> %d%n", currentRows, newRows); for (int index = currentRows; index < newRows; index++) { final var rowConstraints = new RowConstraints(); rowConstraints.setVgrow(Priority.ALWAYS); body.getRowConstraints().add(index, rowConstraints); } for (int index = newRows; index < currentRows; index++) { body.getRowConstraints().remove(1); } switch (newDisplay) { case SMALL: { GridPane.setConstraints(menu, 0, 0, 12, 1); GridPane.setConstraints(textContent, 0, 1, 12, 1); GridPane.setConstraints(side, 0, 2, 12, 1); menu.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, true); textContent.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, true); side.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, true); container.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, true); break; } case MEDIUM: { GridPane.setConstraints(menu, 0, 0, 3, 1); GridPane.setConstraints(textContent, 3, 0, 9, 1); GridPane.setConstraints(side, 0, 1, 12, 1); side.pseudoClassStateChanged(SMALL_PSEUDO_CLASS, true); container.pseudoClassStateChanged(MEDIUM_PSEUDO_CLASS, true); break; } case LARGE: default: { GridPane.setConstraints(menu, 0, 0, 3, 1); GridPane.setConstraints(textContent, 3, 0, 6, 1); GridPane.setConstraints(side, 9, 0, 3, 1); container.pseudoClassStateChanged(LARGE_PSEUDO_CLASS, true); } } } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package layout.responsive; import javafx.application.Application; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import java.util.ResourceBundle; public final class Main extends Application { public static void main(String... args) { launch(args); } @Override public void start(final Stage stage) throws Exception { final var bundle = ResourceBundle.getBundle("layout/responsive/strings"); final var fxmlLoader= new FXMLLoader(getClass().getResource("Container.fxml"), bundle); final var root = fxmlLoader.<Parent>load(); final var scene = new Scene(root); stage.setWidth(700); stage.setHeight(600); stage.setScene(scene); stage.setTitle("Test"); stage.show(); } }
Merci de penser au tagquand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.
suivez mon blog sur Développez.
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook
Partager