I´m creating a program in NetBeans where the user can create their own CSV-file. I've made a GUI. When I press the button, I want a new JLabel and a new JTextField to appear underneath the existing ones, for as many times as the button is pressed. How do I do that?
I've done something similiar and I'm using a JPanel with GroupLayout to solve this problem and that's my code:
EDIT - Your question aroused my interest and I've changed my code to your needs (of course only the basic, you will have to improve it)
Global variables
private GroupLayout m_layout;
private SequentialGroup m_verticalSg;
private ArrayList<Component> m_labelList;
private ArrayList<Component> m_textFieldList;
private ParallelGroup m_horizontalPgLabels;
private ParallelGroup m_horizontalPgTextfields;
Method createLayout()
Creates the layout for your panel which should contain the label & textfield components
private void createLayout()
{
m_layout = new GroupLayout(YOUR_PANEL);
YOUR_PANEL.setLayout(m_layout);
//This SequentialGroup is used for the VerticalGroup
m_verticalSg = m_layout.createSequentialGroup();
m_verticalSg.addContainerGap();
//Two ParallelGroups are used. One for all labels and the other one for all textfields
m_horizontalPgLabels = m_layout.createParallelGroup(GroupLayout.Alignment.LEADING);
m_horizontalPgTextfields = m_layout.createParallelGroup(GroupLayout.Alignment.LEADING);
//These component lists are used for linkSize() -> Equalize components width
m_labelList = new ArrayList<>();
m_textFieldList = new ArrayList<>();
m_layout.setHorizontalGroup(m_layout.createParallelGroup()
.addGroup(m_layout.createSequentialGroup()
.addContainerGap()
.addGroup(m_horizontalPgLabels)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) //Create gap between horizontal groups
.addGroup(m_horizontalPgTextfields)
.addContainerGap()));
m_layout.setVerticalGroup(m_layout.createParallelGroup().addGroup(m_verticalSg.addContainerGap()));
}
Method addNewRow()
Call this method from your button click event
private void addNewRow()
{
if(m_layout == null)
createLayout();
Dimension dimLabel = new Dimension(100, 15);
Dimension dimTextfield = new Dimension(200, 20);
//Create a new label
JLabel lbl = new JLabel();
lbl.setText("Your text");
lbl.setIcon(null/*Your icon*/);
lbl.setSize(dimLabel);
lbl.setPreferredSize(dimLabel);
//Create a new textfield
JTextField txtField = new JTextField();
txtField.setSize(dimTextfield);
txtField.setPreferredSize(dimTextfield);
//Add components to arrays and increase index
m_labelList.add(lbl);
m_textFieldList.add(txtField);
//Create new ParallelGroup for the vertical SequentialGroup
ParallelGroup newVerticalParallelGroup = m_layout.createParallelGroup(GroupLayout.Alignment.LEADING);
newVerticalParallelGroup.addComponent(lbl);
newVerticalParallelGroup.addComponent(txtField);
m_verticalSg.addGroup(newVerticalParallelGroup);
m_verticalSg.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED);
//Add the new label to the horizontal label group
m_horizontalPgLabels.addComponent(lbl, GroupLayout.Alignment.CENTER);
//Add the new textfield to the horizontal textfield group
m_horizontalPgTextfields.addComponent(txtField);
m_layout.linkSize(SwingConstants.HORIZONTAL, m_labelList.toArray(new Component[m_labelList.size()]));
m_layout.linkSize(SwingConstants.HORIZONTAL, m_textFieldList.toArray(new Component[m_textFieldList.size()]));
}
The last step is to add an ActionListener to your button to call the method addNewRow().
jButton1.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
addNewRow();
}
});
Feel free to ask me if something is unclear.
Related
I'm trying to setup a basic GUI Library that will import a list of books and display each book as a JButton within a scroll pane. But, before getting there I'm just trying to orient the panels first and adding a test button to make sure the basics are working before moving on to the details.
I've tried moving code around to add panels in different orders to see if that was an issue but keep getting the same result. I'm completely new to this, so my understanding of it is very limited.
public class LibraryPanel extends JPanel{
private Library library;
private JPanel bookButtons, importBooks;
JScrollPane bookList;
JTextField importField;
JButton load;
public LibraryPanel() {
setPreferredSize(new Dimension(200,500));
Library library = new Library();
setLayout(new BorderLayout());
this.setBorder(BorderFactory.createTitledBorder("Library"));
// Import Books Panel
importBooks = new JPanel();
importBooks.setLayout(new BoxLayout(importBooks,BoxLayout.X_AXIS));
importBooks.setBorder(BorderFactory.createTitledBorder("Import Books"));
importField = new JTextField(15);
importBooks.add(importField);
load = new JButton("Load");
importBooks.add(load);
this.add(importBooks,BorderLayout.SOUTH);
load.addActionListener(new loadButtonListener());
// Book List buttons
JPanel bookButtons = new JPanel();
bookButtons.setLayout(new BoxLayout(bookButtons,BoxLayout.Y_AXIS));
JButton testButton = new JButton("TEST Button");
bookButtons.add(testButton);
//for(int i = 0; i<library.getBooks().size(); i++) {
// BookButton button = new BookButton(library.getBook(i));
//button.addActionListener(new BookButtonListener());
// bookButtons.add(button);
//}
// Scroll Pane
bookList = new JScrollPane();
bookList.setBorder(BorderFactory.createTitledBorder("Book List"));
bookList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
bookList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.add(bookList,BorderLayout.CENTER);
bookList.add(bookButtons);
}
private class loadButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String filename = new String(importField.getText());
library.loadLibraryFromCSV(filename);
}
}
}
However, I'm having an issue with the test button not showing up at all within the scroll pane. The panels are there but not the test button.
You can't "add" components to a JScrollPane, this isn't how they work. A JScrollPane uses a JViewport as it's primary component, which is then used to determine when the scrollbars should be used.
See How to Use Scroll Panes for more details
Instead of...
bookList = new JScrollPane();
//...
bookList.add(bookButtons);
simply do...
bookList = new JScrollPane(bookButtons);
//...
//bookList.add(bookButtons);
I have three JTextFields, when the buy button is pressed the associated listener should retrieve the text from the text fields and use it to update the table.
The issue is that when I press the buy button it tries to use the data in the JTextFields in David's tab as opposed to the one I'm currently on. If I made another tab named "Jack" it would then try to be using jacks. The code to create the text boxes is as follows:
JLabel label2 = new JLabel("Name Of Share:");
tabPanel.add(label2);
textFieldName = new JTextField("", 15);
textFieldName.setColumns(10);
textFieldName.setToolTipText("Enter Number of shares here");
tabPanel.add(textFieldName);
The listener for the buy button:
int quantity = 0;
if (e.getActionCommand().equals("Buy")) {
String name = view.getTextFieldName().getText();
String ticker = view.getTextFieldTicker().getText().toUpperCase();
try{
quantity = Integer.parseInt(view.getTextFieldNumber().getText());
}catch(NumberFormatException er){
}
view.buy(ticker, name, quantity);
}
Everything works fine if I only have one tab but once I introduce more that's when the issues start.
Can anyone suggest a way to fix this so I can get data from the text boxes of only the tab I am on?
I should have mentioned view is of type MainGUI a Class I have created, which is used for building the GUI which has the fields:
public class MainGUI extends JFrame implements Observer {
private JTabbedPane tabbedPane;
private JTable table;
private JTextField textFieldTicker;
private JTextField textFieldName;
private JTextField textFieldNumber;
private DefaultTableModel model;
private PortfolioManager pm;
private JLabel tValue;
to create a Tab the code used is:
JPanel topPanel = new JPanel();
JPanel buttonPanel = new JPanel();
JPanel labelPanel = new JPanel();
JSplitPane splitPanelbtm = new JSplitPane(JSplitPane.VERTICAL_SPLIT, labelPanel, buttonPanel);
JSplitPane splitPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topPanel, splitPanelbtm){
private final int location = 500;
{setDividerLocation(location);}
#Override
public int getDividerLocation(){
return location;
}
#Override
public int getLastDividerLocation(){
return location;
}
};
splitPanel.setEnabled( false );
splitPanel.setDividerSize(0);
splitPanelbtm.setEnabled( false );
splitPanelbtm.setDividerSize(0);
splitPanelbtm.setBorder(null);
splitPanel.setBorder(null);
tabbedPane.add(tabName, splitPanel);
tabbedPane.setName(tabName);
this.add(tabbedPane);
this.setVisible(true);
createLabelsButtons(topPanel);
createTable(topPanel);
tValue = new JLabel("Total Value for " + tabbedPane.getName() + " is: $ ");
labelPanel.add(tValue);
createTabButtons(buttonPanel);
my program has a calculator layout, theres 9 buttons with clear , negative and convert. and 2 radio buttons that when you select one it converts the numbers you entered.
i have designed it, but im not sure how to do the action listener part.
i think i just need help starting off the code .
// import packages
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
// class
public class Lab31Panel extends JPanel implements ActionListener
{
// data declarations
private JRadioButton k2pButton;
private JRadioButton p2kButton;
private ButtonGroup weight;
private JPanel selectConversion;
private JButton jb0,jb1,jb2,jb3,jb4,jb5,jb6,jb7,jb8,jb9,jbminus,jbclear,jbconvert;
private JTextArea display;
//constructor to initiate data and set up GUI
public Lab31Panel()
{
setLayout( new BorderLayout() );
// organizing radio buttons and their behaviours
k2pButton = new JRadioButton( "Kilograms to Pounds" );
p2kButton = new JRadioButton( "Pounds to Kilograms" );
weight = new ButtonGroup();
weight.add( k2pButton );
weight.add( p2kButton );
// adding components to panel to be south of the GUI
selectConversion = new JPanel();
selectConversion.add( k2pButton );
selectConversion.add( p2kButton );
add( selectConversion, BorderLayout.SOUTH );
//setting up west area of GUI
JPanel westPanel = new JPanel();
JPanel convert = new JPanel();
// setting up components for the west of the GUI
westPanel.setLayout(new GridLayout(5,3));
westPanel.add(jb0 = new JButton("0"));
westPanel.add(jb1 = new JButton("1"));
westPanel.add(jb2 = new JButton("2"));
westPanel.add(jb3 = new JButton("3"));
westPanel.add(jb4 = new JButton("4"));
westPanel.add(jb5 = new JButton("5"));
westPanel.add(jb6 = new JButton("6"));
westPanel.add(jb7 = new JButton("7"));
westPanel.add(jb8 = new JButton("8"));
westPanel.add(jb9 = new JButton("9"));
westPanel.add(jbminus = new JButton("-"));
westPanel.add(jbclear = new JButton("clear"));
westPanel.add(jbconvert = new JButton("convert"));
add(westPanel, BorderLayout.WEST);
//setting up east components
JPanel eastPanel = new JPanel();
eastPanel.setLayout(new BorderLayout());
display = new JTextArea();
eastPanel.add(display,BorderLayout.CENTER);
add(eastPanel);
// add listeners to radio buttons
p2kButton.addActionListener(this);
k2pButton.addActionListener(this);
//add listeners to all textfields
} //end constructor
public void actionPerformed(ActionEvent e)
{
}
} // end class
Suggestions:
First and foremost, don't use the same ActionListener for all the buttons.
In that vein, don't have your program implement ActionListener.
Instead, create one ActionListener for the numeric buttons
And one or perhaps better, three, for the operations buttons.
In the numeric buttons, the code should be clear -- put the numbers into the display.
In the operations button listeners, the actions will depend on which operation was pressed.
If the convert button is pressed, then extract your numeric data from the field holding it,
Convert text to number using a parsing method.
Calculate your conversion
And then display it.
ALSO
I would not add any ActionListener to the JRadioButtons since you really don't want any action to occur when pressed.
Instead have the convert button's ActionListener check to see which JRadioButton is selected, and base the conversion equation on this selection.
Something like:
// add listeners to radio buttons // **** no, don't do this
// p2kButton.addActionListener(this);
// k2pButton.addActionListener(this);
jbclear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to clear the JTextField
// usually this will involve setText("")
}
});
jbconvert.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to convert
// first get JRadioButton selection -- which one is set
// then get data from text component
// convert it to number (but catching for NumberFormatException)
// do conversion based on the selected JRadioButton
// and display usually with a call to setText(...)
}
});
First, let me point out that I'm new to programming Java Desktop GUI's. I have created a desktop pane that can hold multiple JInternalFrames. For now, each JinternalFrame contains the same GUI components and a new jInternalFrame (Herein referred to as Internal Frame) can be created via a menu item click.
The elements on each internal Frame are as follows: 3 Jlabels, 3 JTextFields, a Jbutton and a Jtable. After rendering the first Internal Frame I populate the 3 text fields with information and then click the button and a new row is added to the table. The row contains the information used to populate the text fields.
Opening a second Internal Frame gives me, visually, the exact interface of the first. I populate this frame in the same manner,click the button and voila, the table in the second frame is populated.
The issue arises when I return to the previous internal frame. I can type into the text fields without issue but clicking the button to populate the table causes the table in the second Internal Frame to be populated. I suspect that I'm sharing a datamodel but am uncertain as to how to create distinct datamodels for jInternalFrame jTables when the GUI for each frame is the same.
Below is the code (as I am new to Java Desktop GUI development I followed one of the Oracle How-To's to render the internal Frame itself - very simple example):
public class InternalFrames extends JFrame
implements ActionListener {
private static final long serialVersionUID = 1L;
JDesktopPane desktop;
JLabel label1;
JLabel label2;
JLabel label3;
JLabel label4;
JTextField text1;
JTextField text2;
JTextField text3;
JTable table1;
public InternalFrames(){
super("Practice Internal Frames");
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset,inset,screenSize.width - (inset*2),screenSize.height - (inset*2));
desktop = new JDesktopPane();
createFrame();
setContentPane(desktop);
setJMenuBar(setMenuBar());
}
protected JMenuBar setMenuBar(){
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Document");
menu.setMnemonic(KeyEvent.VK_D);
menuBar.add(menu);
JMenuItem menuItem = new JMenuItem("New");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
menuItem.setActionCommand("New");
menuItem.addActionListener(this);
menu.add(menuItem);
menuItem = new JMenuItem("Quit");
menuItem.setMnemonic(KeyEvent.VK_Q);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.ALT_MASK));
menuItem.setActionCommand("Quit");
menuItem.addActionListener(this);
menu.add(menuItem);
return menuBar;
}
public void actionPerformed(ActionEvent e){
if ("New".equals(e.getActionCommand())){
createFrame();
} else if ("Quit".equals(e.getActionCommand())){
}
}
protected void createFrame(){
InternalFrame internalFrame = new InternalFrame();
label1 = new JLabel("Name");
label2 = new JLabel("Email Address:");
label3 = new JLabel("Mobile Number:");
label4 = new JLabel("Test Frames");
label1.setSize(100,10);
label2.setSize(100,10);
label3.setSize(100,10);
label4.setSize(200,10);
text1 = new JTextField(40);
text2 = new JTextField(40);
text3 = new JTextField(40);
internalFrame.setLayout(new MigLayout());
internalFrame.getContentPane().add(label1);
internalFrame.getContentPane().add(text1, "wrap");
internalFrame.getContentPane().add(label2);
internalFrame.getContentPane().add(text2, "wrap");
internalFrame.getContentPane().add(label3);
internalFrame.getContentPane().add(text3,"wrap");
internalFrame.getContentPane().add(label4, "span 2, wrap");
internalFrame.getContentPane().add(new JScrollPane(createTable()), "span 2 2, wrap");
internalFrame.getContentPane().add(createButton());
internalFrame.setVisible(true);
desktop.add(internalFrame);
try {
internalFrame.setSelected(true);
} catch (java.beans.PropertyVetoException pve){ }
}
protected JTable createTable(){
DefaultTableModel dModel = new DefaultTableModel();
table1 = new JTable(dModel);
dModel.addColumn("Name");
dModel.addColumn("Email Address");
dModel.addColumn("Mobile Number");
return table1;
}
protected JButton createButton(){
JButton button1 = new JButton("Add New List Member");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
System.out.println("You clicked the button");
populateTable(table1);
}
});
return button1;
}
protected void populateTable(JTable theTable){
if (validateEntry() == 0)
{
ListMembers listMember = new ListMembers();
listMember.setName(text1.getText());
listMember.setEmailAddress(text2.getText());
listMember.setMobilePhone(text3.getText());
Object[] data = {listMember.getName(),listMember.getEmailAddress(),listMember.getMobilePhone()};
DefaultTableModel dm = (DefaultTableModel) table1.getModel();
dm.addRow(data);
}
}
private static void createAndShowGUI(){
JFrame.setDefaultLookAndFeelDecorated(true);
InternalFrames internalFrame = new InternalFrames();
internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
internalFrame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Any help would be greatly appreciated.
Each time you create a new frame, you initialize a single field (table1) with this newly created table. And the listener of every button you create populates the table referenced by this unique table1 variable. The same goes for your text fields, etc.
Either only use local variables, and pass them between methods (for example, you need to pass the table you just created to the method creating the button, in order for this button to populate this table. Or you extract all the code to a new class, MyInternalFrame (choose a better name), make the table, textfields and buttons instance fields of this new class, and create a new instance of this MyInternalFrame class each time you need a new one.
This second solution looks like the best one to me.
I am adding the components dynamically at runtime on clicking the button.
But now i want to add components Dynamically without clicking button.
How can i do that..?? Here is my source code for adding a component on clicking the Button.
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
String[] items = new String[4];
items[0]="English";
items[1]="French";
items[2]="Spanish";
items[3]="Hindi";
JTextField jtextfield = new JTextField();
jtextfield.setPreferredSize(new Dimension(50, 20));
JButton jbutton = new JButton();
jbutton.setText("Remove");
jbutton.setPreferredSize(new Dimension(89, 23));
JLabel jlabel = new JLabel();
jlabel.setText("Text:");
jlabel.setPreferredSize(new Dimension(40, 20));
JLabel jlabel2 = new JLabel();
jlabel2.setText("Language:");
jlabel2.setPreferredSize(new Dimension(65, 20));
JComboBox jcombo = new JComboBox();
jcombo.setPreferredSize(new Dimension(80,20));
jcombo.addItem(items[0]);
jcombo.addItem(items[1]);
jcombo.addItem(items[2]);
jcombo.addItem(items[3]);
jPanel6.add(jlabel);
jPanel6.add(jtextfield);
jPanel6.add(jlabel2);
jPanel6.add(jcombo);
jPanel6.add(jbutton);
jbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component[]storeAllButtonInPanel = jPanel6.getComponents();
if(storeAllButtonInPanel.length!=0) {
jPanel6.remove(storeAllButtonInPanel.length-1);
jPanel6.remove(storeAllButtonInPanel.length-2);
jPanel6.remove(storeAllButtonInPanel.length-3);
jPanel6.remove(storeAllButtonInPanel.length-4);
jPanel6.remove(storeAllButtonInPanel.length-5);
jPanel6.revalidate();
validate();
repaint();
}
}
});
jPanel6.validate();
jPanel6.repaint();
}
And if i have only 2 values of Text then it also disply two rows and if 3 values then there should be only 3 rows..!! How can i do that.?
no idea what do you want, there is needed / required some control about that, as output to the GUI and by using some of Listener (as your ActionListener),
maybe (with full control) JPopupMenu, API, examples here or here
An instance of javax.swing.Timer can periodically invoke the actionPerformed() method of an ActionListener, as suggested in this example that adds and removes JLabels.