JScrollPane won't work - java

Hey guys I wanted to create a JScrollPane but it won't work... and I don't know why... here's my code...
public class test extends JFrame{
public test(){
setSize(1000,600);
}
private static JButton[] remove;
private static JPanel p = new JPanel();
public static void main(String[]args){
p.setLayout(null);
JFrame t=new test();
remove = new JButton[25];
for(int i=0;i<25;i++){
remove[i]=new JButton("Remove");
remove[i].setBounds(243,92+35*i,85,25);
p.add(remove[i]);
}
JScrollPane scrollPane = new JScrollPane(p);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
t.add(scrollPane);
t.setVisible(true);
}
Umm and Im pretty sure the frame isn't big enough for these 25 buttons... But if i delete that p.setLayout(null); A horizontal scroll bar will be created automatically... I don't really know what is wrong with my code... Pls help thank you very much!

You need to set p's preferredSize for this to work.
p.setPreferredSize(new Dimension(800, 2000));
Or you could have p extend JPanel and then override the getPreferredSize() method to return the proper dimension.
And I agree -- get rid of your null layouts. Learn about and use the layout managers if you want to use Swing correctly and have robust Swing GUI's.
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Foo extends JFrame {
private static final int BUTTON_COUNT = 25;
public static void main(String[] args) {
JPanel btnPanel = new JPanel(new GridLayout(0, 1, 0, 20));
btnPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
AbstractAction removeAction = new AbstractAction("Remove") {
#Override
public void actionPerformed(ActionEvent evt) {
JButton src = (JButton) evt.getSource();
JPanel container = (JPanel) src.getParent();
container.remove(src);
container.revalidate();
container.repaint();
}
};
for (int i = 0; i < BUTTON_COUNT; i++) {
JButton removeBtn = new JButton(removeAction);
btnPanel.add(removeBtn);
}
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.add(btnPanel, BorderLayout.NORTH);
JScrollPane scrollpane = new JScrollPane(borderPanel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setPreferredSize(new Dimension(400, 800));
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

The issue is that a scroll pane checks the component inside it for a "preferred size" so a pane with a null layout has a preferred size of (0,0). Which it ignores.
You should do something along the lines of:
p.setPreferredSize(1000,600);
And you should see some scroll bars appear, I'm not sure how accurate they will be though.

Related

Java Swing 13 GridLayout does not exist?

I can't seem to get a swing GridLayout to work in java 13. The error is that GridLayout cannot be resolved to a type in the following code:
import javax.swing.*;
public class GameFrame extends JFrame {
public static final void NewFrame() {
new GameFrame();
}
public GameFrame() {
this.setSize(1600, 800);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("The Game");
this.setVisible(true);
this.setResizable(false);
JPanel MainPanel = new JPanel();
MainPanel.setLayout(new GridLayout());
}
}
The issue is caused by the class not being imported.
import java.awt.GridLayout;
Since it is not in the swing package it doesn't get imported with the star import.
Also it is better to use explicit imports.
This might be related to the fact that panel is empty. Try running this code and it should work.
public class GridLayoutTest {
private static JButton[] arrayBtn;
public static void main(String[] args) {
// the frame that contains the components
JFrame frame = new JFrame("GridLayoutTest from JCG");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set the size of the frame
frame.setSize(350, 350);
// set the rows and cols of the grid, as well the distances between them
GridLayout grid = new GridLayout(5, 3, 10, 10);
// what layout we want to use for our frame
frame.setLayout(grid);
// add a text field with a specified text to the frame
JTextArea text = new JTextArea();
text.setText("Result");
text.setEditable(false);
frame.add(text);
// add buttons to the frame
frame.add(new JButton("+"));
frame.add(new JButton("="));
arrayBtn = new JButton[10];
// add JButtons dynamically
for(int i=0; i < arrayBtn.length; i++) {
arrayBtn[i] = new JButton(Integer.toString(i));
frame.add(arrayBtn[i]);
}
frame.setVisible(true);
}
}

How can I properly adjust the size and location of a button in JFrame?

I am attempting to make a PC Application using Java and JFrame. I'm trying to format 2 transparent buttons, each sized half of the full screen shown (vertically). The top half of the screen will hold to option to debate someone and the bottom half of the screen will hold the option to spectate a debate if clicked on. Here is what I have so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class BackgroundImageJFrame extends JFrame {
JButton b1;
JButton b2;
JPanel j1;
JPanel j2;
public BackgroundImageJFrame() {
setTitle("Background Color for JFrame");
setSize(340,563);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
/*
One way
-----------------
setLayout(new BorderLayout());
JLabel background=new JLabel(new ImageIcon("C:\\Users\\Computer\\Downloads\\colorful design.png"));
add(background);
background.setLayout(new FlowLayout());
l1=new JLabel("Here is a button");
b1=new JButton("I am a button");
background.add(l1);
background.add(b1);
*/
// Another way
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("C:\\Users\\MLH-User\\Downloads\\Front.jpg")));
setLayout(new FlowLayout());
j1 = new JPanel();
j1.setLayout(null);
b1 = new JButton("Spectate");
//b1.setBounds(0,0,50,50);
b1.setOpaque(false);
b1.setContentAreaFilled(false);
b1.setBorderPainted(false);
j1.add(b1);
b2 = new JButton("Debate");
b2.setLocation(0,0);
b2.setOpaque(false);
b2.setContentAreaFilled(false);
b2.setBorderPainted(false);
j1.add(b2);
add(j1);
// Just for refresh :) Not optional!
setSize(339,562);
setSize(340,563);
}
public static void main(String args[]) {
new BackgroundImageJFrame();
}
}
This is some stuff I experimented with so far, can anyone help me out about where I went wrong?
You should use a layout manager. Here is an example with GridLayout:
public class Example extends JFrame {
private static final int SIZE = 300;
public Example() {
setLayout(new GridLayout(2, 1, 0, 5));
getContentPane().setBackground(Color.WHITE);
JButton debate = new JButton("DEBATE") {
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
};
Font font = debate.getFont().deriveFont(30f);
debate.setFont(font);
// debate.setBorderPainted(false);
debate.setBackground(Color.BLUE.brighter());
debate.setForeground(Color.WHITE);
JButton spectate = new JButton("SPECTATE") {
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
};
spectate.setFont(font);
// spectate.setBorderPainted(false);
spectate.setBackground(Color.RED.brighter());
spectate.setForeground(Color.WHITE);
add(debate);
add(spectate);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new Example());
}
}
Notes:
You have to realize that screen sizes vary. Setting SIZE to 300 was an arbitrary choice for presentation, screens might not have the required size. You can also set the insets or an empty border instead of specifying the size of the component directly.
You can consider creating a class for these buttons if you have more of them.
This is an example of setting the sizes. I don't know about the location part though.
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(4,4,4,4));
for(int i=0 ; i<16 ; i++){
JButton btn = new JButton(String.valueOf(i));
btn.setPreferredSize(new Dimension(40, 40));
panel.add(btn);
}
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);

