What is an effective way to collect data in Java? - java

Scenario: I have a GUI with various components in which the user can choose options. I would like these options to be collected into a single place where then the user can send that information to me. What might be the most reasonable place to store the information?
EDITED:
The GUI is already made up of the parts containing the options that a user has. For example, one JComboBox gives a list of the options that one can choose. Then I got it to print as System.out.println(User choice); All the other components follow the same pattern; all the information is printed through System.out.println(); Now instead of printing this way, I was looking for a reasonable place to write these informations.

Create a class that will be used as a store.
Use an object of that class to store what the user does, say they click a button have a variable in that class that is an integer and represents how many times that button was clicked.
When the data is collected just send data from the store class to wherever you need to send it to.

Say you have a model class to represent the GUI state:
public class Model
{
private String name = "";
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
You can render this on the GUI with a JPanel, for example:
public class GuiPanel extends JPanel
{
private final Model model;
private final JTextField nameField;
public GuiPanel(Model model)
{
this.model = model;
JLabel nameLabel = new JLabel("Name");
nameField = new JTextField(50);
nameField.setText(model.getName());
add(nameLabel);
add(nameField);
}
public void init()
{
nameField.addKeyListener(new KeyListener()
{
public void keyTyped(KeyEvent e)
{
updateModel();
}
public void keyPressed(KeyEvent e)
{
updateModel();
}
public void keyReleased(KeyEvent e)
{
updateModel();
}
});
}
public void updateModel()
{
model.setName(nameField.getText());
}
}
Notice that when the GUI changes, the changes are propagated to the model object. The state of the model can be serialized using something like XStream:
public class Serializer
{
public String serialize(Model model)
{
XStream xstream = new XStream();
return xstream.toXML(model);
}
public Model deserialize(String xml)
{
XStream xstream = new XStream();
return (Model) xstream.fromXML(xml);
}
}
Now, the panel can be shown on a JFrame like:
public class Main
{
public static void main(String[] args) throws Exception
{
final JFrame frame = new JFrame("Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 100);
final Model model = new Model();
GuiPanel panel = new GuiPanel(model);
panel.init();
final Serializer serializer = new Serializer();
JButton button = new JButton("Save");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String xml = serializer.serialize(model);
// TODO: write str to disk
JOptionPane.showMessageDialog(frame, xml);
}
});
frame.add(panel, BorderLayout.CENTER);
frame.add(button, BorderLayout.SOUTH);
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
frame.setVisible(true);
}
});
}
}

options to be collected into a single place where then the user can
send that information to me
You have a lot of options, depending on what "send that information to me" looks like:
You can store information in a centralized relational database. Clients connect to it and send information to be persisted.
You can serialize that data to the file system in some format (e.g. XML, JSON, etc.) and give users a mechanism for posting the data to a listener of some kind. Or they can attach a text file to an email and send that to you, leaving the details of downloading, parsing, and storing up to you.
You say nothing about how you plan to get this data. Have you thought about that? You need to specify both ends of the transaction in order to get a meaningful, actionable answer. Perhaps you should amend your question with more details.
UPDATE
So now we have some details:
The application will write a file to disk
Users will be expected to email to the OP as an attachment
The OP will save the attachments, correlating them to user IDs, and import them into Excel for further processing.
I'd recommend using .csv as the file format. It's a simple text format you can easily import into Excel.
SMTP is the communication protocol. The listener is the email server.
How will users email to you? Will you be setting up an email account to do nothing but field these messages?

Related

JComboBox to display multiple lines of text

