This is my first time really using graphics with Java.
I have a problem where I'm trying to populate a JScrollPane with an undefined number of panels (The following code is just a test; I know it's written using bad practices, but it's a test to see how to do it is all).
In the final program I'm going to have an ArrayList of orders (ArrayList size not predetermined), and in a JScrollPane I'm going to have a JPanel that holds a JPanel (each containing several labels) that will have details of each order.
here's the current test code (the JScrollPane is simply named scrollPane):
JPanel panel = new JPanel();
GroupLayout experimentLayout = new GroupLayout(panel);
ArrayList<JPanel> panelArray = new ArrayList();
for(int i = 0; i <3; i++){
JPanel panel2 = new JPanel();
JLabel label2 = new JLabel("Hello");
JLabel label3 = new JLabel("Hi");
panel2.add(label2);
panel2.add(label3);
//panel.add(panel2);
panelArray.add(panel2);
}
experimentLayout.setHorizontalGroup(
experimentLayout.createParallelGroup()
.addComponent(panelArray.get(0))
.addComponent(panelArray.get(1))
.addComponent(panelArray.get(2))
);
experimentLayout.setVerticalGroup(
experimentLayout.createSequentialGroup()
//.addGroup(experimentLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(panelArray.get(0))
.addComponent(panelArray.get(1))
.addComponent(panelArray.get(2))
);
scrollPane.setViewportView(panel);
When this runs, the JPanels that contain the labels are displayed horizontally (next to each other) instead of under one another.
Any help on how I could go about displaying them vertically would be a great help - Thank you all :)
You might find GridLayout to be useful.
Related
Image of my GUI.
I am trying to add components to two JPanel containers and then add those panels as cards. I want the checkboxes after labels in a vertical manner. The problem I am facing is that the components are coming in a grid of two columns:
public class MyFrame extends JFrame {
MyFrame(int width, int height, String title){
setTitle(title);
setSize(width, height);
JPanel internalJP1 = new JPanel(new GridLayout(5,1));
JLabel hobby = new JLabel("Enter your hobbies:");
JCheckBox cricket = new JCheckBox("Cricket");
JCheckBox music = new JCheckBox("Music");
JCheckBox drawing = new JCheckBox("Drawing");
JCheckBox dancing = new JCheckBox("Dancing");
JCheckBox other = new JCheckBox("Other");
internalJP1.add(hobby);
internalJP1.add(cricket);
internalJP1.add(music);
internalJP1.add(drawing);
internalJP1.add(dancing);
internalJP1.add(other);
JPanel internalJP2 = new JPanel(new GridLayout(4,1));
JLabel payment = new JLabel("Payment by:");
ButtonGroup buttonGroup = new ButtonGroup();
JRadioButton cheque = new JRadioButton("Cheque", false);
JRadioButton cash = new JRadioButton("Cash", false);
JRadioButton debitCard = new JRadioButton("Debit Card", false);
JRadioButton creditCard = new JRadioButton("Credit Card", false);
buttonGroup.add(cheque);
buttonGroup.add(cash);
buttonGroup.add(debitCard);
buttonGroup.add(creditCard);
internalJP2.add(payment);
internalJP2.add(cheque);
internalJP2.add(cash);
internalJP2.add(debitCard);
internalJP2.add(creditCard);
Container c = getContentPane();
CardLayout cl = new CardLayout();
c.setLayout(cl);
c.add(internalJP1,"crd1");
c.add(internalJP2,"crd2");
cl.show(c,"crd1");
}
}
public class Jtest {
public static void main(String[] args) {
MyFrame frame = new MyFrame(300,200,"FirstFrame");
frame.setVisible(true);
}
}
Just change this line of code (in constructor of class MyFrame)
JPanel internalJP1 = new JPanel(new GridLayout(5,1));
to this
JPanel internalJP1 = new JPanel(new GridLayout(0,1));
i.e. replace 5 with 0
I find GridLayout to not be intuitive. When the row parameter of GridLayout constructor is zero, then each row will contain exactly the number of columns indicated. Hence new GridLayout(0, 1) will ensure that each row (in the grid) will contain exactly one column and it will create as many rows as required in order to ensure this.
Note that GridLayout is not the only layout manager to use when you want to place GUI components in a single column. Swing also has BoxLayout, GridBagLayout, GroupLayout and SpringLayout.
There are also third party layout managers including JGoodies and MiG Layout.
The fact that you are using a CardLayout to view one panel or the other does not affect the layout of those panels. Your problem is entirely related to the layout of the 2 panels.
There are 2 easy ways to fix the panels to make them 1-column:
fix their number of rows so that it is >= the number of elements that you actually add. Now, you have JPanel internalJP1 = new JPanel(new GridLayout(5,1)); - but add 6 elements. If you change it to JPanel internalJP1 = new JPanel(new GridLayout(6,1));, you will solve the problem for your 1st panel. The same fix applies to your second panel. Even better, use 0 to make the layout use as many rows as it needs (see docs).
use a vertical BoxLayout and do not worry about the number of elements at all - just stack them vertically. This has the additional advantage that they look better, because even if you give the layout more size than it needs, they still stack together nicely: JPanel internalJP1 = new JPanel(); internalJP1.setLayout(new BoxLayout(internalJP1, BoxLayout.Y_AXIS));
how to add a JLabel simple text over/above a JTextField.
I tried many commands as you can see in my code but nothings works.
this is a snapshot of my code
private JPanel createTextPanel() {
int panelWidth = PANEL_SIZE.width;
int panelHeight = PANEL_SIZE.height/3;
Dimension panelSize = new Dimension(panelWidth,panelHeight);
JPanel textPanel = new JPanel();
textPanel.setPreferredSize(panelSize);
//textPanel.setLayout(null);
/* Add text */
JLabel Text_RED = new JLabel();
Text_RED.setText("Red");
//Text_RED = new JLabel("\nRED\n");
//Text_RED.setHorizontalTextPosition(SwingConstants.TOP);
//Text_RED.setVerticalAlignment(SwingConstants.TOP);
Red = new JTextField(3);
//Red.setVerticalAlignment(JTextField.TRAILING );
Red.setLocation(100,100);
//Red.setLocation(50, 50);
JLabel Text_Green = new JLabel("Green");
Green = new JTextField(3);
JLabel Text_Blue = new JLabel("Blue");
Blue = new JTextField(3);
//setLayout(new GridLayout(2,2,10,10));
textPanel.add(Text_RED);
textPanel.add(Red);
textPanel.add(Text_Green);
textPanel.add(Green);
textPanel.add(Text_Blue);
textPanel.add(Blue);
return textPanel;
}
Suggestions:
Don't use null layouts and absolute positioning. While it seems initially that using these tools is the easiest way to create complex GUI's, it's really a newbie fallacy, as the more you understand and use the layout managers, the more you'll find that they make the job of creating GUI's much easier, and the results much more attractive.
Learn about and use the layout managers. Tutorial link.
Consider using a BorderLayout and adding your JLabel BorderLayout.CENTER and the JTextField at BorderLayout.PAGE_END. As a side note, I generally avoid placing JTextFields in a BorderLayout.CENTER position since this will cause horizontal stretching of the field if the GUI changes size, which I don't think is aesthetically pleasing.
I have used the createVerticalGlue() successfully on a number of times. However in the following screen building code it is not working. I am still wondering why.
The situation is that I have two JPanels (leftPanel, rightPanel) within another Panel (centralPanel). Each of these two panels will host two JComponents using a BoxLayout Y-Axis. I want to distribute the remaining free space before, between and after the two JComponents.
I know that I can use empty borders and rigid areas to solve the problem but it happens that I am a bit hard headed!
My appologies for the long question.
public class MemberGUI extends JFrame {
JPanel contPane = (JPanel) this.getContentPane();
JPanel centralPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JPanel lowerPanel = new JPanel();
JLabel title = new JLabel("Add/Delete Member");
JLabel nameLbl = new JLabel("Member's name");
JLabel idLbl = new JLabel ("Member ID");
JTextField nameFld = new JTextField(10);
JTextField idFld = new JTextField(10);
public void buildMe(){
//LayoutManagers
contPane.add(title,BorderLayout.PAGE_START);
contPane.add(centralPanel,BorderLayout.CENTER);
contPane.add(lowerPanel,BorderLayout.PAGE_END);
centralPanel.add(leftPanel);
centralPanel.add(rightPanel);
leftPanel.setLayout(new BoxLayout(leftPanel,BoxLayout.Y_AXIS));
rightPanel.setLayout(new BoxLayout(rightPanel,BoxLayout.Y_AXIS));
//leftPanel.add(Box.createRigidArea(new Dimension(0,50)));
leftPanel.add(Box.createVerticalGlue());
leftPanel.add(idLbl);
leftPanel.add(Box.createVerticalGlue());
leftPanel.add(nameLbl);
leftPanel.add(Box.createVerticalGlue());
//rightPanel.add(Box.createRigidArea(new Dimension(0,50)));
rightPanel.add(Box.createVerticalGlue());
rightPanel.add(idFld);
rightPanel.add(Box.createVerticalGlue());
rightPanel.add(nameFld);
rightPanel.add(Box.createVerticalGlue());
// JFrame Settings
this.setSize(500,400);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
afaics, centralPanel has default layoutManager, which is FlowLayout. This always sizes its children to their prefSize, so the glue never comes into play.
Nesting containers comes at a price (which nesting wizards like #Andrew happily pay :-) Also, it's not entirely trivial to get right (f.i. replace the upper textField with a comboBox to see the mis-alignment). In the longer run, there's hardly a route around learning to master a more powerful manager, like f.i. MigLayout (my current personal favorite)
I'm trying to add a JList to a GUI, but am wondering how to position it? I want it to appear on the right hand side of the TextArea for data that will be sent to the GUI for selection.
Can anyone suggest how to do this? Here is the code (note: very new to Java and GUI's)
protected static void createAndShowGUI() {
GUI predict = new GUI();
JFrame frame = new JFrame("Phone V1.0");
frame.setContentPane(predict.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setMinimumSize(new Dimension(300, 400));
frame.setVisible(true); // Otherwise invisible window
}
private JPanel createContentPane() {
JPanel pane = new JPanel();
TextArea = new JTextArea(5, 10);
TextArea.setEditable(false);
TextArea.setLineWrap(true);
TextArea.setWrapStyleWord(true);
TextArea.setWrapStyleWord(true);
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
//Adds the buttons from Top to Bottom
String[] items = {"dsfsdfd"};
list = new JList(items);
JScrollPane scrollingList = new JScrollPane(list);
int orient = list.getLayoutOrientation();
JPanel window = new JPanel();
pane.add(window);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(5, 3));
JButton[] buttons = new JButton[] {
new JButton("Yes"),
new JButton(""),
new JButton("Clr"),
new JButton("1"),
new JButton("2abc"),
new JButton("3def"),
new JButton("4ghi"),
new JButton("5jkl"),
new JButton("6mno"),
new JButton("7pqrs"),
new JButton("8tuv"),
new JButton("9wxyz"),
new JButton("*+"),
new JButton("0_"),
new JButton("^#")
}; // Array Initialiser
for (int i = 0; i < buttons.length; i++) {
buttonPanel.add(buttons[i]);
buttons[i].addActionListener(this);
}
pane.add(TextArea);
pane.add(list);
pane.add(buttonPanel);
return pane;
}
Read the section from the Swing tutorial on Using Layout Mananger. There is no need to only use a single layout manager. You can nest layout managers to get the desired effect.
Wrap your TextArea and list in a new panel with a BorderLayout manager. Basically the BorderLayout manager lets you arrange components using north, south, east, west and center coordinates. The components at the center takes all available space as the parent container has more space available to it.
private JPanel createContentPane() {
JPanel pane = new JPanel(); //this is your main panel
JPanel textAreaPanel = new JPanel(new BorderLayout()); //the wrapper
//Some more code...
//Then at the end
//Make your TextArea take the center
textAreaPanel.add(TextArea, BorderLayout.CENTER);
//And the list to the east
textAreaPanel.add(list, BorderLayout.EAST);
pane.add(textAreaPanel);
pane.add(buttonPanel);
return pane;
}
The cool thing is that you can nest panels inside other panels, adding them different layout managers to get your desired layout.
On an unrelated note, try to follow Java naming conventions. Instead of JTextArea TextArea use JTextArea textArea. It makes it easier for you and people reading your code to understand it.
You could use a layout manager like Mig Layout for that kind of positionning.
(source: miglayout.com)
I could recommend you FormLayout. Before I found this layout I had a real pain with GridBagLayout. FormLayout is more powerful and much more convenient to learn and use and it is free. Give it a chance.
As others suggested, familiarize yourself with the concept of layout managers. There are several that come with the standard Swing API and several good 3rd party ones out there.
In addition, you will want to add the JList to a scroll pane (JScrollPane). You may want to consider adding it to a split pane (JSplitPane). And by consider I don't mean "do it because some guy on the net said so" I mean "do it if it makes sense for your end users".
I had problem using a very simple frame containing two JPanel.
The problem is on the layout of the Center JPanel that contains four JButton.
How can I set a better size for buttons or directly for JPanel that uses the GridLayout. On the picture the problem:
alt http://img42.imageshack.us/img42/4601/horrible.jpg
!
Here the code: ` JFrame window = new JFrame("Horrible! LOL");
JTextField textField = new JTextField("");
textField.setPreferredSize(new Dimension(200,20));
JPanel textPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
textPanel.add(textField);
window.add(textPanel, BorderLayout.NORTH);
JButton plus = new JButton("+");
//plus.setPreferredSize(new Dimension(50,50)); nothing would change
JButton minus = new JButton("-");
JButton per = new JButton("x");
JButton divide = new JButton("/");
JPanel prova = new JPanel(new GridLayout(2,2,10,10));
Dimension d = new Dimension(20,20);
prova.setMaximumSize(d); // nothing changed!
prova.add(plus);
prova.add(minus);
prova.add(per);
prova.add(divide);
window.add(prova, BorderLayout.CENTER);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(250,300);
window.setResizable(false);
window.setVisible(true);`
Which is a good solution?
Kind regards
Unfortunately gridlayout doesent respect preferred sizes. But still if you want to stick to grid layout then you can try something like this:
public static JComponent wrap(JComponent comp)
{
JPanel panel = new JPanel();
panel.add(comp);
return panel;
}
And then instead of direclty adding in to prova add like this:
prova.add(wrap(plus));
prova.add(wrap(minus));
prova.add(wrap(per));
prova.add(wrap(divide));
Tested, Works perfect!!
There are other better ways though
That's what happen to me:
It's definitely attached to the upper edge of the grid.
alt text http://img96.imageshack.us/img96/9431/stillnot.jpg
Even if in this case, in the wrap method I can set the preferredSize of buttons/comp, every buttons is on its own edge. What about others solutions. How would you position buttons for a calculator?
Kind regards and thanx angain!