How to fill combobox having different controllers from database? - java

I'm having a problem and I don't know how to solve it. I'm building a "food company" and want to write a program to control the items that have been bought/sold, etc.
I have viewDrinks.fxml, jdbcDrinks.java, controllerDrinks.java where I controll the drinks, for adding or deleting them and persisting them in a database.
But now, I have another view called "Sales" where I want to choose from a ComboBox what drink I want to sell. I'm not sure how I should fill this combobox with items that are not in jdcbSales, sales.fxml and controllerSales.fxml.
I been trying differrent approaches but I haven't found a working solution.
On my controllerSales I have:
jdbcDrinks databaseObject;
#FXML
private ComboBox drinkField;
public void initialize(URL location, ResourceBundle resources) {
ObservableList<String> drinkList = FXCollections.observableArrayList(databaseObject);
this.drinkField.setItems(drinkList);
this.drinkField.setEditable(false);
this.drinkField.getSelectionModel().select(0);
}
In jdbcDrinks I have:
public void getDrinkName{
ps = conexion.prepareStatement("SELECT name FROM drinks");
rs = ps.executeQuery();
}
I want to write a method in jdbcDrinks to get the items from the database, but I'm not sure how to write it and use it on controllerSales.

Related

Binding String ArrayList to JList

I have created a client -> server chat room system, and I have a list of currently connected users, which is currently displayed on a button click within a JTextField, this currently works fine and displays the string array. However, I have added another component to my GUI, being a JList. I have been trying to create a method called updateUserList to update the JList with the users that are connected. I have tried to use a DefaultListModel of type String, however this displays nothing in the JList and I am unsure as to why.
Below is the updateUserList method I have created:
public void updateUserList()
{
model = new DefaultListModel<String>();
for(String usernames : users)
model.addElement(usernames);
jl_users = new JList<String>(model);
}
Please note that model, usernames and jl_users are defined globally, therefore I have not included them in the post.
Why are you using DefaultListModel?
If you want a simply List just use it like this
public void updateUserList()
{
jl_users = new JList<String>(users.toArray(new String[users.size()]));
}
or straight forward
jl_users = new JList(users.toArray());

Adding row to a TableView from a different controller in JavaFX

In this app that i am building i have in one stage a TableView and a few buttons. When i click on one of the buttons it opens a new window that is made of TextFields and a "OK" button. When i click on the OK, i need to insert that data into a Table.
So, i know how to insert a row into a TableView from a controller that controlles that TableView, but now i need to insert it from controller of another window. I tried everything, and it doesent work. I tried to get an instance of TableController and pass the data to its method, then i tried to pass ObservableList to a NewWindowController, and that also doesent work. I'm out of ideas. Can someone help me with this, i would appreciate it. Thank you.
Part of the code:
public class MainController {
#FXML public TableView<Film> tabel;
public TableView<Film> getTabel(){
return tabel;
}
}
newWindow'sController:
public UnosController(){
#FXML protected void insert(ActionEvent e){
Film film = new Film(funosNaziv.getText(), funosZanr.getText(),Integer.valueOf(funosGodina.getText()));
TableView<Film> tabel = mainController.getTabel();
ObservableList<Film> data = tabel.getItems();
data.add(film);
}
}
That is my last try. Doesent work.

How to remove rows in a TableView javafx

