import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Frame extends JFrame {
private JPanel buttonPanel;
private JButton[][] buttons;
private JPanel otherPanel;
public Frame() {
setSize(500, 600);
setLocation(100, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
setResizable(false);
setVisible(true);
buttonPanel = new JPanel();
buttonPanel.setLocation(0, 0);
buttonPanel.setSize(500, 500);
buttonPanel.setLayout(new GridLayout(8, 8));
buttons = new JButton[8][8];
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
buttons[i][j] = new JButton("" + i);
buttonPanel.add(buttons[i][j]);
}
}
add(buttonPanel);
}
}
the buttons are supposed to be put on the panel and then the panel is put on the frame. when its run however nothing is shown on the frame
thanks for the help
Look at where you're setting the JFrame visible. And then look at where you're adding your buttons. Kind of out of order, don't you think? It's like taking a picture of a chair, and then after doing that, asking someone to sit in the chair. If you want to take a portrait, have them sit in the chair first, and then take the picture. Call setVisible(true) after adding all components.
Get rid of your use of null layout as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain. Instead you will want to study and learn the layout managers and then nest JPanels, each using its own layout manager to create pleasing and complex GUI's that look good on all OS's.
where is the main ?
also you have to make an object from JFrame and use it to add these methods, example JFrame f=new JFrame;
f.setSize(..,..);
and so on..
Related
How would one delete the current card that the user is on. I know how to go through a card layout using the next and previous function, but how would one remove the current frame that the user is on? For example, if I have a program where I am currently on the 3rd panel out of 5 total panels, how would I delete the current one which is the 3rd panel. Once you remove it, the next or previous one replaces it. I do not think removecurrentlayout can be used cause I am not removing a component. For example, in the code, how would I go about delete Card 3 if I am on that.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CardLayoutProg {
public static void main(String[] args) {
JFrame frame = new JFrame("CardLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
JPanel buttonPanel = new JPanel();
JButton nextButton = new JButton("Next");
buttonPanel.add(nextButton);
contentPane.add(buttonPanel, BorderLayout.SOUTH);
final JPanel cardPanel = new JPanel();
final CardLayout cardLayout = new CardLayout();
cardPanel.setLayout(cardLayout);
for (int i = 1; i <= 5; i++) {
JButton card = new JButton("Card " + i);
card.setPreferredSize(new Dimension(200, 200));
String cardName = "card" + 123123;
cardPanel.add(card, cardName);
}
contentPane.add(cardPanel, BorderLayout.CENTER);
nextButton.addActionListener(e -> cardLayout.next(cardPanel));
frame.pack();
frame.setVisible(true);
}
}
If you look at the docs for Container, you will see that it has a remove() method. Since JPanel extends Container, it also has this method. You should familiarize yourself with these API docs to find this kind of information.
Unfortunately the CardLayout does not tell you which card (JPanel) is currently being displayed.
Check out Card Layout Focus for a class that extends the CardLayout to provide this functionality.
You would use the getCurrentCard() method to access the panel currently being displayed.
Then once you get the card currently being displayed you can remove it from the parent panel using by the remove(...) method of the Container class.
You would just use the class as follows:
//final CardLayout cardLayout = new CardLayout();
final RXCardLayout cardLayout = new RXCardLayout();
The logic for your "Remove" button would be:
cardPanel.remove(cardLayout.getCurrentCard());
When you say index(3rd panel of 5 panels), you mean the name (String) of the component when it was inserted, right? I don't know any elegant way to do this, but you can try to get all the components in this container (parentComponent) and try to find the one that has the same name as your index. For example:
Component[] components = parentComponent.getComponents();
for(int i = 0; i < components.length; i++) {
if(components[i].getName().equals(index)) {
cardLayout.removeLayoutComponent(components[i]);
}
}
I'm trying to add the JScrollPane to my JTextArea, but somehow, it won't appear.
I've tried resizing it according to the dimension of the JTextArea, but it doesn't seem to work. Also, notice that I'm using the null layout because I want the full-on flexibility of displaying certain buttons and panels at a pinpoint location.
import java.awt.Dimension;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.JTextArea;
public class PaneTester{
private static JFrame frame;
private static JPanel panel;
private static JScrollPane scrollPane;
private static JTextArea notificationBox;
public static void main (String [] args){
stage1();
stage2();
}
private static void stage1(){
createFrame();
createPanel();
frame.getContentPane().add(panel);
panel.setVisible(true);
frame.setVisible(true);
}
private static void stage2(){
generateNotificationBox();
}
private static void createFrame(){
frame = new JFrame();
frame.setSize(new Dimension(900,700));
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
}
private static void createPanel(){
panel = new JPanel();
panel.setLayout(null);
generateGridButtons();
}
private static void generateGridButtons(){
short y = 0;
for(short i=0;i<4;i++){
y += 60;
short x = 500;
for(short j=0;j<5;j++){
JButton gridButton = new JButton();
gridButton.setBounds(x, y,120,60);
panel.add(gridButton);
x += 140;
}
}
}
public static void generateNotificationBox(){
notificationBox = new JTextArea(10,10);
notificationBox.setBounds(25, 25, 200, 400);
scrollPane = new JScrollPane(notificationBox, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS );
Dimension d = new Dimension(notificationBox.getPreferredSize());
scrollPane.getViewport().setPreferredSize(d);
scrollPane.getViewport().add(notificationBox);
panel.add(notificationBox);
panel.repaint();
}
}
Stop mucking with setBounds and setPreferredSize, you're just making live more difficult for your self.
If you want to affect the size of JTextArea (and the viewable area of the JScrollPane) have a look at the JTextArea constructor JTextArea(int rows, int columns), which will allow you to specify the number of rows/columns you want the JTextArea to default to, and which will allow the JTextArea to calculate it's preferredSize based on the current font's metrics in more stable cross platform way
Your core problem, however, is right here...
scrollPane.getViewport().add(notificationBox);
panel.add(notificationBox);
You add the notificationBox to the JScrollPanes JViewport, which is good, but then you add notificationBox to the panel, which will remove it from the JScrollPane's JViewport, which is bad
Instead, add the JScrollPane to the panel
scrollPane.getViewport().add(notificationBox);
panel.add(scrollPane);
You're also making overuse of static. I'd highly recommend you take the time to reduce static down to it's absolute minimum required usage, this will probably mean that rather then constructing the UI in the main method, you have a "main" class which you can insatiate (from main) which will perform the initial setup - IMHO
I've tried that. I think someone else suggested that from another post, but when I tried that, it just took away the JTextArea completely from the panel
Get rid of panel.setLayout(null); and start making use of appropriate layout managers and compound layouts. Start by having look at Laying Out Components Within a Container for more details
So I am a computer science student and I've finished my first year. I wanted to create a simple program and I realized that I am so tired of using no layout;
this.setLayout(null);
It is so tiresome to add bounds to every single component. Well, I have been using JPanel components and GridLayout a lot, which have made my work a bit easier. But I am tired of it.
I care very much about the look of the GUI I make and use almost half the time programming to make the GUI look good before I start adding the functionality of the code. By not using a layout and adding bounds I am forced to setResizable(false) because it looks bad if I change the size of the JFrame.
I've been searching a bit, and I know of BorderLayout, and FlowLayout, but I don't like them. Is there any Layout that keeps the relative size of the components with respect to the size of the window?
For example I want to make a simple program that looks like this: (Quick sketch in Photoshop)
I can easily make this with 3 panels, but as I said, if I change the size of the frame everything stays in place instead of being relative to the window-size.
Can you guys help me?
This design looks for me to fit the BorderLayout, where in the NORTH you have the values that changes the CENTER you have the main part, and the SOUTH you have the buttons.
Link to the Oracle Border Layout
You can apply this BorderLayout to the JFrame, then create 3 JPanels for each of the NORTH,CENTER and SOUTH sections. If you want to use responsive design for the components and panels, take a look at GridBagLayout which is much more flexible than the GridLayout
Layout management is a very complex problem, I don't think people really appreciate just how complex it really is.
No one layout is ever going to achieve everything your want, in most cases, you will need to resort to two or more layouts, especially as your requirements become more complex.
For example, the following is simply a BorderLayout at the base and the buttons on a JPanel using a FlowLayout
Which is achieved by using
JList listOfThings = new JList(...);
JTextField tf = new JTextField();
JButton add = new JButton("Add");
JButton delete = new JButton("Delete");
JButton go = new JButton("Go...");
JPanel buttons = new JPanel();
buttons.add(add);
buttons.add(delete);
buttons.add(go);
add(new BorderLayout());
add(tf, BorderLayout.NORTH);
add(new JScrollPane(listOfThings));
add(buttons, BorderLayout.SOUTH);
For more complex layouts, I would consider using something like GridBagLayout. You may also want to consider MigLayout as an alternative
Take a look at Laying Out Components Within a Container for more details about using layout managers
I'd like to use the combination of BorderLayout and BoxLayout. BorderLayout let me put the component based on their relative location's relation and BoxLayout let me manage the subtle distance ( create some white space). You can use component.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); to achieve this goal too.
Here is a demo and hope it can help you.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class LayoutTest{
private JTextField jTextField;
public void createUI(){
JFrame frame = new JFrame("Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(new TextFieldPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ListPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ButtonPanel());
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
LayoutTest layoutTest = new LayoutTest();
layoutTest.createUI();
}
#SuppressWarnings("serial")
class TextFieldPanel extends JPanel{
public TextFieldPanel(){
setLayout(new BorderLayout());
jTextField = new JTextField();
jTextField.setEditable(false);
add(jTextField,BorderLayout.CENTER);
}
}
#SuppressWarnings("serial")
class ListPanel extends JPanel implements ListSelectionListener{
private JList<String> list;
public ListPanel(){
setLayout(new BorderLayout());
String stringArr[] = new String[30];
for (int i = 0; i < 30; i++) {
stringArr[i] = "JList :This line is item" + i;
}
list = new JList<String>(stringArr);
JScrollPane scrollPane = new JScrollPane(list);
add(scrollPane,BorderLayout.CENTER);
setBackground(new Color(211,211,211));
list.addListSelectionListener(this);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
jTextField.setText(list.getSelectedValue());
}
}
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BorderLayout());
add(button1,BorderLayout.WEST);
add(button2,BorderLayout.CENTER);
add(button3,BorderLayout.EAST);
}
}
}
Here is the effect:
You can use BoxLayout for ButtonPanel if you don't want to let the button's size change.
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(button1);
add(Box.createHorizontalStrut(8));
add(button2);
add(Box.createHorizontalStrut(8));
add(button3);
}
}
And the effect is like this:
For more infomation about using BoxLayout to generate whitespace, you can refer to https://stackoverflow.com/a/22525005/3378204
Try GridBagLayout.
Your sketch is actually quite close to the one of the examples in the official tutorial.
HVLayout keeps the relative size of the components with respect to the size of the window, that is, if you configure components to have a relative size (e.g. buttons usually do not grow or shrink - they stick to their preferred size). This SO question was one of the motivations for me to push HVLayout to a release and a screenshot is included (showing big window size, smalll size and preferred "default" size):
Source code for the window is in RelativeToWindowSize.java
A number of helper-classes from HVLayout are used to build the window, so I don't think it will be of much use here, but to get an impression, the "build window" part shown below:
public RelativeToWindowSize build() {
CSize cs = new CSize();
CForm form = new CForm(new VBox(new Insets(2, 4, 2, 4)), cs);
addTitledBorder(form.get(), "Vertical box", Color.BLACK);
form.add(new JScrollPane(
tfield = new JTextArea("Value that changes with value choosen from list.\nhttp://stackoverflow.com/questions/24462297/layout-relative-to-screensize/")
)).csize().setAreaSize(1.0f, 2.5f).fixedMinHeight().setMaxHeight(4.0f);
// tfield shows mono-spaced font by default.
tfield.setFont(SwingUtils.getUIFont());
form.add(new JScrollPane(vlist = new JList<String>(getListValues())))
.csize().setAreaSize(1.0f, 5.0f);
form.addChild(new HBox());
addTitledBorder(form.get(), "Horizontal box", Color.RED);
form.addChild(new HBox(SwingConstants.CENTER));
addTitledBorder(form.get(), "Centered box.", Color.BLUE);
form.add(createButton(cs, "Add"));
form.add(createButton(cs, "Modify"));
form.up();
form.addChild(new HBox(SwingConstants.TRAILING));
addTitledBorder(form.get(), "Trailing box", Color.GREEN);
form.add(createButton(cs, "Delete"));
setContentPane(form.getRoot());
pack();
setLocationByPlatform(true);
//applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
vlist.addListSelectionListener(this);
log.debug(getClass().getName() + " build.");
return this;
}
private Component createButton(CSize cs, String text) {
// For purpose of demo, let button shrink in width.
return cs.set(new TButton(text)).setFixed().shrinkWidth(0.33f).get();
}
I'm currently trying to fill a JPanel (using GridLayout) with Buttons. These Buttons should be squares having a set width.
The programm should be able to resize the playing field (n*m buttons). Problem is, the buttons are automatically stretched to completely fill the JScrollpane, completely ignoring the set height and width. Thus making the scrollbars unnecessary.
Here is my code:
Creating the panels:
panel_game = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane(panel_game);
Trying to resize the JPanel: (where x and y are the number of buttons and zoomlvl the size)
panel_game.setLayout(new java.awt.GridLayout(x, y));
panel_game.setBounds(panel_game.getX()+5,panel_game.getY()+5,x*zoomlvl-5,y*zoomlvl);
panel_game.setPreferredSize(new Dimension(x*zoomlvl,y*zoomlvl));
And adding the buttons: (f is my playfield, a 2D-Array)(buttons is a Arraylist, containing my buttons)
for(int i=0; i<f.getSize()[0]*f.getSize()[1];i++){
buttons.add(new JButton());
buttons.get(i).setSize(zoomlvl, zoomlvl);
buttons.get(i).setPreferredSize(new Dimension(zoomlvl,zoomlvl));
panel_game.add(buttons.get(i));
}
I have no clue how I can tell Java to stop resizing my buttons etc. automatically.
Help would be appreciated :)
GridLayout is built to fill the container that uses it with components. If the container holding the buttons is constrained in size, then the buttons will stretch or fill to fill that container as closely as possible. A solution may be to nest layout managers so that this does not occur, but I can't give more specific advice without more code, particularly a minimal example program. Images might help too.
If you want to prevent the "button grid panel" from stretching to fill the whole viewport area of the ScrollPane, you could place this grid panel into another panel (with FlowLayout).
In general, you should either
not set the preferred size of the panel_game OR
not set the preferred size of the buttons
because
when you set the preferred size of the buttons, then the preferred size of the panel will be computed from the preferred sizes of the buttons
when you set the preferred size of the panel, then the size of the buttons will be determined by the size of the panel, respectively
Maybe this is what you want to achieve:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollButtonGrid
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int x = 5;
int y = 5;
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(x, y));
for(int i=0; i<x*y;i++){
JButton button = new JButton(String.valueOf(i));
button.setPreferredSize(new Dimension(100,100));
panel.add(button);
}
JPanel container = new JPanel(new FlowLayout(FlowLayout.CENTER, 0,0));
container.add(panel);
JScrollPane scrollPane = new JScrollPane(container);
f.getContentPane().add(scrollPane);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
I wrote this code sample to illustrate a problem I'm having with my program.
I expect to be able to slide the JSplitPane's slider bar to the left, beyond the edge of the buttons, compressing that JPanel, and have the FlowLayout wrap the buttons to a second row.
Instead, the JSplitPane does not allow me to move the slider past the rightmost button on the screen, and if I resize the entire JFrame to force the compression, the buttons (I presume) are just running off the righthand side of the JPanel, underneath the slider bar (I guess, because I obviously cannot see them).
What am I doing wrong?
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class Driver implements Runnable {
public static void main(String[] args) {
(new Driver()).run();
}
public void run() {
try {
go();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
private void go() throws Exception {
JFrame jframe = new JFrame("FlowLayoutTest");
JPanel left = new JPanel();
left.setBackground(Color.RED);
left.setLayout(new BorderLayout());
JPanel right = new JPanel();
right.setBackground(Color.BLUE);
right.setLayout(new BorderLayout());
JSplitPane topmost =
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right);
jframe.setContentPane(topmost);
JPanel bottomleft = new JPanel();
bottomleft.setBackground(Color.GREEN);
bottomleft.setLayout(new FlowLayout());
left.add(bottomleft, BorderLayout.PAGE_END);
for (int i = 0; i < 10; i++) {
bottomleft.add(new JButton("" + i));
}
jframe.pack();
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Is there another layout manager besides FlowLayout that will do what I'm looking for?
Wrap Layout should work.
If you add this
bottomleft.setMinimumSize(new Dimension(0, 0));
before the pack() then it'll reflow. BUT, it won't re-pack the border layout, so instead of two lines you'll get one with the rest cut off. So after a resize you'll have to repack the border layout. If you omit the border layout then it'll reflow like you want.
That said, you should avoid FlowLayout like the plague. Most of the layouts that come with Swing are poor, but FlowLayout is one of the worst offenders.