I'm currently writing a small tool for sending sql queries to a database and recieving the according data.
Now to my problem:
I want to allow the user to enter a new search query or select from a "latest" list, where the last few queries are saved.
For that, I planned on using an editable JComboBox, but I'm having trouble diplaying multiple lines of text in the box itself.
The reason I want to do that, is because sql queries can get quite long and since I want make the box editable and at the same time keep the frame clean.
I've found ways to display multiple lines in the dropdown menu, but nothing for the box itself.
Thank you in advance and please forgive me if I overlooked something simple ;)
Greetings
Zeus
Extended editing functionality is supplied by the ComboBoxEditor, this allows you to define the actual component which is used as the combobox's editor
Based on your requirements, you're going to need (at the very least) a JTextArea, to provide (optionally) word wrapping and multiple lines
A rough and ready example might look something like this...
public class TextAreaComboBoxEditor implements ComboBoxEditor {
private JTextArea ta = new JTextArea(4, 20);
private JScrollPane sp = new JScrollPane(ta);
public TextAreaComboBoxEditor() {
ta.setWrapStyleWord(true);
ta.setLineWrap(true);
}
#Override
public Component getEditorComponent() {
return sp;
}
#Override
public void setItem(Object anObject) {
if (anObject instanceof String) {
ta.setText((String) anObject);
} else {
ta.setText(null);
}
}
#Override
public Object getItem() {
return ta.getText();
}
#Override
public void selectAll() {
ta.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
}
#Override
public void removeActionListener(ActionListener l) {
}
}
This doesn't support ActionListener, as JTextArea uses the Enter key for it's own purposes. If you wanted to, you could use the key bindings API to add your own Action that can trigger the ActionListeners, for that, you'd need to supply a List or other means for managing them so you can call them back

Java - Linking a JTextField variable with another class variable

What I want to achieve is very simple.
I have 2 classes. "SpeedingTicket" & "SpeedingTicket GUI".
Inside my GUI I have 1 textbox name txtSpeedLimit & a button.
Inside my SpeedingTicket class I have a variable "int speedingTicket".
Inside my SpeedingTicket class I also have a get & set method for "speedingTicket".
I know how to get and set text using JTextFields, but I want to be able to:
receive input from the "txtSpeedLimit", and store that value into the "txtSpeedLimit" instance variable in the "SpeedTicket" class. I can then check for validation etc when I come to adding the vehicle speed.
Maybe this isn't the most efficient way of dealing with this program. Maybe I should scrap the instance variables in SpeedingTicket, and deal with it all in the GUI.
Any advice would be hugely appreciated.
Basically what I'm trying to do is this:
class confirmHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
String val = txtSpeedLimit.getText();
int realNum = speed.getSpeedLimit() = txtSpeedLimit; < but obviously that doesn't work, but I want the textbox link to the variable.
EDIT: If we take away the GUI, all I want my program to do is the following:
Speed Limit: 50 < enterd via textfield
Speed: 60 < entered via textfield
if the speed is blah blah (ive already coded this).. then output a result to one of my labels.
I achieved this without making a GUI and making it only console based, but instead of the user typing it via the console, I want it to be typed via textfields.
THe values that are entered into the textfields should be stored in the two variables (speed and speedlimit) that are in the SpeedingTicket class.
You can update a value in:
public class SpeedingTicket {
int speedingTicket;
public SpeedingTicket() {
speedingTicket = 500;
}
public int getSpeedingTicket() {
return speedingTicket;
}
}
by:
public class SpeedingTicketGUI extends JPanel{
SpeedingTicket st;
SpeedingTicketGUI() {
st = new SpeedingTicket();
setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField txtField = new JTextField(10);
txtField.setText(""+st.getSpeedingTicket());
add(txtField);
JButton btn = new JButton("Update");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setSpeedingTicket(txtField.getText());
}
});
add(btn);
}
private void setSpeedingTicket(String text) {
try {
int speedTicket = Integer.parseInt(text);
st.setSpeedingTicket(speedTicket);
System.out.println("Speeding ticket set to " +st.getSpeedingTicket());
} catch (NumberFormatException ex) {
System.out.println("Invalid value " +text);
ex.printStackTrace();
}
}
public static void main(String[] args){
JFrame frame = new JFrame("Speeding Ticket");
frame.setSize(400,100);
frame.add(new SpeedingTicketGUI());
frame.setVisible(true);
}
}
You don't need to store values in JText or any GUI componenets...
Use global static variables. For example:
public static int speed_limit;
You can access this variable from ANY method,class, etc.
There are multiple ways to do it.
You can detect textfield changes by using a DocumentListener or if you want (not recommended) by a KeyListener.
The Listener could be implemented directly by your gui class or by your other class. If you want more abstraction you could implement the DocumentListener by your gui class and create a method
public void addSpeedChangeListener(SpeedChangeListener scl) {
this.speedChangeListeners.add(scl);
}
Your SpeedChangeListener could be very simple:
public interface SpeedChangeListener {
public void speedChanged(int value);
}
Then your second class implements the SpeedChangeListener and calls addSpeedChangeListener(this) on your gui class. Inside the gui class, your document listener calls speedChanged(val) for every listener registered.
EDIT
You can also use the Button and call the speedChanged on every listener inside the actionPerformed method of the ActionListener.
I think it would be easier to use a JOptionDialog which pop ups when the button is clicked. That way you can easily get input and also validate the input straight away.

