I'm new to javafx (and pretty much programming in general) and am trying to add \n characters to my fxml file. I've tried the text="${'10\nquestions'}" method as a test but I get can't resolve symbol '10\nquestions'. Learning how to put \n characters would be helpful but my actual problem comes from the Label fx:id questionText in quiz.fxml
quiz.fxml
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:controller="app.java.controllers.QuizController" xmlns:fx="http://javafx.com/fxml">
<left>
<VBox fx:id="quizLeft">
<Label text="Java" />
<Label fx:id="numberOfQuestions" />
<Label fx:id="score" />
<Label text="Time taken: 2:34" />
</VBox>
</left>
<center>
<VBox id="quizCenter">
<VBox id="questionLabel">
<Label fx:id="questionNumber" />
<Label fx:id="questionText" />
</VBox>
<RadioButton fx:id="option1" >
<toggleGroup>
<ToggleGroup fx:id="answerList" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="option2" toggleGroup="$answerList" />
<RadioButton fx:id="option3" toggleGroup="$answerList" />
<RadioButton fx:id="option4" toggleGroup="$answerList" />
<StackPane id="submitButton">
<Button fx:id="submitAnswerButton" text="Submit" onAction="#submitAnswerButton"/>
</StackPane>
<Button text="test" onAction="#printQuestions"/>
<Button fx:id="homeButton" text="home" onAction="#backToWelcome"/>
</VBox>
</center>
</BorderPane>
currently, if a question is too long I get this.
UI image
that question field that runs too long is connected to questionTextLabel which is populated from a mock db of Questions. How can I get questions that are too long to wrap to multiline. I've tried multiple things with the css as well, like messing around with -fx-text-overrun. Here are the css and controller classes as well. You can also see my project structure and other class in the img provided above.
/*quiz.css*/
.root{
-fx-background-color: #1e349c;
}
#quizLeft{
-fx-background-color: #9c0e7c;
-fx-alignment: center;
-fx-spacing: 10px;
-fx-min-width: 300px;
}
.label{
-fx-text-fill: #fea2ff;
-fx-font-weight: bold;
-fx-font-size: 30px;
}
#quizCenter{
-fx-alignment: center;
}
#questionLabel{
-fx-padding: 70px;
-fx-alignment: center;
}
/*#questionText{*/
/* !*-fx-text-overrun: ;*!*/
/*}*/
.radio-button{
-fx-font-size: 30px;
-fx-text-fill: yellow;
-fx-font-weight: bold;
}
#submitButton{
-fx-padding: 60px;
-fx-font-size: 30px;
}
package app.java.controllers;
import app.java.dao.Question;
import app.java.services.SceneBuilder;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
public class QuizController extends Controller implements Initializable {
#FXML
Button submitAnswerButton;
#FXML
Label questionNumber;
#FXML
Label questionText;
#FXML
RadioButton option1;
#FXML
RadioButton option2;
#FXML
RadioButton option3;
#FXML
RadioButton option4;
#FXML
Button homeButton;
#FXML
Label score;
#FXML
Label numberOfQuestions;
#FXML
ToggleGroup answerList;
Question currentQuestion;
int correctAnswers;
int questionsAnswered;
int currentQuestionNumber;
List<Question> quizList;
SceneBuilder sb;
public void backToWelcome() throws Exception{
sb.setNewScene(homeButton, "welcome");
}
public void submitAnswerButton() throws Exception{
updateScore();
if(questionsAnswered == quizList.size()){
// games over
sb.setNewSceneWithParameters(submitAnswerButton, "endOfQuiz", score);
} else {
// continue to next question
currentQuestionNumber++;
currentQuestion = quizList.get(currentQuestionNumber);
setQuestionNumber(currentQuestionNumber);
setQuestionText(currentQuestion.getQuery());
setChoices(currentQuestion.getAnswers());
}
}
public void setQuestionNumber(int questionNumber){
this.questionNumber.setText("Question #" + (questionNumber + 1));
}
public Question getQuestionFromList(int nextQuestion){
return quizList.get(nextQuestion);
}
public void setQuestionText(String questionText){
this.questionText.setText(questionText);
}
public void setChoices(List<String> choices){
option1.setText(choices.get(0));
option2.setText(choices.get(1));
option3.setText(choices.get(2));
option4.setText(choices.get(3));
}
public boolean checkAnswer(String correctAnswer, String userGuess){
return correctAnswer.equals(userGuess);
}
public void updateScore(){
RadioButton selectedRadioButton = (RadioButton) answerList.getSelectedToggle();
boolean isCorrect = checkAnswer(currentQuestion.getCorrectAnswer(), selectedRadioButton.getText());
if(isCorrect){
correctAnswers++;
}
questionsAnswered++;
setScore();
}
public void printQuestions(){
quizList.forEach(System.out::println);
}
public void setScore(){
score.setText(correctAnswers + " correct out of " + questionsAnswered);
}
#Override
public void initialize(URL location, ResourceBundle resources) {
sb = new SceneBuilder();
currentQuestionNumber = 0;
questionsAnswered = 0;
correctAnswers = 0;
setScore();
}
#Override
public void initData(Object parameter) {
this.quizList = (List<Question>)parameter;
// Set first question
currentQuestion = getQuestionFromList(currentQuestionNumber);
setQuestionNumber(currentQuestionNumber);
setQuestionText(currentQuestion.getQuery());
setChoices(currentQuestion.getAnswers());
this.numberOfQuestions.setText(quizList.size() + " questions");
}
}
Any help and advice I could get would be greatly appreciated. Thanks!
edit:
I know SceneBuilder can do a lot of things for me but since this is my first try at it, I wanna write it myself so I know how to do it manually.
Related
I am stuck on how to add table footer or column footer in JavaFX TableView. I am looking to add a TableView which will show purchased items with quantities and sells price in columns and total items count and total sum at the TableView footer. I looked at various resources, but could not find footer property associated with TableView. Any idea how to do it?
Model Class
package javafxapplication8;
public class TestModel {
private String itemName = null;
private int pricePerUnit = 0;
private double quantity = 0.0;
private double amount = 0.0;
public TestModel() {
}
public TestModel(String argitemName, int argpricePerUnit, double argquantity, double argamount) {
itemName = argitemName;
pricePerUnit = argpricePerUnit;
quantity = argquantity;
amount = argamount;
}
public void setItemName(String argitemName) {
itemName = argitemName;
}
public void setPricePerUnit(int argpricePerUnit) {
pricePerUnit = argpricePerUnit;
}
public void setQuantity(double argquantity) {
quantity = argquantity;
}
public void setAmount(double argamount) {
amount = argamount;
}
public String getItemName() {
return itemName;
}
public int getPricePerUnit() {
return pricePerUnit;
}
public double getQuantity() {
return quantity;
}
public double getAmount() {
return amount;
}
#Override
public String toString() {
return this.itemName + "" + this.pricePerUnit + "" + this.quantity + "" + this.amount;
}
}
XML Code
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" fx:id="anchor" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication8.TVCTestModel">
<children>
<VBox prefHeight="564.0" prefWidth="857.0">
<children>
<HBox alignment="BOTTOM_LEFT" prefHeight="100.0" prefWidth="1613.0" spacing="20.0" />
<BorderPane prefHeight="695.0" prefWidth="1618.0">
<center>
<VBox prefHeight="544.0" prefWidth="772.0">
<children>
<HBox prefHeight="65.0" prefWidth="1618.0" />
<HBox prefHeight="426.0" prefWidth="857.0">
<children>
<HBox alignment="CENTER" prefHeight="225.0" prefWidth="857.0">
<children>
<TableView fx:id="myTableView" prefHeight="419.0" prefWidth="816.0">
<columns>
<TableColumn fx:id="itemName" prefWidth="200.0" text="Item Name" />
<TableColumn fx:id="pricePerUnit" prefWidth="200.0" text="Price Per Unit" />
<TableColumn fx:id="quantity" prefWidth="200.0" text="Quantity" />
<TableColumn fx:id="amount" prefWidth="200.0" text="Amount" />
</columns>
</TableView>
</children>
</HBox>
</children>
</HBox>
</children>
</VBox>
</center>
<bottom>
</bottom>
</BorderPane>
</children>
</VBox>
</children>
</AnchorPane>
Controller Class
package javafxapplication8;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
public class TVCTestModel implements Initializable {
#FXML
private TableColumn<TestModel, String> itemName;
#FXML
private TableColumn<TestModel, Integer> pricePerUnit;
#FXML
private TableColumn<TestModel, Double> quantity;
#FXML
private TableColumn<TestModel, Double> amount;
#FXML
private TableView<TestModel> myTableView;
public ObservableList<TestModel> objList = FXCollections.observableArrayList();
#FXML
private AnchorPane anchor;
private static TestModel curTestModel;
#Override
public void initialize(URL url, ResourceBundle rb) {
this.itemName.setCellValueFactory(new PropertyValueFactory<>("itemName"));
this.pricePerUnit.setCellValueFactory(new PropertyValueFactory<>("pricePerUnit"));
this.quantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
this.amount.setCellValueFactory(new PropertyValueFactory<>("amount"));
objList.add(new TestModel("Item 1", 10, 4, 400));
objList.add(new TestModel("Item 2", 20, 5, 1000));
objList.add(new TestModel("Item 3", 30, 6, 1800));
objList.add(new TestModel("Item 4", 400, 7, 2800));
System.out.println(objList.size());
myTableView.setItems(objList);
}
}
MainMethod Class
package javafxapplication8;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXApplication8 extends Application {
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("TVCTestModel.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException ex) {
Logger.getLogger(JavaFXApplication8.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
launch(args);
}
}
Your updated question was reopened, and the image provided suggests that, instead of a footer, you want two summary fields. As your table is not editable, a simple approximation is illustrated here—add two labels to the view, and iterate the table's model in the controller to establish the localized result:
TVCTestModel.fxml:
…
<bottom>
<HBox alignment="CENTER_RIGHT" style="-fx-spacing: 5px;">
<children>
<Label fx:id="labelQ"/>
<Label fx:id="labelA"/>
</children>
</HBox>
</bottom>
…
TVCTestModel.java
#FXML private Label labelQ;
#FXML private Label labelA;
#Override
public void initialize(URL url, ResourceBundle rb) {
…
double sumQuantity = 0;
double sumAmout = 0;
for (TestModel o : objList) {
sumQuantity += o.getQuantity();
sumAmout += o.getAmount();
}
labelQ.setText("Quantity: "
+ NumberFormat.getNumberInstance().format(sumQuantity));
labelA.setText("Amount: "
+ NumberFormat.getCurrencyInstance().format(sumAmout));
}
If you later decide to make your table editable, as shown here, you should consider these modifications:
Migrate to observable properties in your model class, as shown here.
Create your ObservableList model with an extractor, as shown here and here; your extractor would include properties for quantity and amount; your controller could then update the summary field in a ListChangeListener.
I have a pdf reader developped using Apache PdfBox, my problem is that i have a blurry image after zooming , this problem is only with PDF even if the resolution is very good of the pdf file.
this code working good with png or jpg files, but the problem still with pdf files, i'am really confused, i search on google but i found some solutions that are not complete.
Controller
package application;
import java.nio.file.Paths;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
public class Controller {
String imagePath = "C:\\Users\\piratack007\\Desktop\\1.jpg";
private ImageView imageView = new ImageView();
String path="C:\\Users\\piratack007\\Desktop\\file.pdf";
private PdfModel model= new PdfModel(Paths.get(path));
private ScrollPane scrollPane = new ScrollPane();
private DoubleProperty zoom = new SimpleDoubleProperty(1.1);
private PageDimensions currentPageDimensions ;
#FXML private VBox vbox;
String cssLayout = "-fx-border-color: red;\n" +
"-fx-border-insets: 5;\n" +
"-fx-border-width: 3;\n" +
"-fx-border-style: dashed;\n";
String scrollCssLayout= "-fx-border-color: green;\n" +
"-fx-border-insets: 5;\n" +
"-fx-border-width: 3;\n" +
"-fx-border-style: dashed;\n"+
//Ne pas afficher le petit trait gris
"-fx-background-color:transparent";
public void initialize() {
afficheImage();
}
void afficheImage() {
/*try {
imageView = new ImageView(new Image(new FileInputStream(imagePath)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//loading the first page
imageView = new ImageView(model.getImage(0));
System.out.print("1-imageView.getFitHeight(): "+imageView.getImage().getHeight()+"\n");
System.out.print("imageView.getFitWidth(): "+imageView.getImage().getWidth()+"\n");
currentPageDimensions = new PageDimensions(imageView.getImage().getWidth(), imageView.getImage().getHeight());
zoom.addListener(new InvalidationListener() {
#Override
public void invalidated(Observable arg0) {
//My problem is in this part of code
int width = (int) (imageView.getImage().getWidth() * zoom.get());
int height = (int) (imageView.getImage().getHeight() * zoom.get());
imageView.setFitWidth(width);
System.out.print("Largeur: "+ (width) +"px\n");
imageView.setFitHeight(height);
System.out.print("Hauteur: "+ height +"px\n");
//==================================================
}
});
imageView.preserveRatioProperty().set(true);
scrollPane.setPannable(true);
scrollPane.setStyle(scrollCssLayout);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setContent(imageView);
vbox.setStyle(cssLayout);
vbox.getChildren().add(scrollPane);
}
#FXML private void zoomIn() {
zoom.set(zoom.get()*1.1);
// System.out.print("zoom.get(): "+zoom.get()*100 +"%\n");
}
#FXML private void zoomOut() {
zoom.set(zoom.get()/1.1);
// System.out.print("zoom.get(): "+zoom.get()*100 +"%\n");
}
#FXML private void zoomFit() {
}
#FXML private void zoomWidth() {
}
private class PageDimensions {
private double width ;
private double height ;
PageDimensions(double width, double height) {
this.width = width ;
this.height = height ;
}
#Override
public String toString() {
return String.format("[%.1f, %.1f]", width, height);
}
}
}
PdfModel
package application;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.PDFRenderer;
/**
* #author toru
*/
class PdfModel {
//private static final Logger logger = Logger.getLogger(PdfModel.class.getName());
private PDDocument document;
private PDFRenderer renderer;
Path chemin;
PdfModel() {
}
PdfModel(Path path) {
try {
chemin=path;
document = PDDocument.load(path.toFile());
renderer = new PDFRenderer(document);
} catch (IOException ex) {
throw new UncheckedIOException("PDDocument thorws IOException file=" + path, ex);
}
}
int nombreDePages() {
return document.getPages().getCount();
}
PDPage getPage (int num) {
PDPage page = document.getPage(num);
return page;
}
void fermer() {
try {
document.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void setPath(Path pPays)
{
chemin = pPays;
System.out.println("On est dans la page pdfmodel");
System.out.println("Path: "+pPays);
}
Image getImage(int pageNumber) {
BufferedImage pageImage;
try {
pageImage = renderer.renderImage(pageNumber);
} catch (IOException ex) {
throw new UncheckedIOException("PDFRenderer throws IOException", ex);
}
return SwingFXUtils.toFXImage(pageImage, null);
}
}
ui.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="10.0" minWidth="10.0" prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<bottom>
<HBox prefHeight="50.0" prefWidth="400.0" BorderPane.alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#zoomIn" text="+">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomOut" text="-">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomFit" text="ZoomFit">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomWidth" text="ZoomWidth">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<VBox fx:id="vbox" prefHeight="350.0" prefWidth="400.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*#author toru
*/
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Parent parent = FXMLLoader.load(getClass().getResource("ui.fxml"));
primaryStage.setTitle("Zoom ImageView Demo ");
primaryStage.setScene(new Scene(parent,800, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Best regards
Use the two-parameter renderImage(page, scale) method. 1 is the default scale and is 72 dpi, 4 is 288 dpi which is usually pretty good. So I suggest you start with scale 4, and in a later step you increase when zooming (note that rendering may become slower with higher resolutions).
So a code example for your code would be
pageImage = renderer.renderImage(pageNumber, 4);
I have strange problem while dragging selected text from TextArea. The text is properly selected but when iam dragging to be place on the target position, the selection of text is changed, it reduce the selection for 2-3 characters randomly.
Here is the complete class :
public class DnDMainController extends Application {
ClipboardContent cb = new ClipboardContent();
ObservableList<String> list = FXCollections.observableArrayList();
#FXML
private TextArea sourceText;
#FXML
private ListView<String> listView;
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/main/DnD.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Simple Drag and Drop ExampleGame");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
#FXML
void _detectDrag(MouseEvent event) {
Dragboard db = sourceText.startDragAndDrop(TransferMode.COPY);
cb.putString(sourceText.getSelectedText());
db.setContent(cb);
event.consume();
}
#FXML
void _dragExited(DragEvent event) {
String st = event.getDragboard().getString();
if (!(list.contains(st.trim()))) {
list.add(st);
listView.getItems().addAll(list);
}}
}
[![gif for DnD Issue][1]][1]
I have tried the same on TextField and it is working perfectly on TextField. But unfortunatelly i can not use the TextField due to large string of text. I dont know what Iam doing wrong...
FXML CODE:
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="549.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.DnDMainController">
<children>
<TextArea fx:id="sourceText" layoutY="273.0" onDragDetected="#_detectDrag" prefHeight="127.0" prefWidth="550.0" text="There was once a velveteen rabbit, and in the beginning he was really splendid. He was fat and bunchy, as a rabbit should be; his coat was spotted brown and white, he had real thread whiskers, and his ears were lined with pink sateen. On Christmas morning, when he sat wedged in the top of the Boy’s stocking, with a sprig of holly between his paws, the effect was charming." wrapText="true">
<font>
<Font size="19.0" />
</font></TextArea>
<ListView fx:id="listView" layoutY="40.0" onDragExited="#_dragExited" onMouseClicked="#_callContext" prefHeight="200.0" prefWidth="516.0" />
<Label alignment="CENTER" contentDisplay="CENTER" layoutX="-2.0" layoutY="2.0" prefHeight="38.0" prefWidth="550.0" text="List of Words" textAlignment="CENTER" />
<Label alignment="CENTER" contentDisplay="CENTER" layoutX="7.0" layoutY="240.0" prefHeight="32.0" prefWidth="542.0" text="Story" textAlignment="CENTER" />
</children>
</AnchorPane>```
I ran into a few problems trying to implement this in a straightforward way. I had to create a toggle that would allow me to select text and then drag the text. During the drag, I noticed that it would not grab all of the selected text unless the drag was started at the end of the selected text. I fixed that by grabbing the selected text after it was selected and the toggle mode is changed to drag mode. MCVE below.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Parent;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Test.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Simple Drag and Drop ExampleGame");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="583.0" prefWidth="851.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javaapplication12.TestController">
<children>
<ListView fx:id="listView" layoutX="326.0" layoutY="14.0" onDragDropped="#dragDropped" onDragEntered="#dragEntered" onDragOver="#dragOver" prefHeight="200.0" prefWidth="200.0" />
<TextArea fx:id="textArea" layoutX="224.0" layoutY="274.0" onDragDetected="#dragDetected" prefHeight="247.0" prefWidth="426.0" text="There was once a velveteen rabbit, and in the beginning he was really splendid. He was fat and bunchy, as a rabbit should be; his coat was spotted brown and white, he had real thread whiskers, and his ears were lined with pink sateen. On Christmas morning, when he sat wedged in the top of the Boy’s stocking, with a sprig of holly between his paws, the effect was charming." wrapText="true" />
<ToggleButton fx:id="tbtnDragMode" layoutX="44.0" layoutY="26.0" mnemonicParsing="false" onAction="#handleTbtnDragMode" text="Select Text Mode" />
</children>
</AnchorPane>
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
public class TestController implements Initializable {
#FXML TextArea textArea;
#FXML ListView listView;
#FXML ToggleButton tbtnDragMode;
ObservableList<String> list = FXCollections.observableArrayList();
String selectedText = "";
#Override
public void initialize(URL url, ResourceBundle rb) {
listView.setItems(list);
list.add("test");
}
#FXML private void handleTbtnDragMode(ActionEvent actionEvent)
{
if(tbtnDragMode.isSelected())
{
System.out.println("Drag Mode On");
tbtnDragMode.setText("Drag Mode");
selectedText = textArea.getSelectedText().isBlank() ? "" : textArea.getSelectedText();
}
else {
System.out.println("Drag Mode Off");
tbtnDragMode.setText("Select Text Mode");
}
}
#FXML
private void dragDetected(MouseEvent event) {
System.out.println("drag detected 1");
System.out.println(tbtnDragMode.isSelected());
if(tbtnDragMode.isSelected())
{
System.out.println("drag detected 2");
/* drag was detected, start a drag-and-drop gesture*/
/* allow any transfer mode */
Dragboard db = textArea.startDragAndDrop(TransferMode.ANY);
/* Put a string on a dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(selectedText);
db.setContent(content);
event.consume();
}
}
#FXML
private void dragEntered(DragEvent event) {
System.out.println("dragEntered");
event.consume();
}
#FXML
private void dragDropped(DragEvent event)
{
System.out.println("Drag dropped");
/* data dropped */
/* if there is a string data on dragboard, read it and use it */
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
list.add(db.getString());
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
}
#FXML
private void dragDone(DragEvent event) {
/* the drag and drop gesture ended */
/* if the data was successfully moved, clear it */
System.out.println("drag done");
if (event.getTransferMode() == TransferMode.MOVE) {
//clear textarea selection
System.out.println("drag done");
}
event.consume();
}
#FXML
private void dragExited(DragEvent event) {
System.out.println("dragExited");
event.consume();
}
#FXML
private void dragOver(DragEvent event) {
/* data is dragged over the target */
/* accept it only if it is not dragged from the same node
* and if it has a string data */
System.out.println(event.getGestureSource() + " - " + event.getTarget());
if (event.getGestureSource() != event.getTarget() &&
event.getDragboard().hasString()) {
/* allow for both copying and moving, whatever user chooses */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
}
}
This question already has answers here:
The table cells are empty in my tableview. JavaFX + Scenebuilder
(2 answers)
Closed 4 years ago.
In my application Some of the columns in my table are populating like they should be the columns labeled Name Priority and BurstTime have the correct values being added but for some reason the other two ProcessID and State do not update with the values I am adding to my ArrayList.
It looks like my code should be working can anybody see something I have missed?
Here is my controller
package application;
import java.net.URL;
import java.util.ResourceBundle;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringTokenizer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
public class Controller implements Initializable {
private ArrayList<String> buf = new ArrayList<>();
protected ArrayList<PCB> array = new ArrayList<>();
protected ArrayList<Process> arrayP = new ArrayList<>();
ObservableList<Process> processData = FXCollections.observableArrayList();
#FXML
private Button SubmitButton;
#FXML
private Button LoadButton;
#FXML
private TextArea textArea;
#FXML
private TextField inputBox;
#FXML
private TableView<Process> ProcessTable;
#FXML
private TableColumn<Process, String> processIDP;
#FXML
private TableColumn<Process, String> processTypeP;
#FXML
private TableColumn<Process, String> priorityCodeP;
#FXML
private TableColumn<Process, String> burstTimeP;
#FXML
private TableColumn<Process, String> StatusCodeP;
#Override
public void initialize(URL url, ResourceBundle rb) {
processIDP.setCellValueFactory(new PropertyValueFactory<Process, String>("processIDP"));
processTypeP.setCellValueFactory(new PropertyValueFactory<Process, String>("processTypeP"));
priorityCodeP.setCellValueFactory(new PropertyValueFactory<Process, String>("priorityCodeP"));
burstTimeP.setCellValueFactory(new PropertyValueFactory<Process, String>("burstTimeP"));
StatusCodeP.setCellValueFactory(new PropertyValueFactory<Process, String>("StatusCodeP"));
Process p1 = new Process();
p1.setprocessIDP("22");
p1.setProcessTypeP ("Apname");
p1.setPriorityCodeP("1");
p1.setBurstTimeP ("13");
p1.setstatusCodeP("Tada");
arrayP.add(p1);
ProcessTable.getItems().addAll(arrayP.get(0));
ProcessTable.setItems(FXCollections.observableArrayList(arrayP));
Process p2 = new Process();
p2.setprocessIDP("24");
p2.setProcessTypeP ("Bpname");
p2.setBurstTimeP ("15");
p2.setPriorityCodeP("2");
arrayP.add(p2);
ProcessTable.getItems().addAll(arrayP.get(1));
// edit existing cell ?
arrayP.get(1).setPriorityCodeP("8");
arrayP.get(1).setstatusCodeP("This");
arrayP.get(1).setprocessIDP("TEST");
}
public ObservableList<Process> getProcessData() {
return processData;
}
#FXML
private TextField LoadProgram;
#FXML
private void handleButtonAction() {
textArea.appendText(inputBox.getText() + "\n");
StringTokenizer st1 = new StringTokenizer(inputBox.getText(), " ");
switch(st1.nextToken()) {
// case "proc": proc(); break;
case "mem": textArea.appendText("Memory: " + String.valueOf(Memory.getUsedMemory()) + "/" + String.valueOf(Memory.getTotalMemory()) + "\n"); break;
// case "exe": exe(); break;
// case "reset": reset(); break;
case "load": buf.add(inputBox.getText()) ;
// edit existing cell ?
arrayP.get(1).setPriorityCodeP("9");
ProcessTable.refresh();
break;
case "exit": System.exit(0); break;
case "clear": textArea.clear(); break;
default: break;
}
}
#FXML
private void handleLoadAction() {
File infile = new File("files/" + LoadProgram.getText() + ".txt");
if (infile.exists() == true ) {
textArea.appendText("Loading " + LoadProgram.getText() + "\n");
}
//call to read data here
else {
textArea.appendText("No Program named " + LoadProgram.getText() + " found \n");
}}
public class textLine {
private String infile;
private String cmd, value;
private Scanner input;
public void parseFile(String filename) {
this.infile = "files/" + filename + ".txt";
parseFile();
}
public void addbuf(String textline) {
buf.add(textline);
}
private void parseFile() {
buf.clear();
try {
File file = new File(infile);
if (file.exists() == true)
input = new Scanner(file);
while (input.hasNext()) {
buf.add(input.next());
}
} catch (Exception e) {
e.printStackTrace();
}
input.close();
}
}
}
Here is my class for Procsess
package application;
public class Process {
String processTypeP = "";
String priorityCodeP = "0";
int lineCodeP = 0;
String burstTimeP = "0";
String processIDP = "0";
String StatusCodeP = "0";
public Process (){}
public String getProcessTypeP() {
return processTypeP;
}
public void setProcessTypeP(String processTypeP) {
this.processTypeP = processTypeP;
}
public String getPriorityCodeP() {
return priorityCodeP;
}
public void setPriorityCodeP(String priorityCodeP) {
this.priorityCodeP = priorityCodeP;
}
public int getLineCodeP() {
return lineCodeP;
}
public void setLineCodeP(int lineCodeP) {
this.lineCodeP = lineCodeP;
}
public String getBurstTimeP() {
return burstTimeP;
}
public void setBurstTimeP(String burstTimeP) {
this.burstTimeP = burstTimeP;
}
public String getprocessIDP() {
return processIDP;
}
public void setprocessIDP(String processIDP) {
this.processIDP = processIDP;
}
public String getstatusCodeP() {
return StatusCodeP;
}
public void setstatusCodeP(String StatusCodeP) {
this.StatusCodeP = StatusCodeP;
}
}
Here is my main application
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("/Main.fxml"));
// Parent root = FXMLLoader.load(getClass().getResource("/Main.fxml"));
AnchorPane root = (AnchorPane) loader.load(Main.class.getResource("/application/Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
and my fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<TabPane layoutX="4.0" layoutY="4.0" prefHeight="700.0" prefWidth="900.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Processes">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField fx:id="inputBox" layoutX="14.0" layoutY="54.0" />
<Button fx:id="SubmitButton" layoutX="109.0" layoutY="94.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Submit" />
<TextArea fx:id="textArea" layoutX="197.0" layoutY="14.0" prefHeight="105.0" prefWidth="493.0" />
<TableView fx:id="ProcessTable" layoutX="36.0" layoutY="157.0" prefHeight="430.0" prefWidth="654.0">
<columns>
<TableColumn fx:id="processIDP" prefWidth="75.0" text="ProccessID" />
<TableColumn fx:id="processTypeP" prefWidth="101.0" text="Name" />
<TableColumn fx:id="priorityCodeP" prefWidth="94.0" text="Priority" />
<TableColumn fx:id="StatusCodeP" prefWidth="119.0" text="State" />
<TableColumn fx:id="burstTimeP" prefWidth="100.0" text="BurstTime" />
</columns>
</TableView>
<TextField fx:id="LoadProgram" layoutX="712.0" layoutY="492.0" />
<Button fx:id="LoadProgramButton" layoutX="725.0" layoutY="531.0" mnemonicParsing="false" onAction="#handleLoadAction" text="Load External Program" />
</children></AnchorPane>
</content>
</Tab>
<Tab text="Scheduler">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Memory">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Try renaming your getter methods from getprocessIDP and getstatusCodeP to getProcessIDP and getStatusCodeP respectively (note the capital 'S' and 'P'). To avoid problems like this in the future it's a good habit to generate getters, setters and constructors with the IDE instead of doing it manually.
I have an ImageView inside an AnchorPane, built using FXML.
<fx:root prefHeight="600.0" prefWidth="800.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.LifeMandelbrot">
<children>
<ImageView fx:id="view" fitHeight="600.0" fitWidth="800.0" onMouseClicked="#moveCenter" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<HBox alignment="CENTER" spacing="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<Button fx:id="zoomOut" mnemonicParsing="false" onAction="#zoomOut" text="Zoom-" />
<Button fx:id="zoomIn" mnemonicParsing="false" onAction="#zoomIn" text="Zoom+" />
<Button fx:id="defaultView" mnemonicParsing="false" onAction="#defaultView" text="Vue par défaut" />
</children>
</HBox>
</children>
</fx:root>
As you can see, the ImageView fits the AnchorPane using anchors.
When I click one of the button, the ImageView is repainted.
Problem:
view.getFitWidth() always shows 0, same for the height.
EDIT
The controller code looks like that:
package application;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
public class LifeMandelbrot extends AnchorPane implements Initializable {
private static final double DEFAULT_ZOOM = 200.0;
private static final Complex DEFAULT_CENTER = new Complex(0, 0);
private static final double ZOOM_RATIO = 1.2;
#FXML
private Button zoomOut;
#FXML
private Button zoomIn;
#FXML
private Button defaultView;
#FXML
private Button julia;
#FXML
ImageView view;
private double zoom;
private Complex center;
private List<Color> colors;
private int colorStep;
public LifeMandelbrot() {
zoom = DEFAULT_ZOOM;
center = DEFAULT_CENTER;
colors = new ArrayList<Color>();
colors.add(Color.RED);
colors.add(Color.GREEN);
colors.add(Color.BLUE);
colorStep = 20;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
repaint();
view.fitWidthProperty().bind(widthProperty());
view.fitHeightProperty().bind(heightProperty());
}
#FXML
void defaultView(ActionEvent event) {
zoom = DEFAULT_ZOOM;
center = DEFAULT_CENTER;
repaint();
}
#FXML
void julia(ActionEvent event) {
}
#FXML
void zoomIn(ActionEvent event) {
zoom *= ZOOM_RATIO;
repaint();
}
#FXML
void zoomOut(ActionEvent event) {
zoom /= ZOOM_RATIO;
repaint();
}
#FXML
void moveCenter(MouseEvent event) {
center = fractalFromView(event.getX(), event.getY());
repaint();
}
private void repaint() {
WritableImage image = new WritableImage((int) view.getFitWidth(), (int) view.getFitHeight());
PixelWriter pw = image.getPixelWriter();
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Complex c = fractalFromView(x, y);
int iterations = Fractal.mandelbrot(c);
if (iterations == -1) {
pw.setColor(x, y, new Color(0, 0, 0, 1));
} else {
int colorIndex = iterations / colorStep;
int colorAdd = iterations % colorStep;
Color color1 = colors.get(colorIndex % colors.size());
Color color2 = colors.get((colorIndex + 1) % colors.size());
Color color = color1.interpolate(color2, (double) colorAdd / colorStep);
pw.setColor(x, y, color);
}
}
}
view.setImage(image);
}
private Complex fractalFromView(double x, double y) {
return new Complex((x - view.getFitWidth() / 2) / zoom + center.getReal(),
(y - view.getFitHeight() / 2) / zoom + center.getImaginary());
}
}
Loaded from there:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("../lifeMandelbrot.fxml"));
loader.setRoot(new LifeMandelbrot());
AnchorPane root = loader.load();
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("LIFE Is a Fractal Explorer");
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
You have two instances of LifeMandelbrot: one you create by calling the constructor and explicitly set as the dynamic root of the FXML; the other is created for you by the FXMLLoader and is used as the controller. The one you create you use in the scene graph (scene = new Scene(root)). The one that is created as the controller is never placed in the scene graph. Consequently it never undergoes layout and always has width and height of zero.
Of course, the handler methods and initialize() methods are called on the "controller instance", not the "root instance", so you bind fitWidth and fitHeight to zero.
You need
FXMLLoader loader = new FXMLLoader(getClass().getResource("../lifeMandelbrot.fxml"));
LifeMandelbrot root = new LifeMandelbrot();
loader.setRoot(root);
loader.setController(root);
loader.load();
Scene scene = new Scene(root);
and then you need to remove the fx:controller attribute from the root element of the FXML. This way the controller and root node are the same instance.
Since your FXML already explicitly ties itself to an AnchorPane by using the anchor pane settings on the child nodes, it might be clearer just to use the standard pattern for this. I.e.
<AnchorPane fx:id="root" fx:controller="application.LifeMandelbrot" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="view" onMouseClicked="#moveCenter" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<HBox alignment="CENTER" spacing="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<Button fx:id="zoomOut" mnemonicParsing="false" onAction="#zoomOut" text="Zoom-" />
<Button fx:id="zoomIn" mnemonicParsing="false" onAction="#zoomIn" text="Zoom+" />
<Button fx:id="defaultView" mnemonicParsing="false" onAction="#defaultView" text="Vue par défaut" />
</children>
</HBox>
</children>
</AnchorPane>
In the controller:
public class LifeMandelbrot implements Initializable {
#FXML
private AnchorPane root ;
// existing code...
#Override
public void initialize(URL location, ResourceBundle resources) {
repaint();
view.fitWidthProperty().bind(root.widthProperty());
view.fitHeightProperty().bind(root.heightProperty());
}
// existing code...
}
and then just
FXMLLoader loader = new FXMLLoader(getClass().getResource("../lifeMandelbrot.fxml"));
Scene scene = new Scene(loader.load());