I'm making 10 stars on JPanel with random location.
But the thing is when i set layout, the starts doesn't show up.
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = frame.getContentPane();
c.setLayout(new BorderLayout());
JPanel northPanel = new JPanel(new FlowLayout());
northPanel.add(new JButton("Open"));
c.add(northPanel, BorderLayout.NORTH);
JPanel southPanel = new JPanel(new FlowLayout());
southPanel.add(new JButton("Integer Input"));
c.add(southPanel, BorderLayout.SOUTH);
JPanel centerPanel = new JPanel(null);
centerPanel.setBackground(Color.pink);
for(int i = 0; i < 10; i++) {
int x = (int) (Math.random() * 300);
int y = (int) (Math.random() * 300);
JLabel label = new JLabel("*");
label.setLocation(x, y);
label.setForeground(Color.green);
label.setOpaque(true);
centerPanel.add(label);
}
c.add(centerPanel, BorderLayout.CENTER);
frame.setVisible(true);
}
in the pink section, it is supposed to be shown 10 stars
I found my own way.
after set label.setSize(10,10);
i could find 10 stars in the panel.
Basically, every container like JPanel, JFrame used some layout to place the component in some specific order. as per your code, you are passing null as argument to centralPanel. so basically central panel has no layout to place component.
Note : Flow Layout is a default layout.
in this case lets try with below steps.
1. please use setBound(x, y, height, width), on the place of setLocation(x, y).
for (int i = 0; i < 10; i++) {
int x = (int) (Math.random() * 300);
int y = (int) (Math.random() * 300);
JLabel label = new JLabel("*");
**label.setBounds(x,y,10,10);**
label.setForeground(Color.green);
label.setOpaque(true);
centerPanel.add(label);
}
[1]: https://i.stack.imgur.com/RUlUI.png
If you want to place 10 chars (*) in random locations I would recommend doing it by custom painting as demonstrated in the following mre:
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
//frame.setSize(300, 300); don't set size let the layout managers do it
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = frame.getContentPane();
//c.setLayout(new BorderLayout()); not needed, it is the default
JPanel northPanel = new JPanel(new FlowLayout()); //FlowLayout is the default
northPanel.add(new JButton("Open"));
c.add(northPanel, BorderLayout.NORTH);
JPanel southPanel = new JPanel(new FlowLayout());
southPanel.add(new JButton("Integer Input"));
c.add(southPanel, BorderLayout.SOUTH);
JPanel centerPanel = new PinkPlanet();
c.add(centerPanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
class PinkPlanet extends JPanel{
private static final int W = 300, H = 300;
private static final String STAR ="*";
private final Dimension pSize = new Dimension(W, H);
private final List<Point> locations = new ArrayList<>();
public PinkPlanet() {
setBackground(Color.pink);
for(int i = 0; i < 10; i++) {
int x = (int) (Math.random() * W);
int y = (int) (Math.random() * H);
locations.add(new Point(x, y));
}
}
#Override
public Dimension getPreferredSize() {
return pSize;
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
for(Point location : locations){
g.drawString(STAR, location.x, location.y);
}
}
}
Related
Similar to JButton showing up in the wrong spot after repaint is called, but the responses to that question only addressed the fact that he wasn't using a layout manager, while I am using a layout manager (poorly), so it didn't really help, unfortunately.
Details
Intent of the Program:
To show a preview of a 1920x1080 grid (scaled down to 640x480 to save space), stretching and shrinking as you change the height of each square, width of each square, and the number of columns it'll have. (You specify a number of total squares to be in the grid first, so the number of rows is inferred by the program.)
Structure:
One top-level JFrame.
Contains two JPanels: the Grid, and the sidebar, using a BorderLayout to snap them to the east and west sides.
Sidebar is one JPanel containing all of the JComponents in a Y-Axis aligned BoxLayout.
Grid extends JComponent, and uses Graphics.drawLine() to draw the grid.
Each component in the sidebar calls Grid.repaint() when changed to update the grid.
Current UI, with the two main JPanels outlined in red.
The Problem
Whenever I change any of the components and thus call Grid.repaint():
The grid doesn't clear, resulting in multiple lines appearing;
All of the sidebar components get painted at the top-left corner, while still showing/functioning on the sidebar;
The grid resizes itself to be wider than normal for some reason.
Current UI, but borked.
What I've Tried
Changing the repaint() region to be a rectangle that only covers the grid,
Checking the documentation for anything about this,
Google,
Asking you guys.
The Code
Reprex: (Simplified to "Press the button to reproduce", while still keeping the essence of the potential problem areas.)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BuildGridGUI2
{
static final int WIDTH_MIN = 100;
static final int WIDTH_MAX = 2000;
static final int WIDTH_INIT = 520;
static final int HEIGHT_MIN = 100;
static final int HEIGHT_MAX = 2000;
static final int HEIGHT_INIT = 300;
int widthOfFrames = 255;
int heightOfFrames = 255;
int numCols = 3;
int numFrames = 1;
private final JComponent makeUI()
{
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
Grid g = new Grid();
JComponent j = makeSideMenu(g);
g.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.red),
g.getBorder()));
j.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.red),
j.getBorder()));
p.add(j, BorderLayout.EAST);
p.add(g, BorderLayout.WEST);
return p;
}
private final JComponent makeSideMenu(Grid grid)
{
JPanel p = new JPanel();
JLabel numColsSelectorLabel = new JLabel("Frames Per Column");
JSpinner numColsSelectorField = new JSpinner();
JLabel widthLabel = new JLabel("Width per Frame (Pixels)");
JSpinner widthSpinner = new JSpinner();
JSlider widthSlider = new JSlider(WIDTH_MIN, WIDTH_MAX, WIDTH_INIT);
JLabel heightLabel = new JLabel("Height per Frame (Pixels)");
JSpinner heightSpinner = new JSpinner();
JSlider heightSlider = new JSlider(BuildGridGUI2.HEIGHT_MIN, BuildGridGUI2.HEIGHT_MAX, BuildGridGUI2.HEIGHT_INIT);
JButton confirmButton = new JButton("Confirm");
numColsSelectorField.setEditor(new JSpinner.NumberEditor(numColsSelectorField));
numColsSelectorField.setMaximumSize(numColsSelectorField.getPreferredSize());
widthSlider.setMajorTickSpacing(300);
widthSlider.setMinorTickSpacing(20);
widthSlider.setPaintTicks(true);
widthSlider.setPaintLabels(true);
widthSpinner.setEditor(new JSpinner.NumberEditor(widthSpinner));
widthSpinner.setPreferredSize(new Dimension(70, 30));
widthSpinner.setMaximumSize(widthSpinner.getPreferredSize());
heightSlider.setMajorTickSpacing(300);
heightSlider.setMinorTickSpacing(20);
heightSlider.setPaintTicks(true);
heightSlider.setPaintLabels(true);
heightSpinner.setEditor(new JSpinner.NumberEditor(heightSpinner));
heightSpinner.setPreferredSize(new Dimension(70, 30));
heightSpinner.setMaximumSize(heightSpinner.getPreferredSize());
confirmButton.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e)
{
widthOfFrames = 200;
grid.refresh();
}
});
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setPreferredSize(new Dimension(300, 480));
p.setSize(new Dimension(300, 480));
numColsSelectorLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
numColsSelectorField.setAlignmentX(Component.CENTER_ALIGNMENT);
widthSlider.setAlignmentX(Component.CENTER_ALIGNMENT);
heightSlider.setAlignmentX(Component.CENTER_ALIGNMENT);
confirmButton.setAlignmentX(Component.CENTER_ALIGNMENT);
widthLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
heightLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
widthSpinner.setAlignmentX(Component.CENTER_ALIGNMENT);
heightSpinner.setAlignmentX(Component.CENTER_ALIGNMENT);
p.add(Box.createRigidArea(new Dimension(300, 30)));
p.add(numColsSelectorLabel);
p.add(Box.createRigidArea(new Dimension(300, 5)));
p.add(numColsSelectorField);
p.add(Box.createRigidArea(new Dimension(300, 25)));
p.add(widthLabel);
p.add(Box.createRigidArea(new Dimension(300, 3)));
p.add(widthSpinner);
p.add(widthSlider);
p.add(Box.createRigidArea(new Dimension(300, 25)));
p.add(heightLabel);
p.add(Box.createRigidArea(new Dimension(300, 3)));
p.add(heightSpinner);
p.add(heightSlider);
p.add(Box.createRigidArea(new Dimension(300, 45)));
p.add(confirmButton);
return p;
}
private static void createAndShowGUI() {
BuildGridGUI2 b = new BuildGridGUI2();
JFrame mainFrame = new JFrame("Grid Builder");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(940, 480);
mainFrame.getContentPane().add(b.makeUI());
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
class Grid extends JComponent
{
static final int CANVAS_WIDTH = 640;
static final int CANVAS_HEIGHT = 480;
private final double conversionRatio = 4.0/9.0; // 1080p scaled down to 480p preview
private int squareHeight, squareWidth, numColumns, numRows;
public Grid()
{
setOpaque(true);
setSize(CANVAS_WIDTH, CANVAS_HEIGHT); // trying to get the size to work properly.
setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
updateVars();
int k;
for (k = 0; k < numColumns; k++)
{
// #param: (x1, y1), (x2, y2)
g.drawLine(k * squareWidth, 0, k * squareWidth, CANVAS_HEIGHT);
}
for (k = 0; k < numRows; k++)
{
g.drawLine(0, k * squareHeight, CANVAS_WIDTH, k * squareHeight);
}
}
public void refresh()
{
// Attempting to set the repaint area to only the grid region
// because CTRL+F is free and parameters are not
repaint(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
}
public void updateVars()
{
this.squareWidth = (int)(
(double)BuildGridGUI2.this.widthOfFrames
*
conversionRatio);
this.squareHeight = (int)(
(double)BuildGridGUI2.this.heightOfFrames
*
conversionRatio);
this.numColumns = BuildGridGUI2.this.numCols;
this.numRows = (int)(
(
(double)BuildGridGUI2.this.numFrames
/
numColumns
)
+ 0.5);
}
}
}
Actual Source Code (Not strictly relevant, but if you're in the mood for code review then I'd love to learn better coding conventions.)
Thank you!
All of the sidebar components get painted at the top-left corner, while still showing/functioning on the sidebar;
JComponent is an abstract class that all Swing components extend from. It has no default painting logic.
Therefore invoking super.paintComponent(...) does not really do anything.
In particular it does not clear the background of the component before doing custom painting. This will result in the painting artifacts that you see.
Any time you extend JComponent your logic should be something something like:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// clear background
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
// do custom painting
g.setColor( getForeground() );
...
}
Note: this is the reason the many people override JPanel for simple custom painting as mentioned by Abra. The paintComponent(...) method of the JPanel will clear the background by default.
I made a few changes to the code you posted.
I changed class Grid such that it extends JPanel and not JComponent, since custom painting is usually done on a JPanel.
I added a instance member variable grid with type Grid, to class BuildGridGUI2 rather than creating one and sending it as a parameter to method makeSideMenu.
Here is your code with my modifications (and my preferred coding style). It simply solves your reported problem and nothing more.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BuildGridGUI2 {
static final int WIDTH_MIN = 100;
static final int WIDTH_MAX = 2000;
static final int WIDTH_INIT = 520;
static final int HEIGHT_MIN = 100;
static final int HEIGHT_MAX = 2000;
static final int HEIGHT_INIT = 300;
int widthOfFrames = 255;
int heightOfFrames = 255;
int numCols = 3;
int numFrames = 1;
Grid grid;
private final JComponent makeUI() {
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
grid = new Grid();
JComponent j = makeSideMenu();
grid.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.red),
grid.getBorder()));
j.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.red),
j.getBorder()));
p.add(j, BorderLayout.EAST);
p.add(grid, BorderLayout.WEST);
return p;
}
private final JComponent makeSideMenu() {
JPanel p = new JPanel();
JLabel numColsSelectorLabel = new JLabel("Frames Per Column");
JSpinner numColsSelectorField = new JSpinner();
JLabel widthLabel = new JLabel("Width per Frame (Pixels)");
JSpinner widthSpinner = new JSpinner();
JSlider widthSlider = new JSlider(WIDTH_MIN, WIDTH_MAX, WIDTH_INIT);
JLabel heightLabel = new JLabel("Height per Frame (Pixels)");
JSpinner heightSpinner = new JSpinner();
JSlider heightSlider = new JSlider(BuildGridGUI2.HEIGHT_MIN,
BuildGridGUI2.HEIGHT_MAX,
BuildGridGUI2.HEIGHT_INIT);
JButton confirmButton = new JButton("Confirm");
numColsSelectorField.setEditor(new JSpinner.NumberEditor(numColsSelectorField));
numColsSelectorField.setMaximumSize(numColsSelectorField.getPreferredSize());
widthSlider.setMajorTickSpacing(300);
widthSlider.setMinorTickSpacing(20);
widthSlider.setPaintTicks(true);
widthSlider.setPaintLabels(true);
widthSpinner.setEditor(new JSpinner.NumberEditor(widthSpinner));
widthSpinner.setPreferredSize(new Dimension(70, 30));
widthSpinner.setMaximumSize(widthSpinner.getPreferredSize());
heightSlider.setMajorTickSpacing(300);
heightSlider.setMinorTickSpacing(20);
heightSlider.setPaintTicks(true);
heightSlider.setPaintLabels(true);
heightSpinner.setEditor(new JSpinner.NumberEditor(heightSpinner));
heightSpinner.setPreferredSize(new Dimension(70, 30));
heightSpinner.setMaximumSize(heightSpinner.getPreferredSize());
confirmButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
widthOfFrames = 200;
grid.refresh();
}
});
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setPreferredSize(new Dimension(300, 480));
p.setSize(new Dimension(300, 480));
numColsSelectorLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
numColsSelectorField.setAlignmentX(Component.CENTER_ALIGNMENT);
widthSlider.setAlignmentX(Component.CENTER_ALIGNMENT);
heightSlider.setAlignmentX(Component.CENTER_ALIGNMENT);
confirmButton.setAlignmentX(Component.CENTER_ALIGNMENT);
widthLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
heightLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
widthSpinner.setAlignmentX(Component.CENTER_ALIGNMENT);
heightSpinner.setAlignmentX(Component.CENTER_ALIGNMENT);
p.add(Box.createRigidArea(new Dimension(300, 30)));
p.add(numColsSelectorLabel);
p.add(Box.createRigidArea(new Dimension(300, 5)));
p.add(numColsSelectorField);
p.add(Box.createRigidArea(new Dimension(300, 25)));
p.add(widthLabel);
p.add(Box.createRigidArea(new Dimension(300, 3)));
p.add(widthSpinner);
p.add(widthSlider);
p.add(Box.createRigidArea(new Dimension(300, 25)));
p.add(heightLabel);
p.add(Box.createRigidArea(new Dimension(300, 3)));
p.add(heightSpinner);
p.add(heightSlider);
p.add(Box.createRigidArea(new Dimension(300, 45)));
p.add(confirmButton);
return p;
}
private static void createAndShowGUI() {
BuildGridGUI2 b = new BuildGridGUI2();
JFrame mainFrame = new JFrame("Grid Builder");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(940, 480);
mainFrame.getContentPane().add(b.makeUI());
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
class Grid extends JPanel {
static final int CANVAS_WIDTH = 640;
static final int CANVAS_HEIGHT = 480;
private final double conversionRatio = 4.0 / 9.0; // 1080p scaled down to 480p preview
private int squareHeight, squareWidth, numColumns, numRows;
public Grid() {
setOpaque(true);
setSize(CANVAS_WIDTH, CANVAS_HEIGHT); // trying to get the size to work properly.
setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
updateVars();
int k;
for (k = 0; k < numColumns; k++) {
// #param: (x1, y1), (x2, y2)
g.drawLine(k * squareWidth, 0, k * squareWidth, CANVAS_HEIGHT);
}
for (k = 0; k < numRows; k++) {
g.drawLine(0, k * squareHeight, CANVAS_WIDTH, k * squareHeight);
}
}
public void refresh() {
// Attempting to set the repaint area to only the grid region
// because CTRL+F is free and parameters are not
repaint(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
}
public void updateVars() {
this.squareWidth = (int) ((double) BuildGridGUI2.this.widthOfFrames * conversionRatio);
this.squareHeight = (int) ((double) BuildGridGUI2.this.heightOfFrames * conversionRatio);
this.numColumns = BuildGridGUI2.this.numCols;
this.numRows = (int) (((double) BuildGridGUI2.this.numFrames / numColumns) + 0.5);
}
}
}
One tip: Try to use specific sub-classes of JComponent rather than JComponent. For example, I suggest changing the return type of method makeSideMenu() to JPanel rather than JComponent since that method actually returns a JPanel.
Im adding an array of JPanels inside a JScrollPane. The array of JPanels are being added to the JScrollPane but the scroll bars just wont show.
public class MyFrame extends JFrame {
private JPanel contentPane;
private JPanel panel_1;
private JScrollPane scrollPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MyFrame frame = new MyFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MyFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 288, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
panel_1 = new JPanel();
panel_1.setBounds(10, 114, 434, 136);
panel_1.setLayout(null);
scrollPane = new JScrollPane(panel_1);
scrollPane.setBounds(52, 57, 164, 126);
scrollPane.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Histogram", TitledBorder.LEADING, TitledBorder.TOP, null, Color.BLUE));
scrollPane.setLayout(new ScrollPaneLayout());
contentPane.add(scrollPane);
buildBar();
}
JPanel[] barPanel;
private void buildBar(){
int x=0,y=22,w=100,h=80,s=10,n=3;
barPanel = new JPanel[n];
for(int i=0; i<n; i++){
barPanel[i] = new JPanel();
barPanel[i].setBounds(x, y, w, h);
barPanel[i].setBackground(new Color(255,0,0));
panel_1.add(barPanel[i]);
panel_1.revalidate();
panel_1.repaint();
x = x + w + s;
}
}
}
I have been working on it for hours . Maybe there is something that I've missed out.
You're shooting yourself in the foot with these two lines:
panel_1.setBounds(10, 114, 434, 136);
panel_1.setLayout(null);
Both of which will mess up the JScrollPane's ability to use and display scrollbars. What you need to do is: not to use setBounds but rather have the components use their preferredSize, and avoid using null layout, since this won't change the container's preferredSize.
Yet another reason to studiously avoid null layouts.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class MyPanel2 extends JPanel {
private static final int PREF_W = 388;
private static final int PREF_H = PREF_W;
public static final int INNER_PREF_W = 434;
public static final int INNER_PREF_H = 126;
private static final int HISTO_PANEL_COUNT = 6;
private static final Dimension VP_SZ = new Dimension(164, 126);
private JPanel holderPanel = new JPanel(new GridLayout(0, 1));
public MyPanel2() {
int w = INNER_PREF_W;
int h = INNER_PREF_H;
for (int i = 0; i < HISTO_PANEL_COUNT; i++) {
holderPanel.add(new InnerPanel(w, h));
}
JScrollPane scrollPane = new JScrollPane(holderPanel);
scrollPane.getViewport().setPreferredSize(VP_SZ);
setLayout(new GridBagLayout());
add(scrollPane);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class InnerPanel extends JPanel {
private int w;
private int h;
public InnerPanel(int w, int h) {
this.w = w;
this.h = h;
setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 0, y = 22, w = 100, h = 80, s = 10, n = 3;
g.setColor(Color.RED);
for (int i = 0; i < n; i++) {
g.fillRect(x, y, w, h);
x = x + w + s;
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(w, h);
}
}
private static void createAndShowGui() {
MyPanel2 mainPanel = new MyPanel2();
JFrame frame = new JFrame("MyPanel2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
JScrollPane relies on the preferredSize of your container to determine the scroll bar width. If you use a Layout, the preferredSize will be determined for you when components are added to the panel.
However, when you use:
contentPane.setLayout(null);
You are preventing the preferredSize from changing based on added components.
Try to use a layout which is applicable for your case.
In case you are very certain you do not want to use a Layout, in order to see the scroll bar, you may set the preferredSize of the container for every components you added by manually adjusting the preferredSize. That way, the scrollbar will still extend with newly added components.
I have a JPanel (cardLayoutPanel) which layout is CardLayout.
I also have another 3 different panels (firstPagePanel, secondPagePanel, thirdPagePanel)
firstPagePanel size is approximately around 450x400,
secondPagePanel size is approximately around 800x600
thirdPagePanel size is approximately around 1024x768
I cardLayoutPanel.add all 3 panels and I show firstPagePanel first as my view.
I want to let my program displayed the size of firstPagePanel first which is 450x400
and then if secondPagePanel is displayed, it will change the size to 800x600 and if thirdPagePanel is displayed,it will change the size to 1024,768
Instead of guessing what my 3 panel size should be, I used frame.getPreferredSize() but my first view will always take in the size of my thirdPagePanel which is 1024x768 instead of 450x400;
What can I do to resolve this issue?
public class MainFrame {
private CardLayout cardLayout = new CardLayout();
private JPanel cardLayoutPanel = new JPanel();
private FirstPagePanel firstPagePanel = new FirstPagePanel();
private SecondPagePanel secondPagePanel = new SecondPagePanel();
private ThirdPagePanel thirdPagePanel = new ThirdPagePanel();
private JFrame frame = new JFrame("Panel size test");
public MainFrame() {
cardLayoutPanel.setLayout(cardLayout);
cardLayoutPanel.add(firstPagePanel,"1");
cardLayoutPanel.add(secondPagePanel,"2");
cardLayoutPanel.add(thirdPagePanel,"3");
cardLayout.show(cardLayoutPanel,"1");
frame.add(cardLayoutPanel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.getPreferredSize();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
}
}
The easiest way is to:
Remove the current panel.
Add the new panel.
Pack the top level container.
E.G.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ThreeSizeGui {
public static void swapComponentsAndResizeUI(
JComponent ui,
JComponent current,
JComponent next) {
ui.remove(current);
ui.add(next);
current = next;
Component c = ui.getTopLevelAncestor();
if (c instanceof Window) {
Window w = (Window) c;
w.pack();
}
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
final JPanel ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(6, 6, 6, 6));
JPanel controls = new JPanel(
new FlowLayout(FlowLayout.LEADING));
ui.add(controls, BorderLayout.PAGE_START);
int s = 100;
Dimension[] sizes = {
new Dimension(s * 4, s * 2),
new Dimension(s * 6, s * 3),
new Dimension(s * 8, s * 4)
};
final JComboBox cb = new JComboBox(sizes);
controls.add(cb);
final JPanel[] panels = new JPanel[sizes.length];
for (int ii = 0; ii < sizes.length; ii++) {
Dimension d = sizes[ii];
BufferedImage bi = new BufferedImage(
d.width, d.height, BufferedImage.TYPE_INT_RGB);
JPanel p = new JPanel(new GridLayout());
JLabel l = new JLabel(new ImageIcon(bi));
p.add(l);
panels[ii] = p;
}
ItemListener sizeListener = new ItemListener() {
JPanel current = panels[0];
#Override
public void itemStateChanged(ItemEvent e) {
JPanel next = panels[cb.getSelectedIndex()];
swapComponentsAndResizeUI(ui, current, next);
current = next;
}
};
cb.addItemListener(sizeListener);
ui.add(panels[0], BorderLayout.CENTER);
JFrame f = new JFrame("Three Sized Panels");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(ui);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
I am working on a project where I have to create an image manager program in Java. The program will have the following features in it: Program should take image from the user as input. Then it should display the image in panel(1), and in panel(2) it should give the user an options of changing width, height, hgap, vgap, top margin and left margin of the image with an 'OK' button at the end including an 'action listener' feature. Using the above mentioned features we will get the grids on the image. Now if the user clicks on the particular grid then that particular image should get extracted into a folder.
I am attaching the program which we have done so far.
The difficulties we are facing are: we are not able to insert a JScrollPane for the image. As well as we are unaware of how to add action listeners to the grids so that we can extract that particular image.
package project_image_manager_imp_files;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
class SidePanel1 extends JPanel implements ActionListener {
JTextField top_margin = new JTextField(10);
JTextField left_margin = new JTextField(10);
JTextField Width = new JTextField(10);
JTextField Height = new JTextField(10);
JTextField Vgap = new JTextField(10);
JTextField Hgap = new JTextField(10);
JLabel j1 = new JLabel("Top margin");
JLabel j2 = new JLabel("Left margin");
JLabel j3 = new JLabel("Width");
JLabel j4 = new JLabel("Height");
JLabel j5 = new JLabel("Vertical gap");
JLabel j6 = new JLabel("Horizontal gap");
JButton b = new JButton("OK");
public SidePanel1() {
this.setBackground(Color.black);
Dimension d1 = new Dimension(1000, 1000);
this.setMaximumSize(d1);
this.setPreferredSize(d1);
JPanel p = new JPanel();
JScrollPane vertical = new JScrollPane();
vertical.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(vertical);
vertical.setVerticalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(vertical);
//showCoo.build(c);
//c.add(p);
//p.setOpaque(false);
//t1.addActionListener(new JTextFieldEventClass() );
//b.addActionListener(new JTextFieldEventClass() );
// String s=t3.getText();
//int c=Integer.parseInt(s);
p.add(j1);
p.add(top_margin);
p.add(j2);
p.add(left_margin);
p.add(j3);
p.add(Width);
p.add(j4);
p.add(Height);
p.add(j5);
p.add(Vgap);
p.add(j6);
p.add(Hgap);
p.add(b);
p.setLayout(new GridLayout(7, 2));
b.addActionListener(this);
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(1, 2));
frame.setBounds(200, 200, 600, 400);
frame.setTitle("Hello World Test");
frame.setResizable(true);
//frame.setSize (500, 300);
Container c = frame.getContentPane();
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.WEST);
frame.add(p, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setResizable(true);
}
int height;
int width;
int hgap;
int vgap;
int tm;
int lm;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(Toolkit.getDefaultToolkit().getImage("images1.jpg"), 0, 0, this);
Graphics2D g2d = (Graphics2D) g.create();
//File f=new File("images1.jpg");
//BufferedImage im=ImageIO.read(f);
int frame_width = getWidth();
int frame_height = getHeight();
for (int j = 0; j < frame_height; j++) {
int y = tm + (height * j) + (vgap * j);
for (int i = 0; i < frame_width; i++) {
int x = lm + (width * i) + (hgap * i);
g.drawRect(x, y, width, height);
}
}
}
public static void main(String[] argv) {
//static JScrollBar scrollbar;
SidePanel1 panel = new SidePanel1();
panel.setLayout(new FlowLayout());
//scrollbar = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//panel.add(scrollbar);
try {
while (true) {
Thread.sleep(100);
///.out.println("("+MouseInfo.getPointerInfo().getLocation().x+", "+MouseInfo.getPointerInfo().getLocation().y+")");
}
} catch (InterruptedException e) {}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
width = Integer.parseInt(Width.getText());
height = Integer.parseInt(Height.getText());
hgap = Integer.parseInt(Hgap.getText());
vgap = Integer.parseInt(Vgap.getText());
lm = Integer.parseInt(left_margin.getText());
tm = Integer.parseInt(top_margin.getText());
repaint();
}
}
I am using Swing and AWT (for the listeners) to make a small program. I have a problem concerning getting the size of my JPanel (the class named Chess).
My Layout:
public class Main extends JFrame implements MouseListener, ActionListener{
Chess chessPanel = new Chess ();
JButton newGameButton = new JButton ("New Game");
JButton loadGameButton = new JButton ("Load Game");
JButton saveGameButton = new JButton ("Save Game");
JButton exitButton = new JButton ("Exit");
public static void main (String [] args) {
new Main();
}
Main () {
super ("Chess");
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setSize(dim);
setLocation(0,0);
setUndecorated(true);
chessPanel.addMouseListener(this);
add(chessPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
newGameButton.addActionListener(this);
loadGameButton.addActionListener(this);
saveGameButton.addActionListener(this);
exitButton.addActionListener(this);
buttonPanel.add(newGameButton);
buttonPanel.add(loadGameButton);
buttonPanel.add(saveGameButton);
buttonPanel.add(exitButton);
add(buttonPanel, BorderLayout.SOUTH);
setVisible(true);
}
// ... Code ...
}
As you can see by the code, I have one JPanel in the CENTER, which takes nearly all the screen. In the bottom I have another JPanel (SOUTH), which has a row of buttons.
What I need is the size that the JPanel in the CENTER takes. When I call the getWidth(), getHeight() or getBounds() methods inherited from JPanel, they all return 0, because of the BorderLayout.
Any idea how to get the real values?
PS: The screen always takes up the entire screen, and will never be resized, if that helps.
You're likely calling getWidth before the JPanel has been rendered, and so it will be 0. The solution is to get the size after rendering, for instance after pack() or setVisible(true) has been called on the root container that holds this JPanel.
Also, I recommend against calling setSize() on anything since most of the standard layout managers observe the preferred size of a component, not the size, and when you call pack() telling the layout managers to do their thing, the set sizes are usually ignored. You may want to make your JPanel that is in the center set its own size by overriding its setPreferredSize method if it needs to be a certain size. Then let the JFrame and its held containers set the bet fit size based on the their layout managers when you call pack.
e.g.,
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
Chess chessPanel = new Chess();
JButton newGameButton = new JButton("New Game");
JButton loadGameButton = new JButton("Load Game");
JButton saveGameButton = new JButton("Save Game");
JButton exitButton = new JButton("Exit");
public static void main(String[] args) {
new Main();
}
Main() {
super("Chess");
add(chessPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(newGameButton);
buttonPanel.add(loadGameButton);
buttonPanel.add(saveGameButton);
buttonPanel.add(exitButton);
System.out.printf("chessPanel Size before rendering: %s%n", chessPanel.getSize());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(buttonPanel, BorderLayout.SOUTH);
pack();
System.out.printf("chessPanel Size after rendering: %s%n", chessPanel.getSize());
setLocationRelativeTo(null);
setVisible(true);
}
// ... Code ...
}
#SuppressWarnings("serial")
class Chess extends JPanel {
private static final int CHESS_WIDTH = 600;
private static final int CHESS_HEIGHT = CHESS_WIDTH;
private static final int MAX_ROW = 8;
private static final int MAX_COL = 8;
private static final Color LIGHT_COLOR = new Color(240, 190, 40);
private static final Color DARK_COLOR = new Color(180, 50, 0);
#Override
public Dimension getPreferredSize() {
return new Dimension(CHESS_WIDTH, CHESS_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int panelWidth = getWidth();
int panelHeight = getHeight();
int sqrWidth = panelWidth / MAX_ROW;
int sqrHeight = panelHeight / MAX_COL;
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
Color c = (row % 2 == col % 2) ? LIGHT_COLOR : DARK_COLOR;
g.setColor(c);
int x = (row * panelWidth) / MAX_ROW;
int y = (col * panelHeight) / MAX_COL;
g.fillRect(x, y, sqrWidth, sqrHeight);
}
}
}
}