How does one keep track of all the components in a Java Application?

I'm more interested in understanding how it's done in the real world.
I am building an application in Javafx where it is listening to INPUT within a webpage using webview. When the user clicks an input a new Button("Input Clicked") is created and added to a GridPane, at the bottom. The user can then click the button and a dialog will appear for information, like the inputs ID, Class, Value, etc.
If a webpage has 10+ inputs, how does one keep track of all the new Button()s created? Do I write to a file? Do I create an arraylist? If so, what if the user closes the application? How do I recreate the GridPane, almost like a File->Save feature?
I've attached an image of the application. As you can see, I have clicked the google search INPUT 4 times, 4 buttons were created. Each one needs to be unique. If I close the application, it needs to recreate it.
the code is simply
mainGrid.add(new Button("Input Clicked",IncrementCol,IncrementRow);
Example
One way of keeping track of your input controls is through a pattern called "Model-View-Controller". The state of the input controls is captured in the Model, which you can persist and then restore later.
Something like this. The UI class combines the View (the JTextField and JLabel, etc.) and the Controller (ActionListener). You might want to separate these into different classes in a large enough UI. The Model class holds all the state, that the Controller shifts between the View and the Model.
This allows you to keep track of the things in the UI.
public UI extends JFrame {
private Model model;
private JTextField fn;
private JTextField ln;
private JLabel n;
public JFrame(Model model) {
this.model = model;
fn = JTextField(model.getFirstName());
ln = JTextField(model.getLastName());
n = new JLabel(model.getFullName());
JButton b = new JButton("Submit");
JButton s = new JButton("Save");
JButton r = new JButton("Restore");
b.setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
model.setFirstName(fn.getText());
model.setLastName(ln.getText());
n.setText(model.getFullName());
}
});
s.setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
model.save();
}
});
r.setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
model.load();
fn.setText(model.getFirstName());
ln.setText(model.getLastName());
n.setText(model.getFullName());
}
});
add(fn);
add(ln);
add(l);
add(b);
add(s);
add(r);
}
}
public class Model {
private firstName;
private lastName;
private fullName;
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName; update(); }
public String getLastName() { return firstName; }
public void setLastName(String firstName) { this.firstName; update(); }
public String getFullName() { return fullName; }
public void update() { this.fullName = firstName + " " + lastName }
public void save() {
try(PrintWriter w = new PrintWriter(new FileWriter("c:/temp/test.txt"))) {
w.println(firstName);
w.println(lastName);
}
}
public void load() {
try(Scanner s = new Scanner(new FileReader("c:/temp/test.txt"))) {
firstName = s.next();
lastName = s.next();
update();
}
}
}
If your Buttons/GridPane is Serializable, you could choose an also serializable list implementation (like ArrayList) and then serialize that into a file whenever the user adds a button or closes the application. Deserialization then allows for easy reconstruction of the saved state.
Create model objects, like simple JavaBean, to contain the state and data. These objects should not be JavaFC classes, just simple classes you create. You would serialize these to a file as you see fit. I wrote a lot of code for doing this for JavaFX applications and I can attest that it is possible to write to files on a web deployed JavaFX, though there were some hoops to jump.
You can store the saved objects in memory in custom domain specific Context or Manager singletons (e.g. AccountManager.getInstance() or AccountnContext.getInstance()). These singleton objects would query for the serialized objects upon startup or on request. You can have a serialization class that manages all the sterilization of objects to disk. Maybe it takes the name of the file and the object type and would either save it or retrieve it. The singletons would hold and provide access to the JavaBean objects.
EDIT: Just to add to #sh0rug0ru's answer, my answer is centered on the Model aspect of the MVC. The Model is responsible for containing the state, values, and sterilization of the domain specific objects.

