I am attempting to create a JPanel that houses in a GridLayout a number of JLabels to the left JTextFields on the right. Unfortunately, nothing is shown even if the Components are reported as correctly added. Where is the problem?
public class AlternateGL_JPanel extends JPanel {
protected JPanel layoutPanel;
protected int rows, columns;
public AlternateGL_JPanel(int rows, int columns) {
this.rows = rows;
this.columns = columns;
// ===== MAIN FRAME DEFINITION =====
setBorder(new EmptyBorder(0, 0, 0, 0));
setLayout(new GridLayout(this.rows, this.columns));
// setBounds(10, 10, 500, 500);
// ===== INNER PANEL =====
this.layoutPanel = new JPanel(); //This is the nested panel
layoutPanel.setLayout(new GridLayout(this.rows, this.columns));
super.add(layoutPanel, BorderLayout.PAGE_START);
}
// =========================================================
// TODO | Superclass: JPanel
public void add(JComponent component) {
layoutPanel.add(component);
}
}
/** A <b>ManyTextAndInsertText</b> is a {#link JPanel} that houses a number of {#link JLabel}s to the left
* and {#link JTextField}s on the right.
*
*/
public class ManyTextAndInsertText extends AlternateGL_JPanel {
private JLabel[] texts;
private JTextField[] insertTexts;
public ManyTextAndInsertText(String[] descriptions) {
super(descriptions.length, 2);
this.texts = new JLabel[descriptions.length];
this.insertTexts = new JTextField[descriptions.length];
for(int i=0 ; i<descriptions.length ; i++)
{
texts[i] = new JLabel(descriptions[i]);
insertTexts[i] = new JTextField();
for(int j=0 ; j<this.getComponentCount() ; j++)
System.out.println("\t" + this.getComponent(j).toString());
this.add(texts[i]);
for(int j=0 ; j<this.getComponentCount() ; j++)
System.out.println("\t" + this.getComponent(j).toString());
this.add(insertTexts[i]);
}
}
public class TestManyTextes extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestManyTextes frame = new TestManyTextes();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestManyTextes() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new ManyTextAndInsertText(new String[] { "First text: " , "Second text: "});
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
}
I greatly simplified your code and created this GUI.
Instead of extending Swing components, I used Swing components.
You would get a nicer looking form using a GridBagLayout, rather than a GridLayout.
Here's the runnable example.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class TestManyTexts {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new TestManyTexts();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestManyTexts() {
JFrame frame = new JFrame("Test Many Texts");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ManyTexts panel = new ManyTexts(new String[] { "First text: ",
"Second text: ", "Third Text:", "Forth Text" });
frame.add(panel.getPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class ManyTexts {
private JPanel panel;
private JTextField[] fields;
public ManyTexts(String[] labels) {
createPanel(labels);
}
private void createPanel(String[] labels) {
panel = new JPanel(new GridLayout(0, 2));
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
fields = new JTextField[labels.length];
for (int i = 0; i < labels.length; i++) {
JLabel label = new JLabel(labels[i]);
panel.add(label);
fields[i] = new JTextField(15);
panel.add(fields[i]);
}
}
public JPanel getPanel() {
return panel;
}
public JTextField[] getFields() {
return fields;
}
}
}
Related
i have a problem with adding a specific number of buttons from my for-loop to my JPanel, i know how to add all oof them, but i want to add only 1-10 (i havent decided yet, lets go with 10).'
this is my class where i just declare what objects i want to have.
private static int cID;
private static Deck[] card;
static ArrayList<JButton> buttonList = new ArrayList<JButton>();
private JFrame f;
private JPanel p1;
private JButton button;
public boolean isEmpty() {
return cID == 0;
}
public static void main(String[] args) {
CustomDecks c = new CustomDecks();
c.deckCreator();
}```
this is my for-loop where i create 420 buttons and give them names "card" + i where i is 0 - 419, yet when i try to add card0 to my panel, it fails, why?
private void deckCreator() {
card = new Deck[25];
new ArrayList<Cards> (cSet.cards);
for(int i = 0; i < 420; i++) {
button = new JButton();
buttonList.add(button);
button.setName("card" + i);
f.add(button);
p1.add(card0);
}
f.add(p1);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
f.setExtendedState(Frame.MAXIMIZED_BOTH);
f.setUndecorated(true);
}
}
}
I'm not sure you can create a JPanel large enough to hold 420 JButtons.
Here's an example of a JButton GUI.
[
Generally, you create an application model and view separately. The model is made up of one or more plain Java classes. The view reads from the application model but doesn't update the model.
Your controller classes (ActionListener classes) update the application model and update / repaint the view.
This pattern is called the model / view / controller (MVC) pattern.
You can see in the example code below that the model is created in the view class constructor. Generally, you create the application model first, then you create the application view.
And here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class JButtonScrollGUI {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new JButtonScrollGUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private String[] greekAlphabet;
public JButtonScrollGUI() {
this.greekAlphabet = new String[] { "alpha", "beta", "gamma", "epsilon", "zeta" };
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setTitle("Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createScrollPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createScrollPanel() {
JPanel panel = new JPanel(new BorderLayout());
JPanel innerPanel = createButtonPanel();
Dimension d = innerPanel.getPreferredSize();
d.width += 50;
d.height /= 2;
panel.setPreferredSize(d);
JScrollPane scrollPane = new JScrollPane(innerPanel);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 3, 10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < 20; i++) {
JButton button1 = new JButton("Previous " + i);
panel.add(button1);
JComboBox<String> selectorBox = new JComboBox<>(greekAlphabet);
panel.add(selectorBox);
JButton button2 = new JButton("Next " + i);
button2.setPreferredSize(button1.getPreferredSize());
panel.add(button2);
}
return panel;
}
}
I want to make the JLabel answer print out the answer when users press the label. But I found line 104 does not use the "input" from HanoisFrames. It keeps using 0 as "input" and prints out "0". I tried to write line 96 as
"private class MouseHandler extends HanoisFrames implements MouseListener, MouseMotionListener" and I used "super (int)" but it does not work. What should I do?
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Hanoi {
private JFrame frame;
JButton[][] buttons= new JButton[3][3];
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Hanoi window = new Hanoi();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Hanoi() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 901, 696);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menubar=new JMenuBar();//Menu
frame.setJMenuBar(menubar);
JMenu file= new JMenu("File");
file.setFont(new Font("Segoe UI", Font.PLAIN, 21));
menubar.add(file);
JMenuItem exit= new JMenuItem("Exit");//provide users a way to exit
exit.setFont(new Font("Segoe UI", Font.PLAIN, 21));
file.add(exit);
class exitaction implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
exit.addActionListener(new exitaction());
JPanel panelone = new JPanel();
frame.getContentPane().add(panelone, BorderLayout.CENTER);
panelone.setBackground(Color.WHITE);
panelone.setLayout(new GridLayout(3,4,3,3));
JPanel paneltwo = new JPanel();
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
paneltwo.setBackground(Color.WHITE);
JLabel lblFunHanoiTower = new JLabel("Fun Hanoi Tower");
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
lblFunHanoiTower.setForeground(Color.BLACK);
lblFunHanoiTower.setBackground(SystemColor.activeCaption);
lblFunHanoiTower.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
paneltwo.add(lblFunHanoiTower);
ActionListener listener =new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
if(e.getSource()==buttons[row][col]){
buttons[row][col].setBackground(Color.lightGray);
HanoisFrames f= new HanoisFrames(((row*3)+(col+3)));
f.setVisible(true);//
}
}
}
}
};
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
buttons[row][col] = new JButton("level "+String.valueOf((row*3)+(col+3)-2));
buttons[row][col].setFont(new Font("Tempus Sans ITC", Font.BOLD, 32));
buttons[row][col].setBackground(SystemColor.controlHighlight);
buttons[row][col].setSize(6, 6);
buttons[row][col].addActionListener(listener);
panelone.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
panelone.add(buttons[row][col]);
}
}
}
}
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret ;
private JButton next;
private JButton last;
private JLabel answer;
private JMenu menu;
private JButton reset;
private JLabel move;
private JPanel panel;
static int input;
private JLabel lblLevel;
boolean showAnswer=false;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HanoisFrames frame = new HanoisFrames(input);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public HanoisFrames(int input) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 901, 696);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
MouseHandler handler=new MouseHandler();
panel = new JPanel();
contentPane.add(panel, BorderLayout.SOUTH);
panel.setLayout(new GridLayout(2,3));
move = new JLabel(" Move");
panel.add(move);
reset = new JButton("Reset");
panel.add(reset);
answer = new JLabel();
answer.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(answer);
answer.setText("Answer");
answer.addMouseListener(handler);
answer.addMouseMotionListener(handler);
last = new JButton("Last");
panel.add(last);
ret = new JButton("Return");
panel.add(ret);
next = new JButton("Next");
panel.add(next);
lblLevel = new JLabel("LEVEL "+ String.valueOf(input-2));
lblLevel.setHorizontalAlignment(SwingConstants.CENTER);
lblLevel.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
contentPane.add(lblLevel, BorderLayout.NORTH);
}
public int hanoiCalculator(int input) {
if (input==0){
return 0;
}else if (input==1){
return 1;
}else{
return 2*(hanoiCalculator(input-1)+1)-1;
}
}
private class MouseHandler implements MouseListener,MouseMotionListener {
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
answer.setText("Answer: "+String.valueOf(hanoiCalculator(input)).toString());
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
answer.setText("Answer: ");
}
}
}
Here:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
// ...
private JPanel panel;
static int input;
You never set your input value in your HanoiFrames constructor, and so it remains the default value for an int field, 0. But even if you did set the field because it's a static field, any changes made to it in any HanoiFrames class will change the value in all HanoiFrames classes, and so it cannot be a static field.
So, change input declaration to non-static:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret;
//.....
private JPanel panel;
private int input; // private non-static field now
and set it in the constructor:
public HanoisFrames(int input) {
this.input = input;
This way each HanoisFrames will have a unique and durable input value
Side Recommendation:
I would advise against creating and then swapping a bunch of JFrames. Instead gear your code towards creating JPanels, and then swap them when needed, using a CardLayout.
I wanted to display same textfield and label in both the panels that are added to JTabbedPane but one of panel is displaying the textfield and label and the other is not, when added the same textfield and label for both the panels.
You can only display a component in one container. Better to have your JPanels share the same model, which for the JTextField is its Document, and for the JLabel -- well its text (not really a model that you can extract, so you'll have to change both yourself).
A bit overconvoluted example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
#SuppressWarnings("serial")
public class SharedModels extends JPanel {
private static final int TABS = 10;
private JTabbedPane tabbedPane = new JTabbedPane();
private JTextField labelText = new JTextField(10);
private MyModel myModel = new MyModel();
public SharedModels() {
for (int i = 0; i < TABS; i++) {
MyPanel myPanel = new MyPanel(myModel);
String text = "tab: " + (i + 1);
tabbedPane.addTab(text, myPanel);
}
JPanel topPanel = new JPanel();
topPanel.add(new JLabel("Text for JLabel:"));
topPanel.add(labelText);
labelText.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
setLabelText(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
setLabelText(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
setLabelText(e);
}
private void setLabelText(DocumentEvent e) {
Document doc = e.getDocument();
int length = doc.getLength();
try {
String text = doc.getText(0, length);
myModel.setLabelText(text);
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
});
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(tabbedPane, BorderLayout.CENTER);
add(new MyPanel(myModel), BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
SharedModels mainPanel = new SharedModels();
JFrame frame = new JFrame("SharedModels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyModel {
private Document document = new PlainDocument();
private String labelText = "";
private EventListenerList eventListenerList = new EventListenerList();
private ChangeEvent changeEvent = null;
public void addChangeListener(ChangeListener l) {
eventListenerList.add(ChangeListener.class, l);
}
public void removeChangeListener(ChangeListener l) {
eventListenerList.remove(ChangeListener.class, l);
}
public String getLabelText() {
return labelText;
}
public void setLabelText(String labelText) {
this.labelText = labelText;
fireChangeListeners();
}
protected void fireChangeListeners() {
Object[] listeners = eventListenerList.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == ChangeListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
}
}
}
public Document getDocument() {
return document;
}
}
#SuppressWarnings("serial")
class MyPanel extends JPanel {
private JLabel label = new JLabel("");
private JTextField textField = new JTextField(10);
public MyPanel(MyModel myModel) {
textField.setDocument(myModel.getDocument());
myModel.addChangeListener(ce -> {
label.setText(myModel.getLabelText());
});
add(new JLabel("Label text:"));
add(label);
add(textField);
setPreferredSize(new Dimension(400, 100));
}
}
I want to display a list of strings in a window and i tried to use a JPanel surounded by JScrollPane because the size of the strings list is unknown. The problem is that the window is displaying the text Horizontally and i want to be displayed line after line. How to fix this? This is the code i've written so far.
package interface_classes;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
public class ErrorMessageW {
private JFrame errorMessageW;
private ArrayList<String> errors;
private JPanel panel;
private JScrollPane scrollPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
final ArrayList<String> err = new ArrayList<>();
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ErrorMessageW window = new ErrorMessageW(err);
window.errorMessageW.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ErrorMessageW(ArrayList<String> err) {
errors = err;
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
errorMessageW = new JFrame();
errorMessageW.setTitle("Unfilled forms");
errorMessageW.setBounds(100, 100, 367, 300);
errorMessageW.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnOk = new JButton("OK");
btnOk.setBounds(239, 208, 89, 23);
btnOk.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
errorMessageW.dispose();
}
});
errorMessageW.getContentPane().setLayout(null);
errorMessageW.getContentPane().add(btnOk);
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBounds(10, 10, 330, 175);
errorMessageW.getContentPane().add(scrollPane);
panel = new JPanel();
for(String s : errors){
JTextArea text = new JTextArea(1,20);
text.setText(s);
text.setFont(new Font("Verdana",1,10));
text.setForeground(Color.RED);
panel.add(text);
}
scrollPane.setViewportView(panel);
}
public JFrame getErrorMessageW() {
return errorMessageW;
}
public void setErrorMessageW(JFrame errorMessageW) {
this.errorMessageW = errorMessageW;
}
}
This is what i get
This is what i want, but using the JScrollPane:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class ErrorMessageW {
private JFrame errorMessageW;
private ArrayList<String> errors;
private JPanel panel;
private JScrollPane scrollPane;
private JTextArea errorMessage = new JTextArea(3, 30);
/**
* Launch the application.
*/
public static void main(String[] args) {
final ArrayList<String> err = new ArrayList<String>();
err.add("Short String");
err.add("A very very very very very very very very very very very "
+ "very very very very very very very very very very very "
+ "very very very very very very very very long String");
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ErrorMessageW window = new ErrorMessageW(err);
window.errorMessageW.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ErrorMessageW(ArrayList<String> err) {
errors = err;
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
errorMessageW = new JFrame();
JPanel contentPane = new JPanel(new BorderLayout(5, 15));
contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
errorMessage.setLineWrap(true);
errorMessage.setWrapStyleWord(true);
JScrollPane jsp = new JScrollPane(
errorMessage,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
contentPane.add(jsp, BorderLayout.PAGE_START);
errorMessageW.add(contentPane);
errorMessageW.setTitle("Unfilled forms");
errorMessageW.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JButton btnOk = new JButton("OK");
btnOk.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
errorMessageW.dispose();
}
});
JPanel btnConstrain = new JPanel(new FlowLayout(FlowLayout.TRAILING));
btnConstrain.add(btnOk);
contentPane.add(btnConstrain, BorderLayout.PAGE_END);
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scrollPane, BorderLayout.CENTER);
DefaultListModel<String> listModel = new DefaultListModel<String>();
for (String s : errors) {
listModel.addElement(s);
}
final JList<String> errorList = new JList<String>(listModel);
Dimension preferredSize = new Dimension(errorMessage.getPreferredSize().width,200);
errorList.setPreferredSize(preferredSize);
ListSelectionListener errorSelect = new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
errorMessage.setText(errorList.getSelectedValue());
}
};
errorList.addListSelectionListener(errorSelect);
scrollPane.setViewportView(errorList);
errorMessageW.pack();
}
public JFrame getErrorMessageW() {
return errorMessageW;
}
public void setErrorMessageW(JFrame errorMessageW) {
this.errorMessageW = errorMessageW;
}
}
First of all, you could try, instead of creating multiple instances of JTextArea, using only one and appending each error to it like this:
JTextArea text = new JTextArea(1, 20);
text.setFont(new Font("Verdana",1,10));
text.setForeground(Color.RED);
for(String s : errors) {
text.append(s + "\n");
}
panel.add(text);
However, if you do need to create more than one JTextArea, you can use a BoxLayout like this:
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
You just need to write a function that adds a new line character as an element of your ArrayList after every other element in your ArrayList of errors. Below i did a test program that shows how that can be done. I also checked the oputput. Just paste the code and understand the working of code. All the best!
import java.util.ArrayList;
public class TestingArraylist {
static ArrayList<String> errors = new ArrayList<String>();
static final String[] warnings = new String[]{"Error 0 occured","Error 1 occured","Error 2 occured","Error 3 occured","Error 4 occured"};;
public static void addNewLineToArrayList(String[] elementofarraylist){
for(int i =0;i<elementofarraylist.length;i++){
errors.add(elementofarraylist[i]);
errors.add("\n"); //this is what you need to do!
}
}
public static void main(String[] args) {
addNewLineToArrayList(warnings);
//checking below if our work has really succeded or not!!
for(int j =0;j<errors.size();j++){
System.out.print(errors.get(j));
}
}
}
Hello Guru's I am a beginner Java swing developer and am trying to build a simple app... here is a simplified version.
Setup: 1 JFrame, 2 BorderLayout based tabbed panels (A and B) each has 1 textfiled, shared JPanel class with combo box and ItemListener initialized in each tab's (North)
Issue: How to control updates to textfield's text based on which panel it came from eg. if I select Apples in TabA, the Item Listener updates the TextField on TabB as well. What I would like to accomplish is determine where the call came from TabA or TabB and only update the textfield associated with that tab.
Hope this makes some sense
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public JTextField tfPanelA;
public JTextField tfPanelB;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
contentPane.add(tabbedPane, BorderLayout.CENTER);
JPanel panelA = new JPanel();
tabbedPane.addTab("Tab A", null, panelA, null);
panelA.setLayout(new BorderLayout(0, 0));
sharedPanel s1 = new sharedPanel(this);
panelA.add(s1, BorderLayout.NORTH);
tfPanelA = new JTextField();
panelA.add(tfPanelA);
tfPanelA.setColumns(10);
JPanel panelB = new JPanel();
tabbedPane.addTab("Tab B", null, panelB, null);
panelB.setLayout(new BorderLayout(0, 0));
sharedPanel s2 = new sharedPanel(this);
panelB.add(s2, BorderLayout.NORTH);
tfPanelB = new JTextField();
panelB.add(tfPanelB);
tfPanelB.setColumns(10);
}
}
// Shared Class...
public class sharedPanel extends JPanel {
private Main app;
private String[] clist = {"Apples","Oranges","Bananas"};
/**
* Create the panel.
*/
public sharedPanel(final Main app) {
this.app=app;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
//update PanelA's textfield ONLY if called from PanelA
// do this if called from PanelA
app.tfPanelA.setText(e.getItem().toString());
// do this if called from PanelB
app.tfPanelB.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Since you have create a new instance of sharedPanel for each tab, simply provide a reference to the text field you want to be updated to it...
Which you end up with something more like...
public class sharedPanel extends JPanel {
private JTextField field;
private String[] clist = {"Apples","Oranges","Bananas"};
public sharedPanel(final JTextField field) {
this.field=field;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
sharedPanel.this.field.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Updated with a "model" example
This is very basic example of just one possible use of a model to bridge the changes between the common panel and other panels. This means that the common panel doesn't care about anything else and updates the supplied model, which fires events to interested parties who can take appropriate action as required.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TabbedModel {
protected static final String[] MAIN_LIST = {"Apples","Oranges","Bananas"};
public static void main(String[] args) {
new TabbedModel();
}
public TabbedModel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTabbedPane tabPane = new JTabbedPane();
tabPane.addTab("A", new ATab());
tabPane.addTab("B", new ATab());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(tabPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DefaultCommonModel implements CommonModel {
private List<ChangeListener> listeners;
private String value;
public DefaultCommonModel() {
listeners = new ArrayList<>(25);
}
#Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
#Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
#Override
public void setValue(String aValue) {
if (aValue == null ? value != null : !aValue.equals(value)) {
value = aValue;
fireStateChanged();
}
}
#Override
public String getValue() {
return value;
}
protected void fireStateChanged() {
if (!listeners.isEmpty()) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
}
public interface CommonModel {
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
public void setValue(String value);
public String getValue();
}
public class CommonPanel extends JPanel {
private CommonModel model;
private JComboBox comboBox;
public CommonPanel(CommonModel model) {
this.model = model;
setLayout(new GridBagLayout());
comboBox = new JComboBox(new DefaultComboBoxModel<>(MAIN_LIST));
comboBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
String value = (String) e.getItem();
CommonPanel.this.model.setValue(value);
}
});
add(comboBox);
}
}
public class ATab extends JPanel {
private List<JTextField> fields;
public ATab() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
DefaultCommonModel model = new DefaultCommonModel();
model.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
CommonModel model = (CommonModel) e.getSource();
for (JTextField field : fields) {
field.setText(model.getValue());
}
}
});
CommonPanel commonPanel = new CommonPanel(model);
add(commonPanel, gbc);
fields = new ArrayList<>(25);
for (int index = 0; index < random(); index++) {
JTextField field = new JTextField(10);
add(field, gbc);
fields.add(field);
}
}
protected int random() {
return (int)Math.round(Math.random() * 9) + 1;
}
}
}
Since you have two instances of your SharedPanel you can add the textfield to be updated as a reference to the constructor:
SharedPanel s1 = new SharedPanel(this, tfPanelA);
and
public SharedPanel(final Main app, final JTextField tf) {
...
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
tf.setText(e.getItem().toString());
}
});
...
}