0

I am working on an JavaFX interface for a program, and I am trying to add pagination to a table.

Here is a part of my controller code (what I omitted in adding is handles for some buttons from my interface)

public class AllController {

private RaportPDF wrpdf;

private final static int rowsPerPage = 10;

public void updateSarcina(Observable<Sarcina> observable) 
{
    SarcinaService service = (SarcinaService)observable;
    smodel.setAll(service.getAllSarcinas());
}
public void updatePost(Observable<Post> observable) 
{
    PostService service = (PostService)observable;
    pmodel.setAll(service.getAllPosts());
}
public void updateFisa(Observable<Elementfisa> observable) 
{
    FisaService service = (FisaService)observable;
    fmodel.setAll(service.getAllFisa());
}

public Observer<Sarcina> getSarcinaObserver() 
{
    return new Observer<Sarcina>() 
    {
        @Override
        public void update(Observable<Sarcina> observable) 
        {
            updateSarcina(observable);
        }
    };
}
public Observer<Post> getPostObserver() 
{
    return new Observer<Post>() 
    {
        @Override
        public void update(Observable<Post> observable) 
        {
            updatePost(observable);
        }
    };
}
public Observer<Elementfisa> getFisaObserver() 
{
    return new Observer<Elementfisa>() 
    {
        @Override
        public void update(Observable<Elementfisa> observable) 
        {
            updateFisa(observable);
        }
    };
}


@SuppressWarnings("rawtypes")
@FXML private TableView allTable;

private TableColumn<Sarcina, String> sFirstColumn;
private TableColumn<Sarcina, String> sSecondColumn;
private TableColumn<Post, String> pFirstColumn;
private TableColumn<Post, String> pSecondColumn;
private TableColumn<Elementfisa, String> fFirstColumn;
private TableColumn<Elementfisa, String> fSecondColumn;

@FXML private ComboBox<String> ComboObject;

@FXML private Label firstLabel;
@FXML private Label secondLabel;
@FXML private Label thirdLabel;

@FXML private TextField firstTextField;
@FXML private TextField secondTextField;
@FXML private TextField thirdTextField;
@FXML private TextField filterTextField;

@FXML private RadioButton radioButtonFirst;
@FXML private RadioButton radioButtonSecond;
@FXML private Button addButton;
@FXML private Button updateButton;
@FXML private Button deleteButton;
@FXML private Button clearFieldsButton;
@FXML private Button raportButton;
@FXML private Pagination pagination ;
SarcinaService sservice;
PostService pservice;
FisaService fservice;

ObservableList<Sarcina> smodel;
ObservableList<Post> pmodel;
ObservableList<Elementfisa> fmodel;

private String currentComboBoxString;

private Boolean isSelectedFC;
private Boolean isSelectedSC;

ToggleGroup toggleRadioGroup = new ToggleGroup();

public AllController() 
{

}
private int intValidate(String e) 
{
    for(int i = 0; i < e.length(); i++) 
    {
        if(i == 0 && e.charAt(i) == '-') 
        {
            if(e.length() == 1) 
            {
                showErrorMessage("Numar invalid !");
                return -1;
            }
            else continue;
        }
        if(Character.digit(e.charAt(i), 10) < 0) 
        {
            showErrorMessage("Numar invalid !");
            return -1;
        }
    }
    return Integer.parseInt(e);
}
@SuppressWarnings("unchecked")
private void fillItemsOnTable(boolean justColumns) 
{
    @SuppressWarnings("rawtypes")
    ObservableList localModel = null;
    if (currentComboBoxString.equals("Sarcina")) 
    {
        allTable.getColumns().clear();
        allTable.getColumns().add(sFirstColumn);
        allTable.getColumns().add(sSecondColumn);
        localModel = this.smodel;
    }
    else if (currentComboBoxString.equals("Post")) 
    {
        allTable.getColumns().clear();
        allTable.getColumns().add(pFirstColumn);
        allTable.getColumns().add(pSecondColumn);
        localModel = this.pmodel;
    }
    else if (currentComboBoxString.equals("Fisa")) 
    {
        allTable.getColumns().clear();
        allTable.getColumns().add(fFirstColumn);
        allTable.getColumns().add(fSecondColumn);
        localModel = this.fmodel;
    }
    if (!justColumns)
        allTable.setItems(localModel);
}

@FXML public void handleRaport()
{
    if (isSelectedFC) 
    {
        ObservableList<Sarcina> model = FXCollections.observableArrayList(fservice.filterRapoarte());
        ComboObject.setValue("Sarcina");
        this.fillItemsOnTable(true);
        allTable.setItems(model);
        wrpdf.addPdf(model);
    }


}

public void setService(SarcinaService sservice, PostService pservice, FisaService fservice) 
{
    this.sservice = sservice;
    this.pservice = pservice;
    this.fservice = fservice;

    this.smodel = FXCollections.observableArrayList(sservice.getAllSarcinas());
    this.pmodel = FXCollections.observableArrayList(pservice.getAllPosts());
    this.fmodel = FXCollections.observableArrayList(fservice.getAllFisa());

    this.fillItemsOnTable(false);
}
@FXML private void onActionComboBox(ActionEvent event) 
{
    String current = ComboObject.getSelectionModel().getSelectedItem();
    if (current.compareTo(currentComboBoxString) != 0) 
    {
        currentComboBoxString = current;
        if (current.equals("Sarcina")) 
        {
            secondLabel.setText("Desc: ");
            radioButtonSecond.setText("By Desc");
            thirdLabel.setVisible(false);
            radioButtonFirst.setVisible(false);
            thirdTextField.setVisible(false);
        }
        else if (current.equals("Post")) 
        {
            secondLabel.setText("Name: ");
            thirdLabel.setText("Type: ");
            radioButtonFirst.setText("By Name");
            radioButtonSecond.setText("By Type");
            thirdLabel.setVisible(true);
            radioButtonFirst.setVisible(true);
            thirdTextField.setVisible(true);
        }
        else if (current.equals("Fisa")) 
        {
            secondLabel.setText("Sarcina ID: ");
            thirdLabel.setText("Post ID: ");
            radioButtonFirst.setText("By Sarcina");
            radioButtonSecond.setText("By Post");
            thirdLabel.setVisible(true);
            radioButtonFirst.setVisible(true);
            thirdTextField.setVisible(true);
        }
        this.fillItemsOnTable(false);
    }
}

//pagination;

public int itemsPerPage() {
    return 1;
}

public int rowsPerPage() {
    return 5;
}

@SuppressWarnings("unchecked")
private Node createPage(int pageIndex) 
{
    int fromIndex = pageIndex * rowsPerPage;
    int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
    allTable.setItems(FXCollections.observableArrayList(data.subList(fromIndex, toIndex)));

    return new BorderPane(allTable);
}

//pagination


@SuppressWarnings("unchecked")
@FXML private void initialize() 
{
    ComboObject.getItems().addAll(
            "Sarcina",
            "Post",
            "Fisa"
        );
    currentComboBoxString = "Sarcina";
    ComboObject.setValue("Sarcina");

    sFirstColumn = new TableColumn<>("ID");
    sSecondColumn = new TableColumn<>("Desc");
    pFirstColumn = new TableColumn<>("Name");
    pSecondColumn = new TableColumn<>("Type");
    fFirstColumn = new TableColumn<>("Sarcina");
    fSecondColumn = new TableColumn<>("Post");

    sSecondColumn.setCellValueFactory(new PropertyValueFactory<Sarcina, String>("Desc"));
    sFirstColumn.setCellValueFactory(new  PropertyValueFactory<Sarcina, String>("Id"));     
    pFirstColumn.setCellValueFactory(new PropertyValueFactory<Post, String>("Nume"));
    pSecondColumn.setCellValueFactory(new PropertyValueFactory<Post, String>("Tip"));



    fFirstColumn.setCellValueFactory(new Callback<CellDataFeatures<Elementfisa, String>, ObservableValue<String>>()
    {
         public ObservableValue<String> call(CellDataFeatures<Elementfisa, String> p) 
         {
             if (p.getValue() != null && p.getValue().getSarcina() != null) 
             {
                  return new SimpleStringProperty(p.getValue().getSarcina().getDesc());
             } else 
             {
                 return new SimpleStringProperty("Empty");
             }
         }
      });
    fSecondColumn.setCellValueFactory(new Callback<CellDataFeatures<Elementfisa, String>, ObservableValue<String>>() 
    {
         public ObservableValue<String> call(CellDataFeatures<Elementfisa, String> p) 
         {
             if (p.getValue() != null && p.getValue().getPost() != null) 
             {
                  return new SimpleStringProperty(p.getValue().getPost().getNume());
             } else 
             {
                 return new SimpleStringProperty("Empty");
             }
         }
      });
    isSelectedFC = true;
    isSelectedSC = false;
    radioButtonFirst.setToggleGroup(toggleRadioGroup);
    radioButtonSecond.setToggleGroup(toggleRadioGroup);
    radioButtonFirst.setSelected(true);

    allTable.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
        if (newSelection != null) 
        {
            if (currentComboBoxString.equals("Sarcina")) 
            {
                firstTextField.setText(((Sarcina) newSelection).getId().toString());
                thirdTextField.setText("N/A");
                secondTextField.setText(((Sarcina) newSelection).getDesc());
            }
            else if (currentComboBoxString.equals("Post")) 
            {
                firstTextField.setText(((Post) newSelection).getId().toString());
                secondTextField.setText(((Post) newSelection).getNume());
                thirdTextField.setText(((Post) newSelection).getTip());
            }
            else if (currentComboBoxString.equals("Fisa")) 
            {
                firstTextField.setText(((Elementfisa) newSelection).getId().toString());
                secondTextField.setText(((Elementfisa) newSelection).getSarcina().getId().toString());
                thirdTextField.setText(((Elementfisa) newSelection).getPost().getId().toString());
            }
        }
    });
}