How to align JPanel in java

I have a JPanel which is in a box layout but I am unsure how to align the JPanel to center of the window (and stay centered even if window is resized) I've tried looking for a solution but all questions seem over complicated compared to what it is that I'm looking for.
import java.awt.*;
import javax.swing.*;
public class Stacker extends JFrame {
public Stacker() {
super("Stacker");
setSize(430, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create top panel
JPanel commandPane = new JPanel();
BoxLayout vertical = new BoxLayout(commandPane,
BoxLayout.Y_AXIS);
commandPane.setLayout(vertical);
JButton subscribe = new JButton("Subscribe");
JButton unsubscribe = new JButton("Unsubscribe");
JButton refresh = new JButton("Refresh");
JButton save = new JButton("Save");
commandPane.add(subscribe);
commandPane.add(unsubscribe);
commandPane.add(refresh);
commandPane.add(save);
JMenuItem j1 = new JMenuItem("File");
JMenuItem j2 = new JMenuItem("Open");
JMenuItem j3 = new JMenuItem("Close");
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu("Feeds");
menu.add(j1);
menu.add(j2);
menu.add(j3);
menubar.add(menu);
setJMenuBar(menubar);
// create bottom panel
/*JPanel textPane = new JPanel();
JTextArea text = new JTextArea(4, 70);
JScrollPane scrollPane = new JScrollPane(text);
// put them together
FlowLayout flow = new FlowLayout();
setLayout(flow);
add(commandPane);
add(scrollPane); */
setJMenuBar(menubar);
add(commandPane);
setVisible(true);
}
public static void main(String[] arguments) {
Stacker st = new Stacker();
}
}
You say you're using a BoxLayout, but is the JPanel with the BoxLayout the JPanel you want to center, or does it contain the JPanel you want to center?
If it contains the JPanel you want to center, then you can add a glue on either side of the JPanel to be centered. If it is the JPanel you want to center, then you can use GridBagLayout or BoxLayout to achieve the effect you're talking about.
Googling something like "Java center component" will give you a ton of results.
for this idea (still not clear from your description) use GridBagLayout without set for GridBagConstraints
.
.
.
import java.awt.*;
import javax.swing.*;
public class CenteredJPanel {
private JFrame frame = new JFrame("Test");
private JPanel panel = new JPanel();
private JButton subscribe = new JButton("Subscribe");
private JButton unsubscribe = new JButton("Unsubscribe");
private JButton refresh = new JButton("Refresh");
private JButton save = new JButton("Save");
public CenteredJPanel() {
panel.setLayout(new GridBagLayout());
panel.add(subscribe);
panel.add(unsubscribe);
panel.add(refresh);
panel.add(save);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CenteredJPanel centeredJLabel = new CenteredJPanel();
}
});
}
}

