I am making a program that returns the output in a long string variable. The data in the string is constantly changing based on what the user enters in the GUI. My question is, how do I take this and store it inside of my linked list? I have looked at a few examples, but the class I was provided with for my class is a little different, and I haven't been able to find something to specifically fix my problem.
Controller Code:
public class RentGameDialogController extends RentalStoreGUIController implements Initializable{
/** TextField Objects **/
#FXML private TextField nameField, rentedOnField, dueBackField;
/** String for NameField **/
String name, rentedOn, dueBack;
/** Game ComboBox ID's **/
#FXML private ObservableList<GameType> cbGameOptions;
#FXML private ComboBox<GameType> cbGame;
/** Console ComboBox ID's **/
#FXML private ObservableList<PlayerType> cbConsoleOptions;
#FXML private ComboBox<PlayerType> cbConsole;
/** GameType object **/
private GameType game;
/** PlayerType Object **/
private PlayerType console;
/** Button ID's **/
#FXML Button cancel, addToCart;
/** Counter for calculating total **/
int gameCounter;
/** Stage for closing GUI **/
private Stage currentStage;
private MyLinkedList list = new MyLinkedList();
#Override
public void initialize(URL location, ResourceBundle resources) {
/** Select Console **/
cbConsoleOptions = FXCollections.observableArrayList();
for (PlayerType p : PlayerType.values()) { cbConsoleOptions.addAll(p); }
cbConsole.getItems().addAll(cbConsoleOptions);
/** Select Game **/
cbGameOptions = FXCollections.observableArrayList();
for (GameType g : GameType.values()){ cbGameOptions.addAll(g); }
cbGame.getItems().addAll(cbGameOptions);
}
public String getName(){
name = nameField.getText();
try {
String[] firstLast = name.split(" ");
String firstName = firstLast[0];
String lastName = firstLast[1];
} catch (Exception e){
e.printStackTrace();
}
return name;
}
public String getGame() {
return cbGame.getSelectionModel().getSelectedItem().toString();
}
public String getConsole() {
return cbConsole.getSelectionModel().getSelectedItem().toString();
}
public String getRentedOn() throws ParseException {
rentedOn = rentedOnField.getText();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date rentedOnDate = format.parse(rentedOn);
Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(rentedOnDate);
try {
cal.getTime();
} catch (Exception e) {
rentedOnField.setText("ERROR");
}
return rentedOn;
}
public String getDueBack() throws ParseException {
dueBack = dueBackField.getText();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date dueBackDate = format.parse(dueBack);
Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(dueBackDate);
try {
cal.getTime();
} catch (Exception e) {
dueBackField.setText("ERROR");
}
return dueBack;
}
/*************************************
* This is the method to call the other
* String methods so their output can be
* put into my main GUI
*
*
* #return
* #throws ParseException
*************************************/
public String storePurchaseData() throws ParseException {
gameCounter++;
String toList = getName() + " | " + getGame() + " | " + getConsole() + " | " +
getRentedOn() + " | " + getDueBack();
//Add 'toList' to the linked list here if possible
return toList;
}
#FXML
public void handleCancelButtonAction () {
currentStage = (Stage) cancel.getScene().getWindow();
currentStage.close();
}
#FXML
public void addToCartButton () throws ParseException {
appendTextArea(storePurchaseData());
currentStage = (Stage) cancel.getScene().getWindow();
currentStage.close();
}}
This code is for my controller. It launches a basic GUI, then I can pull the data from all of the fields I made, convert them to Strings and can then print them in one long chain of text. I would like to store the string into my linked list class.
Linked List code:
public class MyLinkedList<E> implements Serializable {
private DNode<E> top;
public int size;
public MyLinkedList() {
top = null;
size = 0;
}
}
I am very new to linked lists and I am trying to understand them, does this code make sense? Do I need to add anything to, say, save the String that I am storing into a text file?
Thank you in advance
Without getting into your game code at all, it looks like your MyLinkedList class takes a type parameter E - You haven't shown the code for DNode but it also takes the E type. If you can specify this to be a String then the nodes of MyLinkedList can be populated with Strings as you desire.
DNode<String> myFirstNode = new DNode<>(null, null, "nodeData");
MyLinkedList<String> list = new MyLinkedList<>(myFirstNode);
This assumes that the MyLinkedList class also has a constructor that takes a DNode to initialize its head, and that DNode looks something like this.
Related
so when i clicking the Messages tabPane containing the Jtree, this is the preview in my java swing which seems fine.
pict 1 (loading the message)
pict 2. (done)
when i click any of the checkboxes in the JTree it should be either loading(checking) or unloading(unchecking) the messages in the message list with the swingworker running to see the progress. But what happen is after i click the checkboxes (of any condition), yes the swingworker running and giving the loading/unloading progress, but after that, i get this:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException:
Cannot invoke "model.Message.getContents()" because "message" is null
and make the message lists is unclickable, which were clickable before i attempted to click the checkboxes in the JTree.
at the moment i dont need JTree in my purpose for learning swing, so I'm not really taking into account about this JTree lesson, but i need this to be fixed so i can keep go along with the tutorial. that's why i'm not quite sure which code are problematic and needed to put in this thread. So i'm very sorry if my question is not clear. if there still anything i have to put at this thread, please ask me i'll be happy to put it here.
this the class that mentioned in exception
public class MessagePanel extends JPanel implements ProgressDialogListener{
public MessagePanel(JFrame parent) {
messageListModel = new DefaultListModel();
messageList = new JList(messageListModel);
messageList.setCellRenderer(new MessageListRenderer());
messageList.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Message message = (Message)messageList.getSelectedValue();
textPanel.setText(message.getContents());
}
});
}
this is the class and method that related with the above class
public class MessageListRenderer implements ListCellRenderer {
private JPanel panel;
private JLabel label;
private Color selectedColor,normalColor;
public MessageListRenderer() {
//some ui settings
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Message message = (Message)value;
label.setText(message.getTitle());
panel.setBackground(cellHasFocus ? selectedColor: normalColor);
return panel;
}
}
===================
public class TextPanel extends JPanel{
public void setText(String text) {
textArea.setText(text);
}
}
===================
public class Message {
private String title,contents;
public Message(String title, String contents) {
super();
this.title = title;
this.contents = contents;
}
public String getTitle() {return title;}
public void setTitle(String title) {this.title = title;}
public String getContents() {return contents;}
public void setContents(String contents) {this.contents = contents;}
}
Your Message class constructor requires two parameters (of: String, String) in order to create an instance of Message. I have no clue what you are currently using to create you Message instances nor do I know what is storing those instances. You do need to keep track of them otherwise you will loose them to JVM Garbage Collection.
I think perhaps you may want to modify your Message Class a little so that you can internally (or externally) store your Message instances and easily access any one of those instances when required, for example:
public class Message {
// A List Interface object to hold Message instances.
private static java.util.List<Message> messageInstances = new java.util.ArrayList<>();
// The OS System's New-Line character to use for console writing.
private final static String ls = System.lineSeparator();
// Instance member variables
private String title;
private String contents;
/**
* Constructor #1
* Does Nothing but adds the instance to the messageInstances List!
* Relies on Setters to fill instance member variables.
*/
public Message() {
messageInstances.add((this));
}
/**
* Constructor #2
* Contains parameters of which the arguments will fill instance member
* variables listed within the Parameters list below.
*
* #param title (String) The Message Title.<br>
*
* #param contents (String) The message content related to the above title.
*/
public Message(String title, String contents) {
super();
this.title = title;
this.contents = contents;
messageInstances.add((this));
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public static java.util.List<Message> getMessageInstances() {
return messageInstances;
}
/**
* Removes one (or more) Message instances from the messageInstances List.
* This method must be supplied at least one integer index value of the
* Message instance to remove otherwise a Warning is displayed within the
* console window. Several index values can be supplied providing they are
* delimited with a comma or all desired Message Instance index values to
* remove are supplied within a Single Dimensional int[] Array.<br><br>
*
* <b>Valid uses of this class method:</b><pre>
*
* removeMessageInstance(0, 4, 2, 16);
*
* OR
*
* int[] indexes = {0, 4, 2, 16};
* removeMessageInstance(indexes);</pre>
*
* #param instanceIndexes
*/
public static void removeMessageInstance(int... instanceIndexes) {
int[] iIndex = null;
if (instanceIndexes.length == 0) {
System.err.println("Message.removeMessageInstance() method Warning!" + ls
+ "Require an index value of the Message Instance to remove!" + ls
+ "Ignoring Removal call!" );
return;
}
iIndex = new int[instanceIndexes.length];
System.arraycopy(instanceIndexes, 0, iIndex, 0, instanceIndexes.length);
for (int i = 0; i < iIndex.length; i++) {
if(iIndex[i] < 0 || iIndex[i] > messageInstances.size()) {
System.err.println("Message.removeMessageInstance() method Warning!" + ls
+ "The supplied Message Instance index value (" + iIndex[i] + ") is invalid!" + ls
+ "Ignoring Removal call for Message Instance at Index " + iIndex[i] + "!");
continue;
}
messageInstances.remove(iIndex[i]);
}
}
#Override
public String toString() {
return new StringBuilder("").append(title).append(" | ")
.append(contents).toString();
}
}
Do whatever it is you do to create Message instances.
Now, in your MessagePanel class within the ListSelectionListener:
public void valueChanged(ListSelectionEvent e) {
String title = messageList.getSelectedValue().toString(); // toString() may not be required.
List<Message> messages = Message.getMessageInstances();
for (Message msg : messages) {
if (msg.getTitle().equalsIgnoreCase(title)) {
textPanel.setText(msg.getContents());
break;
}
}
}
I have this method in my application which is constructing RadioButtons using an helper class: Mode. I would like to call out of the createModesRadios method .getText() for the user's selected RadioButton. Also I would like to save the user's choices in order to remember them in a following use. Is there an easy way to call them and set the choices into the CheckBoxes, into the RadioButtons and into the PrefixSelectionComboBoxs?
I am using a Model Class Configuration.java in order to store the information, because I will need to process some calculations with the user inputs. I would like to store in it also the choices made from the controllers mentioned above.
Part of my Class
public class ConfigurationEditDialogController {
// General Tab
#FXML
private TextField configurationNameField;
#FXML
private TextField commentField;
#FXML
private TextField creationTimeField;
#FXML
private TextField startAddress;
#FXML
private ToggleSwitch triggerEnable;
#FXML
private ToggleSwitch softwareTrigger;
#FXML
private ToggleSwitch ctsEnable;
// Data Acquisition Tab
#FXML
private Pane dataAcquisitionTab;
#FXML
private Button okButton;
private Mode[] modes = new Mode[]{
new Mode("Vertical", 4),
new Mode("Hybrid", 2),
new Mode("Horizontal", 1)
};
private int count = Stream.of(modes).mapToInt(Mode::getCount).max().orElse(0);
private ToggleGroup group = new ToggleGroup();
private IntegerProperty elementCount = new SimpleIntegerProperty();
private ObservableMap<Integer, String> elements = FXCollections.observableHashMap();
CheckBox[] checkBoxes = new CheckBox[count];
private ObservableList<String> options = FXCollections.observableArrayList(
"ciao",
"hello",
"halo");
private Stage dialogStage;
private Configuration configuration;
private boolean okClicked = false;
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
#FXML
private void initialize() {
HBox radioBox = createModesRadios(elementCount, modes);
GridPane grid = new GridPane();
VBox root = new VBox(20, radioBox);
root.setPrefSize(680, 377);
grid.setHgap(40);
grid.setVgap(30);
grid.setAlignment(Pos.CENTER);
elementCount.addListener((o, oldValue, newValue) -> {
// uncheck checkboxes, if too many are checked
updateCheckBoxes(checkBoxes, newValue.intValue(), -1);
});
for (int i = 0; i < count; i++) {
final Integer index = i;
CheckBox checkBox = new CheckBox();
checkBoxes[i] = checkBox;
PrefixSelectionComboBox<String> comboBox = new PrefixSelectionComboBox<>();
comboBox.setItems(options);
comboBox.setPromptText("Select Test Bus " + i);
comboBox.setPrefWidth(400);
comboBox.setVisibleRowCount(options.size() -1);
comboBox.valueProperty().addListener((o, oldValue, newValue) -> {
// modify value in map on value change
elements.put(index, newValue);
});
comboBox.setDisable(true);
checkBox.selectedProperty().addListener((o, oldValue, newValue) -> {
comboBox.setDisable(!newValue);
if (newValue) {
// put the current element in the map
elements.put(index, comboBox.getValue());
// uncheck checkboxes that exceed the required count keeping the current one unmodified
updateCheckBoxes(checkBoxes, elementCount.get(), index);
} else {
elements.remove(index);
}
});
grid.addRow(i, comboBox, checkBox);
}
// enable Ok button iff the number of elements is correct
okButton.disableProperty().bind(elementCount.isNotEqualTo(Bindings.size(elements)));
root.getChildren().add(grid);
dataAcquisitionTab.getChildren().add(root);
}
/**
* Create Radio Buttons with Mode class helper
*
* #param count
* #param modes
* #return
*/
private HBox createModesRadios(IntegerProperty count, Mode... modes) {
ToggleGroup group = new ToggleGroup();
HBox result = new HBox(50);
result.setPadding(new Insets(20, 0, 0, 0));
result.setAlignment(Pos.CENTER);
for (Mode mode : modes) {
RadioButton radio = new RadioButton(mode.getText());
radio.setToggleGroup(group);
radio.setUserData(mode);
result.getChildren().add(radio);
radio =
}
if (modes.length > 0) {
group.selectToggle((Toggle) result.getChildren().get(0));
count.bind(Bindings.createIntegerBinding(() -> ((Mode) group.getSelectedToggle().getUserData()).getCount(), group.selectedToggleProperty()));
} else {
count.set(0);
}
return result;
}
/**
* Method for updating CheckBoxes depending on the selected modek
*
* #param checkBoxes
* #param requiredCount
* #param unmodifiedIndex
*/
private static void updateCheckBoxes(CheckBox[] checkBoxes, int requiredCount, int unmodifiedIndex) {
if (unmodifiedIndex >= 0 && checkBoxes[unmodifiedIndex].isSelected()) {
requiredCount--;
}
int i;
for (i = 0; i < checkBoxes.length && requiredCount > 0; i++) {
if (i != unmodifiedIndex && checkBoxes[i].isSelected()) {
requiredCount--;
}
}
for (; i < checkBoxes.length; i++) {
if (i != unmodifiedIndex) {
checkBoxes[i].setSelected(false);
}
}
}
/**
* Sets the stage of this dialog.
*
* #param dialogStage
*/
public void setDialogStage(Stage dialogStage) {
this.dialogStage = dialogStage;
}
/**
* Sets the configuration to be edited in the dialog.
*
* #param configuration
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
configurationNameField.setText(configuration.getConfigurationName());
commentField.setText(configuration.getComment());
//Set the comboboxes and the checkboxes and the radiobutton
creationTimeField.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm")));
}
/**
* Returns true if the user clicked OK, false otherwise.
*
* #return
*/
public boolean isOkClicked() {
return okClicked;
}
/**
* Called when the user clicks ok.
*/
#FXML
private void handleOk() {
if (isInputValid()) {
configuration.setConfigurationName(configurationNameField.getText());
configuration.setComment(commentField.getText());
configuration.setTestBus1(elements.get(0));
configuration.setTestBus2(elements.get(1));
configuration.setTestBus3(elements.get(2));
configuration.setTestBus4(elements.get(3));
configuration.setCreationTime(DateTimeUtil.parse(creationTimeField.getText()));
// Store the information of the sample mode (vertical, hybrid or horizontal).
okClicked = true;
dialogStage.close();
}
}
Mode Helper Class
public class Mode {
private final String text;
private final int count;
public Mode(String text, int count) {
this.text = text;
this.count = count;
}
public String getText() {
return text;
}
public int getCount() {
return count;
}
}
Configuration.java
public class Configuration {
private final StringProperty configurationName;
private final StringProperty comment;
private final StringProperty testBus1;
private final StringProperty testBus2;
private final StringProperty testBus3;
private final StringProperty testBus4;
private final StringProperty triggerSource;
private final StringProperty sampleMode;
private final StringProperty icDesign;
private final StringProperty triggerMode;
private final DoubleProperty acquisitionTime;
private final ObjectProperty<LocalDateTime> creationTime;
/**
* Default constructor.
*/
public Configuration() {
this(null, null);
}
/**
* Constructor with some initial data.
*
* #param configurationName
* #param comment
*/
public Configuration(String configurationName, String comment) { //todo initialize null values
this.configurationName = new SimpleStringProperty(configurationName);
this.comment = new SimpleStringProperty(comment);
// Some initial sample data, just for testing.
this.testBus1 = new SimpleStringProperty("");
this.testBus2 = new SimpleStringProperty("");
this.testBus3 = new SimpleStringProperty("");
this.testBus4 = new SimpleStringProperty("");
this.triggerSource = new SimpleStringProperty("");
this.sampleMode = new SimpleStringProperty("");
this.icDesign = new SimpleStringProperty("Ceres");
this.triggerMode = new SimpleStringProperty("Internal");
this.acquisitionTime = new SimpleDoubleProperty(2346.45);
this.creationTime = new SimpleObjectProperty<>(LocalDateTime.of(2010, 10, 20,
15, 12));
}
/**
* Getters and Setters for the variables of the model class. '-Property' methods for the lambdas
* expressions to populate the table's columns (just a few used at the moment, but everything
* was created with scalability in mind, so more table columns can be added easily)
*/
// If more details in the table are needed just add a column in
// the ConfigurationOverview.fxml and use these methods.
// Configuration Name
public String getConfigurationName() {
return configurationName.get();
}
public void setConfigurationName(String configurationName) {
this.configurationName.set(configurationName);
}
public StringProperty configurationNameProperty() {
return configurationName;
}
// Comment
public String getComment() {
return comment.get();
}
public void setComment (String comment) {
this.comment.set(comment);
}
public StringProperty commentProperty() {
return comment;
}
// Test Bus 1
public String getTestBus1() {
return testBus1.get();
}
public void setTestBus1(String testBus1) {
this.testBus1.set(testBus1);
}
public StringProperty testBus1Property() {
return testBus1;
}
// Test Bus 2
public String getTestBus2() {
return testBus2.get();
}
public void setTestBus2(String testBus2) {
this.testBus2.set(testBus2);
}
public StringProperty testBus2Property() {
return testBus2;
}
// Test Bus 3
public String getTestBus3() {
return testBus3.get();
}
public void setTestBus3(String testBus3) {
this.testBus3.set(testBus3);
}
public StringProperty testBus3Property() {
return testBus3;
}
// Test Bus 4
public String getTestBus4() {
return testBus4.get();
}
public void setTestBus4(String testBus4) {
this.testBus4.set(testBus4);
}
public StringProperty testBus4Property() {
return testBus4;
}
// Trigger Source
public String getTriggerSource(){
return triggerSource.get();
}
public void setTriggerSource (String triggerSource){
this.triggerSource.set(triggerSource);
}
public StringProperty triggerSourceProperty() {
return triggerSource;
}
// Sample Mode
public String getSampleMode() {
return sampleMode.get();
}
public void setSampleMode (String sampleMode){
this.sampleMode.set(sampleMode);
}
public StringProperty sampleModeProperty() {return sampleMode;}
// IC Design
public String getIcDesign() {
return icDesign.get();
}
public void setIcDesign (String icDesign){
this.icDesign.set(icDesign);
}
public StringProperty icDesignProperty() {
return icDesign;
}
// Trigger Mode
public String getTriggerMode() {
return triggerMode.get();
}
public void setTriggerMode (String triggerMode){
this.triggerMode.set(triggerMode);
}
public StringProperty triggerModeProperty() {return triggerMode;}
// Acquisition Time
public double getAcquisitionTime() {
return acquisitionTime.get();
}
public void setAcquisitionTime(double acquisitionTime){
this.acquisitionTime.set(acquisitionTime);
}
public DoubleProperty acquisitionTimeProperty() {
return acquisitionTime;
}
// Last modified - Creation Time
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
public LocalDateTime getCreationTime() {
return creationTime.get();
}
public void setCreationTime(LocalDateTime creationTime){
this.creationTime.set(creationTime);
}
public ObjectProperty<LocalDateTime> creationTimeProperty() {
return creationTime;
}
}
You can use the java.util.Properties class to easily read/write settings like this to/from an XML file.
Save To Properties
Properties props = new Properties();
// Set the properties to be saved
props.setProperty("triggerMode", triggerMode.get());
props.setProperty("acquisitionTime", String.valueOf(acquisitionTime.get()));
// Write the file
try {
File configFile = new File("config.xml");
FileOutputStream out = new FileOutputStream(configFile);
props.storeToXML(out,"Configuration");
} catch (IOException e) {
e.printStackTrace();
}
This creates the config.xml file and populates it with all the properties you set using the props.setProperty() method.
Within the props.setProperty() method, you have two parameters. The first is the name of the property, the second is the actual value. The name is important as you will use it to read the appropriate value later.
The above code outputs the following XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Configuration</comment>
<entry key="acquisitionTime">12.0</entry>
<entry key="triggerMode">My Trigger Mode</entry>
</properties>
Read from Properties
Reading from the XML file is just as simple. Use the loadFromXML() method:
FileInputStream in;
// Load the settings file
in = new FileInputStream(DataFiles.LOCAL_SETTINGS_FILE);
properties.loadFromXML(in);
From there, you can set your Configuration model object by getting each property:
configuration.setAcquisitionTime(props.getProperty("acquisitionTime", "0.0"));
configuration.setTriggerMode(props.getProperty("triggerMode", "Manual"));
The getProperty() method also takes two parameters. The first is obviously the name of the property we saved earlier. The second is the default value to use if the requested property name does not exist in the XML file.
Pretty simple!
I do recommend updating all the values in your Configuration.java model and saving properties from there (instead of trying to save the properties directly from your textfields, comboboxes, etc).
EDIT
In order to retrieve the values from your controls within the for loop, you need to add them to a list that is accessible from outside that loop.
Create appropriate lists to hold the controls as their created:
List<PrefixSelectionComboBox<String>> comboBoxes = new ArrayList<PrefixSelectionComboBox<String>>();
List<CheckBox> checkBoxes = new ArrayList<>();
At the bottom of your loop, add the new controls to these lists:
comboBoxes.add(comboBox);
checkBoxes.add(checkBox);
grid.addRow(i, comboBox, checkBox);
Now, when you need their values, you can iterate over those lists to extract them:
for (PrefixSelectionComboBox cb : comboBoxes) {
cb.getValue(); // Do with this what you must
}
for (CheckBox cb : checkBoxes) {
cb.isSelected();
}
So I have this class "Member" :
package pkgData;
import java.io.Serializable;
public class Member implements Comparable<Member>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String city;
public Member(String nameOfMember,String location) {
super();
this.name = nameOfMember;
this.city=location;
}
public String getNameOfMember() {
return name;
}
public String getLocationOfMember() {
return city;
}
public void setNameOfMember(String nameOfMember) {
this.name = nameOfMember;
}
#Override
public String toString() {
return name +", " + city;
}
#Override
public int compareTo(Member o) {
int result =this.getNameOfMember().compareTo(o.getNameOfMember());
if(result==0){
result = this.getLocationOfMember().compareTo(o.getLocationOfMember());
}
return result;
}
}
And I have a JComboBox which is EDITABLE and the model of the ComboBox is DefaultComboBoxModel.
So the problem is that if I cast the selectedItem:
Member nameOfMember = (Member)memberModel.getSelectedItem();
if(nameOfMember== null)
throw new Exception("please select a name and a location");
It only checks if the entered string is empty. If I enter a string like "Name, Location" I always get the exception that String cannot be cast to Member. Which String to I have to enter that the String can be cast to Member?
Here is my JComboBox:
private JComboBox<Member> getComboBoxMember() {
if (comboBoxMember == null) {
comboBoxMember = new JComboBox<Member>();
comboBoxMember.setEditable(true);
comboBoxMember.setModel(memberModel);
}
return comboBoxMember;
}
and here the global variables:
private DefaultComboBoxModel<Member> memberModel;
private JComboBox<Member> comboBoxMember;
String nameOfMember = (String) memberModel
.getSelectedItem();if(nameOfMember==null)throw new Exception("please select a name and a location");else
{
String[] parts = nameOfMember.split(",");
String part1 = parts[0]; // name
String part2 = parts[1]; // location
Member member=new Member(part1, part2);
}
String split & cast method
What you can do is first of all test if the string you get is null, or if it matches well you format. Then, you can create a new object with these elements.
Here's a small example code :
String memberData = (String)memberModel.getSelectedItem();
if(memberData == null || memberData.split(", ")[0].isEmpty() || memberData.split(", ")[1].isEmpty()) {
throw new Exception("Data is incorrect, please provide name and location separated with ", ");
}
Member member = new Member(memberData.split(", ")[0], memberData.split(", ")[1]);
JComboBox method
With Java 7 happened a new possibility of extension to JComboBox, which can now be generically parameterized (as for ArrayLists) in the form JComboBox<Type>. Thus, the objects you can get with getSelectedItem() can now be casted to the generic type you gave in parameter to JComboBox. The only problem is that, when a JComboBox is edited, as in your case, the data is casted to a simple String.
What you can do in your listener method (I will use ActionListener) is the following :
class ItemAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
try {
//In case the user has not modified the object
Member member = (Member)box.getSelectedItem();
//Just an example here
if(member != null) {
System.out.println(member.toString());
}
} catch(ClassCastException ex) {
//In case the object has been modified
String data = (String)box.getSelectedItem();
//Apply first method here
}
}
}
But the problem with this method is that you end up using the first method still.
I'm trying to fill a listview with the artist and title of songs using the open() method.
To achieve this I created the artist and title ArrayLists and merged them using the create() method.
The problem is, when I try to run create() inside open() nothing happens. However, if I assign the create() method to a different button and click it after using the filechooser everything works fine.
So, I would like to know if it is possible to run the create() method after the open() method using only one button via fxml or regular java code.
public class PLController implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
list.setItems(visibleList);
}
List<File> filelist = new ArrayList<File>();
ArrayList<String> title = new ArrayList<String>();
ArrayList<String> artist = new ArrayList<String>();
ObservableList<String> visibleList = FXCollections.observableArrayList();
#FXML
ListView<String> list;
#FXML
Button impButton;
public void create(){
for(int i = 0; i < title.size(); i++){
visibleList.add(artist.get(i) +" - " +title.get(i));
Collections.sort(visibleList);
}
}
public void handleMetadata(String key, Object value){
if (key.equals("title")){
title.add(value.toString());
}
if (key.equals("artist")){
artist.add(value.toString());
}
}
public void open(){
FileChooser chooser = new FileChooser();
filelist = chooser.showOpenMultipleDialog(impButton.getScene().getWindow());
for(File f:filelist){
try {
Media media = new Media(f.toURI().toURL().toString());
media.getMetadata().addListener(new MapChangeListener<String, Object>(){
#Override
public void onChanged(Change<? extends String, ? extends Object> change) {
if(change.wasAdded()) {
handleMetadata(change.getKey(), change.getValueAdded());
}
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
}
}create(); //Nothing happens
}
As others have pointed out, the Media object does not have its metadata initialized immediately. (It needs to read data from the URL and populate those metadata as it receives them.) That is why the metadata are exposed as an ObservableMap. When you reach the end of your open() method, it is highly unlikely that the metadata will have been initialized, so your create() method will not see any data at that point.
What you need to do is observe the map, and update the ListView once both the artist and title are available. The best way to do this, in my opinion, is to encapsulate the information you want into a separate class:
public class Video {
private final Media media ;
private final ReadOnlyStringWrapper artist = new ReadOnlyStringWrapper("Unknown");
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper("Title");
public Video(File file) {
try {
this.media = new Media(file.toURI().toURL().toExternalForm());
artist.bind(Bindings.createStringBinding(() -> {
Object a = media.getMetadata().get("artist");
return a == null ? "Unknown" : a.toString();
}, media.getMetadata()));
title.bind(Bindings.createStringBinding(() -> {
Object t = media.getMetadata().get("title");
return t == null ? "Unknown" : t.toString();
}, media.getMetadata()));
}
catch (Exception e) {
throw new RuntimeException("Could not create Video for "+file, e);
}
}
public ReadOnlyStringProperty titleProperty() {
return title.getReadOnlyProperty();
}
public ReadOnlyStringProperty artistProperty() {
return artist.getReadOnlyProperty();
}
public final String getTitle() {
return title.get();
}
public final String getArtist() {
return artist.get();
}
public final Media getMedia() {
return media ;
}
}
Now you can create a ListView<Video> to display the videos. Use a cell factory to display the artist and the title in the format you want. You can make sure that the observable list fires updates when either the artist or title properties change, and you can keep it sorted via a SortedList.
#FXML
private ListView<Video> list ;
private ObservableList<Video> visibleList ;
public void initialize() {
visibleList = FXCollections.observableArrayList(
// make list fire updates when artist or title change:
v -> new Observable[] {v.artistProperty(), v.titleProperty()});
list.setItems(new SortedList<>(list, Comparator.comparing(this::formatVideo)));
list.setCellFactory(lv -> new ListCell<Video>() {
#Override
public void updateItem(Video item, boolean empty) {
super.updateItem(item, empty) ;
setText(formatVideo(item));
}
});
}
#FXML
private void open() {
FileChooser chooser = new FileChooser();
List<File> fileList = chooser.showOpenMultipleDialog(impButton.getScene().getWindow());
if (fileList != null) {
fileList.stream()
.map(Video::new)
.forEach(visibleList::add);
}
}
private String formatVideo(Video v) {
if (v == null) return "" ;
return String.format("%s - %s", v.getArtist(), v.getTitle());
}
Simply creating a Media object and assigning a listener to it won't fire the code in the listener. So the title list in your code remains empty. The create() method is called, but since you are iterating over an empty list, nothing actually happens.
Use a debugger or add some logging information in such cases.
Also, you should sort the list after the for loop, not every time you add an item.
i have the following problem: I read out database items in an observable list. Now I want to display some items from the selected line in a few textfields on the right side of my tableview.
I got the observable-line-index with the following code, but I want to select an other column of the line.
AnalysemethodenTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
public void changed(ObservableValue<?> observable, Object oldvalue, Object newValue) {
index.set(analysemethodendata.indexOf(newValue));
databaseIndex = (analysemethodendata.indexOf(newValue) + 1);
System.out.println("Index:\t" + databaseIndex);
}
});
I found the following code: Click
But i don't understand this. It's something like to write a new list and place a copy of the items of the observable list in this new list.
I think, if I have the index of the line with my code, I can select the other items in the line of the observable list, too (I thought like "x,y" like an array)
If i cast it to String, the output is only machine code.
Hope I can understand the solution with your help!
EDIT: I inserted the following code:
System.out.println(analysemethodendata.get(databaseIndex).toString());
But I only get machine code in my Output:
table.analysemethoden_table#63c0d5b7
EDIT 2:
Table-Controller-Code:
package table;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleStringProperty;
public class analysemethoden_table {
private final SimpleStringProperty rAmnorm;
private final SimpleStringProperty rMethverantw;
private final SimpleFloatProperty rBestimmungsgrenze;
private final SimpleFloatProperty rNachweisgrenze;
public analysemethoden_table (String sAmnorm, String sMethoverantw, Float sBestimmungsgrenze, Float sNachweisgrenze) {
this.rAmnorm = new SimpleStringProperty(sAmnorm);
this.rMethverantw = new SimpleStringProperty(sMethoverantw);
this.rBestimmungsgrenze = new SimpleFloatProperty(sBestimmungsgrenze);
this.rNachweisgrenze = new SimpleFloatProperty(sNachweisgrenze);
}
// Getter- und Setter-Methoden
/** rAmnorm **/
public String getRAmnorm() {
return rAmnorm.get();
}
public void setRAmnorm(String set) {
rAmnorm.set(set);
}
/** rMethverantw **/
public String getRMethverantw() {
return rMethverantw.get();
}
public void setRMethverantw(String set) {
rMethverantw.set(set);
}
/** rBestimmungsgrenze **/
public Float getRBestimmungsgrenze() {
return rBestimmungsgrenze.get();
}
public void setRBestimmungsgrenze(Float set) {
rBestimmungsgrenze.set(set);
}
/** rNachweisgrenze **/
public Float getRNachweisgrenze() {
return rNachweisgrenze.get();
}
public void setRNachweisgrenze(Float set) {
rNachweisgrenze.set(set);
}
}
You need to use
analysemethodendata.get(databaseIndex).getRAmnorm();
or any other getter method in place of getRAmnorm() to get the required output.
databaseIndex -> row number