adding method to a Java gui - java

I'm trying to setup a GUI to display an array of classes, but can't figure out how to add the array to the GUI. I'm fairly new to Java, so I could use all the help possible.
Book[] bk = new Book{10]
JFrame frame = new JFrame("Bookstore");
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.NORTH);
frame.getContentPane().add(panel);
frame.setVisible(true);
class Book implements Comparable<Book> {
//rest of code }
How would I display Book in the GUI?

You're question's a bit unclear, but if you want to present the names of the books in a GUI, first you need to give each Book a name, aka a string representation. Add a name attribute to Book with a getName() method.
Then create a String array containing the names of the books. You can do that by:
String names = new String[books.length];
for(int i=0; i<names.length; i++){
names[i] = books[i].getName();
}
Then you can input all the names into a JTextArea, or possibly a JComboBox if you want users to be able to choose a book.
With a JComboBox:
JComboBox combo = new JComboBox(names);
panel.add(combo);
With a JTextArea:
JTextArea textArea = new JTextArea(10,names.length);
textArea.setEditable(false);
for(int i=0; i<names.size; i++){
textArea.append("Book " + i + "#: " + names[i] + "\n");
}
panel.add(textArea);
Hope this helps.

When you need to display the attributes of a collection or array of objects of a class, you have several options available to you including:
The simplest would be to use a JTextArea, give it a monospaced font, and display the String representation of each object, with each object on one line, and using a formatted String, such as can be obtained via String.format(...), to display the contents.
Better would be to put your collection of objects into a TableModel of some sort and then display the data in a JTable. Easiest would be to use a DefaultTableModel, but this will require that you convert the attributes of each Book object into an array or Vector of Object. More flexible would be to create your own class that extends AbstractTableModel, but this will require more work on your part to create the appropriate methods of the TableModel, and making sure to fire the correct AbstractTableModel notification methods when any of these methods change the data nucleus (usually a collection of Book object) in any significant way.
If you want to display one object's attributes at time, you could populate your GUI with several JTextFields, each one corresponding to an attribute of your Book object, and then use Next and Previous JButtons to move through your collection of Books, displaying the attributes of the selected book on button press. Say when the next button is pressed, an int index variable that is used to select a Book from the collection is incremented, and the Book corresponding to that index is selected. Then all of the attributes from that selected Book are displayed in their corresponding text field.
The details will depend on which route you go.

Related

How to add elements to an already created JList (Netbeans generated)

I am developing an application in Netbeans using Java and have been told to use the GUI creation features that Netbeans offer. Due to this I cannot edit the initComponents(); method to edit the creation of the JList and add a default list model to it.
I have tried creating a new JList but that resulted in an infinite loop. I haven't ever created controls through coding them myself, only by an IDE's GUI creation tools.
This is what I have currently:
private void formWindowActivated(java.awt.event.WindowEvent evt) {
//String to hold current patients data
String patientDetails;
//Take the arraylist from the model
ArrayList<IAccountStrategy> unapprovedPatients;
unapprovedPatients = model.getObservers();
//Create default list model to store the patients details
DefaultListModel<String> unapprovedPatientModel = new DefaultListModel<>();
IAccountStrategy xx;
//For loop to iterate through each element of unapprovedPatients
for(int i = 0; i < unapprovedPatients.size(); i++){
//get the current patients details and store them in a string variable
xx = unapprovedPatients.get(i);
patientDetails = xx.getAccountID() + xx.getUsername() + xx.getFirstname() + xx.getLastname();
//Add string variable to list model
unapprovedPatientModel.addElement(patientDetails);
}
//add list model to existing JList
listPatients.addElement(unapprovedPatientModel);
}
I would like to output all the elements from the list model into the actual JList and then let the user interact with the list itself.
Thanks in advance!
is it not possible to use the list as I want
You just wrote code to create the DefaultListModel.
So now all you need is to add:
list.setModel( unapprovedPatientModel );
so the JList can use the newly created model.
Although the problem with this code is that the code will be executed every time the window is activated.
But the point is that all you need to do is update the list using the setModel() method. How you do this in the IDE is up to you.

Dynamically create JTextAreas?

Working on a GUI in Eclipse using WindowBuilder and ran into a roadblock..
I've created a JWindow with a drop-down box intended to display a list of people from a people array. The structure of my classes are:
public class Person {
String name;
int age;
ArrayList<Goal> goals;
}
public class Goal {
String name;
int daysToComplete;
}
Within this JWindow GUI, the drop-down box lists out all of the Person instances. Once I select a person (let's say Bob) - I want to dynamically create labels and JTextAreas to list out Bob's attribute values, for example:
Name: Bob
Age: 20
Goals:
- Goal 1, complete in X days
- Goal 2, complete in Y days
and so on.. I don't want to statically add 3 labels (Name, Age, Goals) and their respective JTextAreas (Bob, 20, Goal 1/Goal 2), because the structure of Person will likely change in the future.
What is the best way to do this?
Thanks!
If I'm understanding you correctly, you can get what you want by creating anonymous instances of JLabel and JTextArea and placing them into an array list. I don't know the specifics of your environment, but hopefully, you can follow the idea:
ArrayList<JLabel> nameLabelList = new ArrayList<JLabel>();
ArrayList<JLabel> ageLabelList = new ArrayList<JLabel>();
ArrayList<Goal> goalList = new ArrayList<Goal>();
// Event handler method
public void personSelected(person)
{
nameLabelList.add(person.name);
ageLabelList.add(person.age);
// This assumes each person has a single goal. You can adapt the code
// for multiple goals easily
goalLabelList.add(person.goal);
}
Then, after the lists are created, all you have to do is loop through these array lists and spit them out into your UI:
for(int counter = 0; counter < nameLabelList.size; counter++)
{
myContainer.add(nameLabelList.get(counter));
myContainer.add(ageLabelList.get(counter));
myContainer.add(new JLabel(goalList.get(counter).toString()));
}
After adding the contents of the array lists, make sure that they show up in the UI:
myContainer.revalidate();
myContainter.repaint();
You will have to add new Panels to your Main Panel. So your Main Panel should provide a scrollable inner Panel to which you add new lines. If you have ever worked with HTML and Tables you will understand what I am talking about.
Once you got this attribute-show-panel (inner Panel), you can load as many attributes into it with a for loop as you want.
The code would technically be like for each goal in goalArray -> add new linePanel to attribute-show-panel.
whereas a linePanel yould store a label, abutton, etc and many line Panels would list vertically

using JList with Vector not printing anything

I have the following class ReviewPanel in which i have created a JList and trying to populate it with Vector passed to it. the vector already has its values filled but when i add it to JList it doesn't shows anything.
following is my class
public class ReviewPanel extends JPanel
{
private Vector bookList;
private JList jl;
private JRadioButton poor,fair,avg,good,exlnt;
private JButton jb;
public ReviewPanel(Vector bookList)
{
this.bookList = bookList;
jl = new JList<String>(this.bookList);
String tmp=null;
for(int i=0;i<bookList.size();i++){
tmp = tmp + bookList.get(i) + "\n";
System.out.println(tmp); //here it is showing the values in booklist vector
}
add(jl);
ButtonGroup bg =new ButtonGroup();
poor = new JRadioButton("1 Poor");
fair = new JRadioButton("2 Fair");
avg = new JRadioButton("3 Average");
good = new JRadioButton("4 Good");
exlnt = new JRadioButton("5 Excellent");
bg.add(poor);
bg.add(fair);
bg.add(avg);
bg.add(good);
bg.add(exlnt);
add(poor);
add(fair);
add(avg);
add(good);
add(exlnt);
jb = new JButton("Submit Review");
add(jb);
}
//more code
}
below is the pic for what it looks like. even though i have added the Jlist already. it doesn't show anything
not savvy to jlist and vectors, any help appreciated.
In the past I have had simular issues with the FlowLayout, which is the default layout for a JPanel.
It sometimes does not show one of the items added (in my case it was often the last).
You can test if the use of your layout manager is your problem by starting you function with setLayoutManager(null). This turns is off, which will place the elements on their default locations and sizes. If the JList does show this is your problem.
A very good example for your program is the Button Demo. This also shows the use of SwingUtils to make sure you create your program on the 'Event Dispatch Thread', which is required for all interaction with Swing objects.

Dynamic GUI Creation from ResultSet - Java

I'm trying to create a Java GUI dynamically by taking values from a result set and using it to generate a checklist. I've created a small demo program to demonstrate what I've done:
SQL Commands
CREATE USER 'test'#'localhost' IDENTIFIED BY 'testpw';
CREATE DATABASE combotest;
USE combotest;
CREATE TABLE combotable (
id INT(5) NOT NULL PRIMARY KEY auto_increment,
type VARCHAR(50) NOT NULL);
INSERT INTO combotable (id, type) VALUES
(default, 'Label'),
(default, 'Textfield'),
(default, 'Combo'),
(default, 'Label'),
(default, 'Textfield'),
(default, 'Combo'),
(default, 'Combo');
GRANT SELECT ON combotest.* TO 'test'#'localhost';
For your convenience if you'd like to test it yourself I've put all the SQL commands above.
Now, for my Java code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import javax.swing.*;
public class resToComboDemo implements ActionListener {
//JDBC Variables
static Connection connect = null;
static Statement statement = null;
static ResultSet res = null;
#SuppressWarnings("rawtypes")
//Other Variables
JComboBox comboBox;
JButton submit;
JFrame frame;
JLabel label;
JTextField textField;
Container pane;
public static void main(String[] args) throws SQLException {
new resToComboDemo();
}
public resToComboDemo() throws SQLException {
try {
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/combotest?"
+ "user=test&password=testpw");
statement = connect.createStatement();
//Note: in this specific case I do realize that "order by id" is not necessary. I want it there, though.
res = statement.executeQuery("SELECT * FROM combotable ORDER BY id");
createStuff(res);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error 1: "+e, "Error!", JOptionPane.ERROR_MESSAGE);
} finally {
connect.close();
}
}
#SuppressWarnings({"rawtypes", "unchecked" })
public void createStuff (ResultSet res) throws SQLException {
frame = new JFrame("Testing dynamic gui");
Dimension sD = Toolkit.getDefaultToolkit().getScreenSize();
int width = sD.width;
int height = sD.height - 45;
frame.setSize(width,height);
pane = frame.getContentPane();
pane.setLayout(new GridLayout(0, 2));
while (res.next()) {
Object[] options = { "Pass", "Fail"};
String type = res.getString("type");
JLabel label = new JLabel("<html><small>"+type+"</small></html>");
JLabel blank = new JLabel(" ");
blank.setBackground(Color.black);
blank.setOpaque(true);
if (type.equals("Label")) {
label.setBackground(Color.black);
label.setForeground(Color.white);
label.setOpaque(true);
pane.add(label);
pane.add(blank);
} else if (type.equals("Combo")) {
pane.add(label);
comboBox = new JComboBox(options);
pane.add(comboBox);
} else if (type.equals("Textfield")) {
pane.add(label);
textField = new JTextField(20);
pane.add(textField);
}
}
JLabel blank2 = new JLabel(" ");
pane.add(blank2);
submit = new JButton("Submit");
submit.addActionListener(this);
pane.add(submit);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
Now, everything works great with creating the GUI here. However, I need to be able to treat the Combobox and Textfield components as their own separate entities. Meaning, I want to be able to get user input from each different component. Right now, if I were to request information from textfield, it just gives me the information from the last textfield. This makes perfect since, because that's how java reads it. I have no problem with that.
I just can't for the life of me figure out how to get each component's input separately. Perhaps by taking the result set and adding the results to some type of array? I've attempted this multiple times in different flavors and I can't get it to come out the way I need it to. Some of you are going to request that I show you what I've tried... but honestly, it's not worth it.
And, before anybody asks: No, I will not use FlowLayout. :)
Any help is greatly appreciated!
There are probably a few ways to achieve this based on what you want to do...
If you are only performing a batch update, you could use a Map keyed to the id of the row and mapping to the Component.
This way, when you want to save the values back to the database, you would simply iterate the Maps key values, extract the Component associated with each key and then extract the value of the Component...
I might consider making a wrapper interface which has a simple getText method and wrap the component within it, making the implementation of the wrapper responsible for extracting the text, but that's just me ;)
If you want to perform updates when a individual component is updated, you would need to swap the mapping, so that the Component would the key and the id would be mapped to it.
This would mean that when some kind of event occurred that would trigger and update (ie a ActionEvent), you could extract the source from the event and look up the id in the Map based on the Component that caused the event...
Now...frankly, I would simply use a JTable and create a custom TableModel which could model all this.
This would require you to create POJO of the table, maintaining the id, type and value within a single object. This would define a basic row in the table.
The only problem is you would need to create a (reasonably) complex TableCellEditor that could take the type and return an appropriate editor for the table. Not impossible, it's just an additional complexity beyond the normal usage of a table.
This would all the information you need is available in a single object of a single row in the table.
Take a look at How to use tables for more details
Equally, you could use a similarly idea with the Map ideas above...
You could also simply create a self contained "editor" (extending from something like JPanel), which maintain information about the id and type and from which you could extract the value and simply keep a list of these....for example...
what about interrogating the Container ( pane) which contains the components
getComponents() method and loop through the sub component and check for JComobox and JTextField do the required cast and retrieve the value
Just an idea in case you are against adding the sub-components into a kind of list
You only have a reference to the last text field or combo box that you create, since you are reusing the variables that hold them. I would put them in an ArrayList, store each new text field and combbox as you create them, then you can go back and get input from all of them after you're done.
---------- (after the OP's response to the above paragraph)
No, there is no "place to refer you" -- it's your set of requirements, it would be pretty remarkable to find code that already existed that did this exact thing. Java and Swing give you the tools, you need to put things together yourself.
You don't show your "actionPerformed" routine, but let's hypothesize about it for a minute. It is called by the framework when an action is done, and it is passed an "ActionEvent" object. Looking through its methods, we find that it has "getSource()", so it will give you a reference to the component which generated the event.
Let's further think about what we have -- a set of components in the UI, and ones which can generate events are interesting to us. We want to, in this case, retrieve something from the component that generated the event.
If we have the component (from actionEvent.getSource()) and we want to do something with it, then we can, at worst do something like the following in the actionPerformed() method:
Component sourceComponent = actionEvent.getSource();
if (sourceComponent instanceof JComboBox)
{ JComboBox sourceBox = (JComboBox) sourceComponent;
// get the value from the combo box here
}
else if (sourceComponent instanceof JTextField)
{ JTextField sourceTextField = (JTextField) sourceComponent;
// get the value from the text field here
}
// or else do nothing -- our action was not one of these.
Done this way, you don't even need to keep a list of the components -- the UI is keeping a reference to all of them, and you just use that reference when the actionEvent occurs.
Now, this is not the only or even the best or the simplest way of doing this. If you wanted to extend JComboBox and JTextField with your own classes, you could have those classes both implement an interface that defined something like getValue() or getText; then you would not need the ugly instance of operator, which can usually be done away with by better design and planning.

Getting content from JTextFields created dynamically

I am learning Java with Swing and I have some problems with using JTextField. In my program I want to dynamically add a few JTextFields with some text:
while( (ln = bufFile.readLine()) != null ) {
// inIdPanel is JPanel
inIdPanel.add(new JTextField(ln));
}
And it works good. However, the content of these JTextFields can be modified by users, and later I want to call getText() from all of them. Is this possible? How can I do this?
I saw this question: Java Swing: JButton creates new JTextField(s) but this isn't enough to solve my problem (I think using arrays in my case is not a good idea but maybe I'm wrong).
The reason why you cannot call getText() is that you have not stored a reference to the JTextField when you created it. You will need to use an array or collection to store the JtextFields as you create them so you can call the method on them later. A collection will be easier than an array because you do not know how many lines you will read in so you want it to be able to grow.
List<JTextField> fields = new ArrayList<JTTextField>();
while( (ln = bufFile.readLine()) != null ) {
JTextField field = new JTextField(ln);
inIdPanel.add(field);
fields.add(field);
}
Then you can call the .getText() from all of them
for(JTextField field: fields){
System.out.println(field.getText());
}
For an easy solution, just add an ArrayList<JTextField> textFieldList and add to the code you posted:
while((ln = bufFile.readLine()) != null) {
textFieldList.add(new JTextField(ln));
inIdPanel.add(textFieldList.get(textFieldList.size()-1));
}
Then, when you want to access the text fields, you simply iterate through them, e.g.
for (JTextField jtf : textFieldList) {
/* Operate on jtf, call methods, etc */
}
You could replace the ArrayList with an array if there is a defined limit on how many text fields you could add, but the list is nice if that quantity is unknown.

Categories