private void clearFields() 
{
    firstTextField.setText("");
    secondTextField.setText("");
    thirdTextField.setText("");
}

And here is the code from my "main" class:

public class PrimaryLayoutMain extends Application {

AnchorPane apview;
BorderPane rootLayout;
Stage primaryStage;

SarcinaXMLRepo srep;
SarcinaService sservice;
PostXMLRepo prep;
PostService pservice;
ElementFisaRepo frep;
FisaService fservice;

FXMLLoader loader;

@Override
public void start(Stage primaryStage) {
    srep = new SarcinaXMLRepo(new ValidatorSarcina(), "SarcinaXMLRepo.xml");
    sservice = new SarcinaService(srep);
    prep = new PostXMLRepo(new ValidatorPost(), "PostXMLRepo.xml");
    pservice = new PostService(prep);
    frep = new ElementFisaRepo(new ValidatorEF());
    fservice = new FisaService(frep);

    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("Management de sarcini.");

    loader = new FXMLLoader();

    initRootLayout();        
    initView();       
}

private void initView() {
    try {
        String pathToFxml = "src/fisapost/view/PrimaryLayout.fxml";
        URL fxmlUrl = new File(pathToFxml).toURI().toURL();
        loader.setLocation(fxmlUrl);
        apview = (AnchorPane) loader.load();
        rootLayout.setCenter(apview);

        AllController viewCtrl = loader.getController();
        viewCtrl.setService(sservice, pservice, fservice);
        sservice.addObserver(viewCtrl.getSarcinaObserver());
        pservice.addObserver(viewCtrl.getPostObserver());
        fservice.addObserver(viewCtrl.getFisaObserver());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void initRootLayout() {
    try {

        FXMLLoader loader = new FXMLLoader();
        String pathToFxml = "src/fisapost/view/RootLayout.fxml";
        URL fxmlUrl = new File(pathToFxml).toURI().toURL();
        loader.setLocation(fxmlUrl);
        rootLayout = (BorderPane) loader.load();


        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
}

public static void main(String[] args) {
    launch(args);
}

}

I found this solution pretty useful, but I can't implement it correctly in my program. For one, my main and controller classes are separate, and I don't initialize manually a data array with elements at the start of the code (the data for my ObservableList arrays is read from a file).enter image description here

The interface after I run the code looks like this. How can I add pagination to every table, since I also have a ComboBox that changes the table when I select different values in it? I also used SceneBuilder for the entire interface.

Artyomska
  • 1,309
  • 5
  • 26
  • 53
  • The basic structure where you reuse a single table (of unknown type) and repopulate its columns and data just seems wrong. Why not create three separate tables and just show the one that's chosen? Then it should be easy to wrap each table in its own `Pagination`. – James_D Jan 04 '17 at 16:41
  • I still want to do something before rewriting a big part of my code. If I have _private Node createPage(int pageIndex,ObservableList data)_ in this manner, how could I pass the ObservableList argument here? _pagination.setPageFactory(this::createPage);_ – Artyomska Jan 04 '17 at 17:13
  • I strongly recommend against that. This is just the wrong approach: look at how many `SuppressWarnings` you have had to use in order to get it to work. Do you really want to build more code on top of that, so that you have more code to fix later? Though it's not really clear where you are stuck: just wrap the table in a pagination; you will need to add code to reset it to the first page when the table content changes. – James_D Jan 04 '17 at 17:15
  • As for the question in the previous comment, you can do `pagination.setPageFactory(pageIndex -> createPage(pageIndex, whicheverList));`. But surely you can figure out which list you are currently using in the `createPage(...)` method anyway? – James_D Jan 04 '17 at 17:20
  • The problem is that I don't know how to wrap the table in a pagination :/ and in my opinion the problem lies at _createPage_ procedure. Who is the "data" list in my code, since I have smodel,pmodel and fmodel as ObservableList's, and when I try to pass any of them there I receive a _java.lang.NullPointerException_ error, since they are empty. – Artyomska Jan 04 '17 at 17:20
  • You have already linked a question that shows you how to wrap a table in a pagination. If you don't know how to fix a null pointer exception, read http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it – James_D Jan 04 '17 at 17:23
  • I found a solution (also written by you :) ) [here](https://stackoverflow.com/questions/36666169/javafx-tableview-pagination-can-not-create-fxml-based-solution?noredirect=1&lq=1). But it also uses the _data_ list. The thing I really don't understand is who is _data_ for me. I mean, at createPage, who is the list I should give as ObservableList? I really don't get this :(, since smodel,pmodel,fmodel are seemingly empty, and I don't have any other lists. – Artyomska Jan 04 '17 at 18:02
  • Are they empty, or null? If they are empty, you would not get a null pointer exception. They seem to be initialized when you call `setService(...)`, so you just need to make sure that is called before you try to do anything with the lists. Not at all sure what that has to do with pagination. Again, though, if you weren't trying to reuse a single table view for three different things, none of this would be a problem. – James_D Jan 04 '17 at 18:05
  • They are null I think (I get the null error when I try to assign any of them instead of _data_ in createPage). – Artyomska Jan 04 '17 at 18:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132329/discussion-between-artyomska-and-james-d). – Artyomska Jan 04 '17 at 18:40
  • Sadly, nothing seems to work. I tried everything I could think of, following what you said closely. If you know how to do it, can you explain please step by step (so I could write the code myself and understand) how should I proceed adding pagination without making three different tables? Please. – Artyomska Jan 04 '17 at 19:16
  • I've already told you the answer is to make three different tables. – James_D Jan 04 '17 at 19:16

0 Answers0