I have been trying to add a remove button so that it removes a selected row in my tableview. My problem is slightly different from those i have found elsewhere. My problem lies behind the fact that in my application i have used 1 FXML file as the basis of several different interfaces. When i initialize 1 of these and use the functionality of the remove button it removes the tableView rows fine and how it is supposed to. But when i initialize a second interface (still using the same FXML and henceforth same variable names) it only lets me delete items in the 2nd tableView and not in the first. I have a good idea as to why this is, but i do not know how to fix it.
Here are a few methods i have tried:
public void removeProject(ActionEvent event){
int index = projectTable.getSelectionModel().getSelectedIndex();
if(index >=0){
projectTable.getItems().remove(index);
}else
//Show warning
}
}
Another different approach:
public void removeProject(ActionEvent event){
ObservableList<Project> currentlySelected, allProjects;
currentlySelected = projectTable.getSelectionModel().getSelectedIndex();
allProjects = projectTable.getItems();
currentlySelected.forEach(allProjects::remove);
}
Also please keep in mind that both of these methods work fine until i initialize a second tableView. After this point the value i get from both my ObservableList<Project> currentlySelected and my int Indexare -1 when i am trying to select a row in a table which isn't the most recent initialization of the interface. Sorry if it sounds a bit confusing but it is a bit confusing, if i can clear anything up ill add an edit later
Cheers
Edit 1:
Here is an example where i am trying to remove from the table based on which interface it is in currently:
ObservableList<Project> itemsSelected;
switch(counter){
case 1:
itemsSelected = projectTable.getSelectionModel().getSelectedItems();
itemsSelected.forEach(projTableStorage.getProj1()::remove);
break;
case 2:
itemsSelected = projectTable.getSelectionModel().getSelectedItems();
itemsSelected.forEach(projectTableStorage.getProj2()::remove);
break;
A few things to note:
The projectTableStorage.getProj() is used to store all of the data in each table, the returned value is an ObservableList and i use this to set the items of the table whenever that interface is loaded so the data is not lost when swapping between interfaces, perhaps there is more efficient ways to go about it, this is just how i did it
There are 7 of these interfaces, i am just testing with 2 to make testing shorter and simpler for now at least
Edit 2:
Loading FXML files:
public AnchorPane initLayouts(FXMLLoader loader, AnchorPane projectLayout, MainLayoutController mainLay) throws IOException{
loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/control/view/ProjectLayout.fxml"));
loader.setController(mainLay);
projectLayout = (AnchorPane) loader.load();
return projectLayout;
}
in MainLayoutController:
public AnchorPane loadLayout(AnchorPane projectLayout, Project project, FXMLLoader loader)throws IOException{
projectLayout = project.initLayouts(loader, projectLayout, this);
return projectLayout;
}
load layout is called whenever a button is pressed
Edit 3:
Here is the 'removeProjec' code again
public void removeProject(ActionEvent event){
ObservableList<Project> itemsSelected, currentProject;
itemsSelected = getProjectTable().getSelectionModel().getSelectedItems();
itemsSelected.forEach(getProjectTable().getItems()::remove);
System.out.println("value of itemsSelected is : " + itemsSelected);
}
and my project table storage:
ObservableList<Project> project1= FXCollections.observableArrayList();
ObservableList<Project> project2 = FXCollections.observableArrayList();
public void setProject1(Project project){
project1.add(project);
}
public void setProject2(Project project){
project2.add(project);
}
public ObservableList<Project> getProject1(){
return project1;
}
public ObservableList<Project> getProject2(){
return project2;
}
And also just in case the getProjectTable method(Tried with and without annotation):
#FXML
public TableView<Project> getProjectTable(){
return projectTable;
}
Edit 4:
public void createNewProjectLayout(ActionEvent event) throws IOException{
if(event.getTarget() == newProjectLayoutButton1){
projectLayout1 = loadOrReloadProjectLayout(newProjectLayoutButton1, project1, projectLayout1, 1);
setTable(Counter);
}else if(event.getTarget() == newProjectLayoutButton2){
projectLayout2 = loadOrReloadProjectLayout(newProjectLayoutButton2, project2, projectLayout2, 2);
setTable(Counter);
}
A few things to note:
The loadOrReload is simply to load the file the first time it is clicked using the loadLayout method previously mentioned, and then reload the result of loadLayout for the next time it is pressed
The setTable is used to set any data stored previously in the table to be put in the table again using the observable lists from the ProjectTableStorage class

Wicket - updating ListView using AJAX and Wicket Model

I have a :
Client Class
ListView
TextField
I need to populate my ListView in order to form a table:
WORKING CODE:
clientModel = new LoadableDetachableModel() {
#Override
protected Object load() {
return Client.getClientListByCompanyName(searchClientInput.getValue());
}
};
searchClientInput.setModel(new Model<String>());
searchClientInput.add(new AjaxFormComponentUpdatingBehavior("onkeyup") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(clientListViewContainer);
}
});
clientListView = new ListView<Client>(CLIENT_ROW_LIST_ID, clientModel) {
#Override
protected void populateItem(ListItem<Client> item) {
Client client = item.getModelObject();
item.add(new Label(CLIENT_ROW_COMPANY_CNPJ_ID, client.getCompanyName()));
item.add(new Label(CLIENT_ROW_COMPANY_NAME_ID, client.getCompanyCnpj()));
}
};
clientListViewContainer.setOutputMarkupId(true);
clientListViewContainer.add(clientListView);
add(clientListViewContainer);
Now, in my HTML, I have a TextField. Whenever an user types something in this TextField, a select will be made in the database with whatever he typed. So for each word, a select is made, and the table needs to be updated. I am guessing I will need to use AJAX and possibly a Model. I'm kind of lost about how I can do this, if someone can provide me examples I would be very grateful.
EDIT: New code that is throwing exception: Last cause: Attempt to set model object on null model of component: searchClientForm:searchClientInput
EDIT 2: Ok so the exception was that my TextField didn't had a model to bind data to. So what I did was: searchClientInput.setModel(new Model<String>());
I also had a problem with the event. Using onkeydown was working, but not as intended. I had Company Name 1-4. If I typed Company Name 1, I would need to press one key again so the table would get updated. With onkeyup this don't happens. Thanks for the help.
You could give the ListView a LoadableDetachableModel which provides the selected clients matching your TextField's value.
Use an AjaxFormComponentUpdatingBehavior on your TextField which add a parent of the ListView to the request target (don't forget #setOutputMarkupId().
I believe the best way to perform what you want (which is repainting a table/list at each input change --> DB access) is with a DataView and a DataProvider.
A DataView is just like the ListView component except it uses an IDataProvider to get the data you want to present. You are able to implement the DataProvider so it accesses your DB, and you can add restrictions (where clauses) to the DataProvider.
[this is more like pseudo-code]
public final class MyDataProvider<T> extends SortableDataProvider<T> {
// ...
Set filters;
// filters is the set where the restrictions you want to apply are stored
...
#Override
public Iterator<T> iterator(int first, int count) {
// DAO (Data Access Object) access to DB
// ...
return dao.findByRestrictions(filters).iterator();
}
...
}
Now on the ajax event on your input component you are able to update the filter being used in the DataProvider, and in the the next repaint of the DataView, the provider will "pull" the data matching the restrictions defined in the filter.
Hope it helps. Best regards.

Serialize JavaFX components

I'm trying to develop a little drag & drop application under Java FX. User will drop JFX components like Buttons, Menus, Labels on certain positions. When done, he will save this layout and later on he will reopen the layout and he will use it again.
Its important to store the information about all objects that are dropped on some position.
I decided to use serialization for this purpose. But I'm not able to serialize JavaFX components. I tried to serialize Buttons, Scenes, Stages, JFXPane but nothing seemed to work (I obtained NotSerializableException).
Any suggestions how to save all the components and then retrieve them ?
P.S.: I was trying to find out some method with FXML but I did not succeed.
Thank you very much for your answers :)
You are correct, JavaFX (as of 2.1) does not support serialization of components using the Java Serializable interface - so you cannot use that mechanism.
JavaFX can deserialize from an FXML document using the FXMLLoader.load() method.
The trick though, is how to write your existing components and states out to FXML?
Currently, there is nothing public from the platform which performs FXML serialization. Apparently, creating a generic scenegraph => FXML serializer is quite a complex task (and there is no public 3rd party API for this that I know of). It wouldn't be too difficult to iterate over the scenegraph and write out FXML for a limited set of components and attributes.
If the main goal of saving user components on the servers side - is to have a possibility to show the same interface to the user - why not to save all descriptive information you need about users components, and when it is needed - just rebuild user interface again, using stored descriptive information? Here is primitive example:
/* That is the class for storing information, which you need from your components*/
public class DropedComponentsCoordinates implements Serializable{
private String componentID;
private String x_coord;
private String y_coord;
//and so on, whatever you need to get from yor serializable objects;
//getters and setters are assumed but not typed here.
}
/* I assume a variant with using FXML. If you don't - the main idea does not change*/
public class YourController implements Initializable {
List<DropedComponentsCoordinates> dropedComponentsCoordinates;
#Override
public void initialize(URL url, ResourceBundle rb) {
dropedComponentsCoordinates = new ArrayList();
}
//This function will be fired, every time
//a user has dropped a component on the place he/she wants
public void OnDropFired(ActionEvent event) {
try {
//getting the info we need from components
String componentID = getComponentID(event);
String component_xCoord = getComponent_xCoord(event);
String component_yCoord = getComponent_yCoord(event);
//putting this info to the list
DropedComponentsCoordinates dcc = new DropedComponentsCoordinates();
dcc.setX_Coord(component_xCoord);
dcc.setY_Coord(component_yCoord);
dcc.setComponentID(componentID);
} catch (Exception e) {
e.printStackTrace();
}
}
private String getComponentID(ActionEvent event){
String componentID;
/*getting cpmponentID*/
return componentID;
}
private String getComponent_xCoord(ActionEvent event){
String component_xCoord;
/*getting component_xCoord*/
return component_xCoord;
}
private String getComponent_yCoord(ActionEvent event){
String component_yCoord;
/*getting component_yCoord*/
return component_yCoord;
}
}

Categories