JTable Row filtering by JTextField value

I enter a name on my JTextfield , But my table don't filter any thing!
My code:
public class UserPage_Admin extends JFrame {
JTable table;
UserModel model;
public UserPage_Admin() {
model = new UserModel(...);
TableRowSorter sorter = new TableRowSorter<TableModel>(model);
table = new JTable(model);
table.setRowSorter(sorter);
add(new JScrollPane(table), BorderLayout.CENTER);
add(panelForm(), BorderLayout.PAGE_START);
RowFilter<UserModel, Object> rf = null;
try {
rf = RowFilter.regexFilter(filterTF.getText(), 0);
} catch (PatternSyntaxException pse) {
return;
}
sorter.setRowFilter(rf);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(850, 600);
setVisible(true);
}
you are calling RowFilter.regexFilter(filterTF.getText(), 0); in UserPage_Admin() constructor. How it supposed to read the text from the filterTF. I think you should call it from an Action Event Listener assigned to a JButton which will be called upon submitting(clicking) the text as follows:
submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = filterText.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(RowFilter.regexFilter(text, 0));
}
}
});
If you want to use Filtering upon user key type event, add key listener to the text field you are taking input filter-string.
filterTxtFeild.addKeyListener(new KeyAdapter() {
public void keykeyReleased(KeyEvent evt) {
// on each key type event filter.
// put your filter code as submit button
}
});
However, as it is suggested in the comments below, to work with Swing Text Component, one should have used the Document.addDocumentListener(DocumentListener). A Swing text component uses a Document to represent its content. Document events occur when the content of a document changes in any way. Add the document listener as follows:
filterTxtFeild.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
// put your filter code here upon data insertion
}
#Override
public void removeUpdate(DocumentEvent e)
{
//put your filter code here upon data removal
}
#Override
public void changedUpdate(DocumentEvent e) {}
});
Edit: Why DocumentListener is preferable ?
If we want validation of input in the data source, using KeyEvent while filtering the data you’ll find it does not reflect the user’s keystroke and input events are sent to the listeners before they are processed by the data source. suppose that when we want an user name to be entered, someone input a text like "$%^&". On such invalid input, KeyEvent will still be fired even though no valid changes has been made to data source. But, DocumentListeners are notified only when a valid changes has been made to the data source. Data entry components produce events in which a validator can listen for asynchronously, one should never modify the contents of a text component from within a DocumentListener. If we do so, the program will likely deadlock.
I enter a name on my JTextfield , But my table don't filter any thing!
there are two ways, you don't mentioned expected logics
filtering on KeyTyped from DocumentListener (your code talking about ???)
from ActionListener invoked from ENTER Key
both a.m. ways added to JTextField
then there are another two very important options
filtering in whole JTables, columns and rows (your code talking about ???)
in one (quite possible in two or more, never tried) columns
everything depends of your goal
everything by using standard methods implemented in API
You simply fail to use sorter after initializing it. You should call JTable.setRowSorter().

How do I pass the values from one class to another?

I have this gui pop up panel and it got things to filled up like packets number, distance etc. Once users fill in the information, he will click ok, the gui will close and my other gui class which has calculation method should receives all data that are filled in earlier gui. How do I store that data? I know I can store in temp file but I don't want to do that. I hope you can enlighten me.
import java.awt.*;
import java.applet.Applet;
class Example extends Applet implements ActionListener
{
TextField txt = new TextField(10);
Button goButton = new Button("Go");
String data = new String ();
public void init ()
{
add(txt);
add(goButton);
goButton.addActionListener(this);
}
public void actionPerformed (ActionEvent e)
{
String cmd = e.getActionCommand();
if (cmd.equals("Go"))
{
// preserve data
data = txt.getText();
repaint();
}
}
}
You should create an intermediate class that represents the data.
After the GUI has been filled in and the submit button clicked, parse the data and fill in the fields in your class.
For example:
public class MyData {
public String Name;
public String Address;
}
Then, fire a method in your calculation method that takes this class as a parameter:
public void Calculate(MyData data) {
...
}
For more advanced handling, look into "interfaces" in Java - that's the standard way this is done.

Categories