Keep BoxLayout From Expanding Children

I want to stack some JComponents vertically inside a JPanel so they stack at the top and any extra space is at the bottom. I'm using a BoxLayout. The components will each contain a JTextArea that should allow the text to wrap if necessary. So, basically, I want the height of each of these components to be the minimum necessary for displaying the (possibly wrapped) text.
Here's a contained code example of what I'm doing:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args){
new TextAreaTester();
}
public TextAreaTester(){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.PAGE_AXIS));
panel.setPreferredSize(new Dimension(100,400));
for(int i = 0; i<3; i++){
JPanel item = new JPanel(new BorderLayout());
JTextArea textarea = new JTextArea("this is a line of text I want to wrap if necessary");
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
textarea.setMaximumSize( textarea.getPreferredSize() );
item.add(textarea,BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
frame.add(panel);
frame.setVisible(true);
frame.pack();
}
}
The child JPanels are expanding to fill the vertical space. I tried using glue because I thought that's what glue was for, but it seems to do nothing at all. Any help?
Note: I have found questions that look almost identical, but none with answers I can apply.
One solution: nest JPanels with the outer JPanel using Borderlayout and adding the BoxLayout using JPanel to this one BorderLayout.NORTH, also known as BorderLayout.PAGE_START:
Edit for Kleopatra:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args) {
new TextAreaTester();
}
public TextAreaTester() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
// panel.setPreferredSize(new Dimension(100,400));
for (int i = 0; i < 3; i++) {
JPanel item = new JPanel(new BorderLayout());
// item.setLayout(new BoxLayout(item,BoxLayout.LINE_AXIS));
JTextArea textarea = new JTextArea(
"this is a line of text I want to wrap if necessary", 3, 35);
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
// textarea.setMaximumSize(textarea.getPreferredSize());
// item.setMaximumSize( item.getPreferredSize() );
item.add(new JScrollPane(textarea), BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
JPanel mainPanel = new JPanel(new BorderLayout()) {
private final int prefW = 100;
private final int prefH = 400;
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
};
// mainPanel.setPreferredSize(new Dimension(100, 400));
mainPanel.add(panel, BorderLayout.PAGE_START);
frame.add(mainPanel);
frame.setVisible(true);
// frame.getContentPane().add(jp);
frame.pack();
}
}
Alternatively, you can use Box.Filler. Just replace your call to panel.add(Box.createGlue()) with
panel.add(new Box.Filler(new Dimension(0, 0),
new Dimension(0, Short.MAX_VALUE),
new Dimension(0, Short.MAX_VALUE)));
If you want to achieve the same for a horizontal layout, just use Short.MAX_VALUE for width instead of height in the Dimension call.

Items not Appearing in New Frame in Java

I'm building a JFrame that will eventually display the output of a program that has a variable number of sections in it. I have parsed the output but displaying it in the frame is a problem.
When the frame appears, it is completely empty with the exception of the scroll pane. How do I get these labels to show up?
public class OutputPanel extends JFrame {
public OutputPanel(Vector parsedOutput) {
this.setTitle("Output");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
Iterator<Vector> outputIter = parsedOutput.iterator();
while(outputIter.hasNext()) {
Vector section = outputIter.next();
JLabel sectionLabel = new JLabel((String)section.get(0));
System.out.println((String)section.get(0));
scrollPane.add(sectionLabel);
}
this.add(scrollPane);
this.pack();
this.setVisible(true);
}
}
You shouldn't add components to the scrollPane
scrollPane.add(sectionLabel);
but rather add them to a separate panel, and either use
scrollPane = new JScrollPane(thePanel);
or
scrollPane.setViewportView(thePanel);
Example:
import java.awt.GridLayout;
import java.util.Vector;
import javax.swing.*;
class Test {
public static void main(String[] args) {
new OutputPanel(null);
}
}
class OutputPanel extends JFrame {
public OutputPanel(Vector parsedOutput) {
this.setTitle("Output");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel content = new JPanel(new GridLayout(0, 1));
for (int i = 0; i < 100; i++) {
JLabel sectionLabel = new JLabel("hello " + i);
content.add(sectionLabel);
}
JScrollPane scrollPane = new JScrollPane(content);
this.add(scrollPane);
this.pack();
this.setVisible(true);
}
}
Produces:
You should use setViewPortView() with a container instead of add() for JScrollPane.
Try this.
public class OutputPanel extends JFrame {
public OutputPanel(Vector parsedOutput) {
this.setTitle("Output");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
Iterator<Vector> outputIter = parsedOutput.iterator();
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
scrollPane.setViewportView(panel);
while(outputIter.hasNext()) {
Vector section = outputIter.next();
JLabel sectionLabel = new JLabel((String)section.get(0));
System.out.println((String)section.get(0));
panel.add(sectionLabel);
}
this.add(scrollPane);
this.pack();
this.setVisible(true);
}
}

Categories