I am in the process of creating a calendar component in Swing, and am running into some trouble.
I want the component to be able to be able to change amount of columns for different views, but that seems simple enough with GridBagLayout.
The problem is getting GBL to show a grid with row and columns that could be empty. I have tried, but can't get it to do that. What is a way to do this, or another simple method to end up being able to place panels on certain places on a grid, such as this:
I have a class called PanelCalendarWeek that extends JPanel. Some of the code is omitted for brevity. The code is below, and the following link is a picture of its output.
public PanelCalendarWeek() {
/* This panel holds the date */
innerPanel = new JPanel();
innerPanel.setBackground(Color.BLACK);
innerPanel.setBounds(0, 0, 700, 700);
innerPanel.setPreferredSize(new Dimension(700, 700));
innerPanel.setLayout(new GridBagLayout());
/* Create Grid bag containts for the BLACK area */
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.PAGE_END;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 0;
c.gridy = 0;
/* Add example panels that would be dates */
JPanel panel1 = new JPanel();
panel1.setBorder(BorderFactory.createLineBorder(Color.WHITE, 2));
panel1.setPreferredSize(new Dimension(1, 200));
panel1.setBackground(Color.BLUE);
innerPanel.add(panel1, c);
/* Create more components in the manner above for example reasons */
this.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent e) {
innerPanel.setBounds(0, 0, columnView.getWidth(), 1000);
innerPanel.setPreferredSize(new Dimension(columnView.getWidth(), 1000));
} // more code omitted for brevitu
});
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.getViewport().setLayout(null);
scrollPane.setViewportView(innerPanel);
scrollPane.setBounds(0, 0, 400, 400);
columnView = new JPanel();
columnView.setBackground(Color.RED);
columnView.setBounds(0, 0, 200, 50);
columnView.setPreferredSize(new Dimension(200, 50));
scrollPane.setColumnHeaderView(columnView);
rowView = new JPanel(); /* omitted, same process as above */
this.setLayout(new BorderLayout());
this.add(scrollPane, BorderLayout.CENTER);
}
Related
I have a jframe with a jpanel on top of it and the panel often has to change its contents with repaint() and revalidate(). I have managed to place the images, texts and buttons just the I way I want them to be on this jpanel. Everything is working, but now I am trying to set a background to the jframe, that does not interfere with the contents above it. For example, if there is a drawing of a tree, it should appear behind the text of the jpanel, without disrupting it. I found that the thing that semi works is to use setContentPane() on the jframe, adding a class, that has extended jpanel and has overrode paintComponent(). Everything appears on the screen, but the text is squashed vertically and the elements are moved towards the top of the frame.
If instead of using setContentPane() I just add the background class to the frame, it doesn't appear, no matter the setOpaque() of the jpanel.
I also tried using jLayeredPane, since the things I read on the internet suggest that this is the right answer. However, I couldn't make it work and the background remained hidden.
private final int WIDTH = 1024;
private final int HEIGHT = 768;
Frame()
{
JFrame frame = new JFrame();
panel = new JPanel();
gbc = new GridBagConstraints();
//Unrelated elements
//font = new Font(Font.MONOSPACED, Font.PLAIN, 20);
//border = BorderFactory.createEmptyBorder();
//imageResizer = new ImageResizer();
frame.setTitle("Shady Path");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(WIDTH, HEIGHT);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setIconImage(new ImageIcon("res/human.png").getImage());
frame.setContentPane(new DrawPanel());
panel.setLayout(new GridBagLayout());
panel.setOpaque(false);
gbc.anchor = GridBagConstraints.PAGE_START;
frame.add(panel);
frame.setVisible(true);
}
//One of the two methods that change the contents of the jpanel
void appendMain(String mainImage, JTextArea mainText, JButton button)
{
panel.removeAll();
image = new JLabel(imageResizer.resize(200, 200, mainImage));
gbc.insets = new Insets(0, 0, 30, 0);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(image, gbc);
formatText(mainText);
panel.add(mainText, gbc);
button.setFont(font);
button.setForeground(Color.WHITE);
button.setBackground(Color.BLACK);
button.setBorder(border);
gbc.fill = GridBagConstraints.VERTICAL;
gbc.insets = new Insets(50, 0, 70, 0);
panel.add(button, gbc);
panel.revalidate();
panel.repaint();
}
//This is for the text formating
private void formatText(JTextArea baseText)
{
baseText.setEditable(false);
baseText.setForeground(Color.WHITE);
baseText.setFont(font);
baseText.setLineWrap(true);
baseText.setWrapStyleWord(true);
baseText.setMargin(new Insets(0, 300, 0, 300));
baseText.setOpaque(false);
gbc.insets = new Insets(30, 0, 0, 0);
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
}
//The following code is for the paintComponent() class
//The imageResizer is another class that I made, but it just resizes images and it is unrelated.
public class DrawPanel extends JPanel
{
private Image image;
public DrawPanel()
{
ImageResizer imageResizer = new ImageResizer();
ImageIcon imageIcon = imageResizer.resize(1024, 768, "res/test.png");
image = imageIcon.getImage();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
Well... It looks like #HovercraftFullOfEels was right with his comment. Literally, I just had to set the layout of the DrawPanel to a BorderLayout and everything was fixed.
public DrawPanel()
{
this.setLayout(new BorderLayout());
ImageResizer imageResizer = new ImageResizer();
ImageIcon imageIcon = imageResizer.resize(1024, 768, "res/test.png");
image = imageIcon.getImage();
}
I am trying to make a login page but unfortunately my formPanel's border is so out of bounds. Here in the pic you can see the titled border is way out. I need it to be more around my panel with login form:
I see that when creating this formPanel it is that big and the border just surround it. I tried with setPrefferedSize but its not working. How can I fix it?
Here is my code:
public class LoginPanel extends JPanel {
private JLabel title;
public LoginPanel() {
this.setBackground(new Color(0, 128, 43));
this.setBorder(new EmptyBorder(10, 10, 10, 10));
this.setLayout(new BorderLayout());
//adding the title
title = new JLabel("<html><h1><strong><i>Krisko Beatz Quiz</i></strong></h1><hr></html>");
title.setForeground(Color.BLACK);
JPanel titlePanel = new JPanel();
titlePanel.setBackground(new Color(0, 128, 43));
titlePanel.add(title);
this.add(titlePanel, BorderLayout.PAGE_START);
//creating the login form
JPanel formPanel = new JPanel(new GridBagLayout());
formPanel.setBackground(new Color(0, 128, 43));
//gbc
GridBagConstraints gbc = new GridBagConstraints();
//gbc for username
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(5, 0, 0, 0);
JLabel username = new JLabel("Username: ");
username.setForeground(Color.BLACK);
formPanel.add(username, gbc);
//gbc for textfield
gbc.gridx = 1;
gbc.gridy = 0;
JTextField usernameField = new JTextField(10);
formPanel.add(usernameField, gbc);
//gbc for pass
gbc.gridx = 0;
gbc.gridy = 1;
JLabel password = new JLabel("Password: ");
password.setForeground(Color.BLACK);
formPanel.add(password, gbc);
//gbc for pass field
gbc.gridx = 1;
gbc.gridy = 1;
JPasswordField passField = new JPasswordField(10);
formPanel.add(passField, gbc);
//gbc for button
gbc.gridx = 1;
gbc.gridy = 2;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.PAGE_END;
JButton loginButton = new JButton("Login");
formPanel.add(loginButton, gbc);
//add border to the form panel
TitledBorder title = BorderFactory.createTitledBorder("Login");
formPanel.setBorder(title);
this.add(formPanel, BorderLayout.CENTER);
}
}
I tried with setPrefferedSize but its not working.
Don't try to manage the preferredSize of a component.
I would guess the problem is that you are using setSize(...) instead of pack().
You should be using pack() AFTER all the components have been added to the frame. Then all the components will be displayed at their preferred size.
Edit:
I originally misread your question and changed my original answer. The point in my original answer of using the "wrapper" panel is to give extra space to the wrapper panel, while keeping the "formPanel" at a fixed size. This way the titled border will remain around the formPanel even as the frame size is changed.
So again the basic approach for this type of solution is:
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(formPanel, new GridBagConstraints());
this.add(wrapper, BorderLayout.CENTER);
//this.add(formPanel, BorderLayout.CENTER);
I took your LoginPanel class as is, and wrote a Main class around it to start the GUI.
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LoginPanel());
frame.pack();
frame.setVisible(true);
});
}
}
Especially note, I did no explicit setting of the size, only a pack() call which resizes everything to its preferred size according to your layout.
The resulting layout looks perfectly fine to me.
So the conclusion is: Your LoginPanel is fine, but probably there is something wrong in your other code which you didn't post here.
I am a beginner in Java Swing and I am trying to put a multiple JPanels in a JScrollPanel. The matter is, the JSCrollPannel (named jp in the code) should not fill all the JFrame but it does even if I fix a size with setSize() and a maximal size with setMaximalSize(). What is the trouble? How can I make the JSCrollPane smaller than the JFrame?
package GUI;
import java.awt.*;
import javax.swing.*;
public class MultiPanels {
private JScrollPane getContent() {
Dimension d = new Dimension(300,200);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc= new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(getPanel(d, 6, Color.red), gbc);
panel.add(getPanel(d, 4, Color.green.darker()), gbc);
panel.add(getPanel(d, 4, Color.orange), gbc);
panel.add(getPanel(d, 12, Color.blue), gbc);
panel.add(getEmptyPanel(d), gbc);
return new JScrollPane(panel);
}
private JScrollPane getPanel(Dimension d, int rows, Color color) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(color);
GridBagConstraints gbc= new GridBagConstraints();
gbc.insets = new Insets(10,5,10,5);
gbc.weightx = 1.0;
for(int i = 0, j = 1; i < rows; i++) {
gbc.gridwidth = GridBagConstraints.RELATIVE;
panel.add(new JButton(String.valueOf(j++)), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(new JButton(String.valueOf(j++)), gbc);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
private JScrollPane getEmptyPanel(Dimension d) {
JPanel panel = new JPanel() {
protected void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(0,0,Color.red,
0,h,Color.cyan);
((Graphics2D)g).setPaint(gp);
g.fillRect(0,0,w,h);
}
};
panel.setPreferredSize(new Dimension(300,400));
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
public static void main(String[] args) {
JFrame f = new JFrame();
JScrollPane jp = new MultiPanels().getContent();
jp.setSize(new Dimension(200, 200));
jp.setMaximumSize(new Dimension(200,200));
jp.setPreferredSize(new Dimension(200,200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(jp);
f.setSize(400,400);
f.setLocation(200,200);
f.setResizable(false);
f.setVisible(true);
}
}
Any time things don't size or arrange correctly, you have to look into Layouts.
Generally, spend more time on:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
To be specific, the default layout of a JPanel and JFrame is BorderLayout which is a very simple layout manager indeed. When you add to a component managed by BorderLayout without saying where, it is automatically added to the center and fills to use all available space:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#border
It is possible to use "none" (Absolute Positioning) as the layout, but this is almost always a bad idea and you want to think about what you really want to do with the rest of the space in the JFrame: perhaps by letting new child components, with their own size demands, take up some of the space that the main panel is now swallowing up.
I was wondering if I could get some help on my application. I can not find the right values without stuffing everything up. Its using GridBagConstraint, JPanel, JScrollPane (Doesn't Work on one of the panels), JButton, JTabbedPane and JTextArea. The relevant code that is stuffing the display up is down below. TabBar and FileViewer extends of JPanel and Window extends of JFrame;
My init for the tabs and how I add tabs. (This isn't the JScrollPane stuffup part)
private TabBarComponent() {
super(new GridLayout(0, 1, 5, 0));
instance = this;
tabbedPane = new JTabbedPane();
add(tabbedPane);
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
}
public void addBar(String text, JScrollPane s) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(s);
tabbedPane.addTab(text, panel);
}
This is the JScrollPane stuff up one... right now it doesn't bother me but will eventually. I add to the panel by panel.add(button).
public FileViewerComponent() {
super(new GridLayout(0, 1, 5, 0));
instance = this;
panel = new JPanel();
panel.setLayout(new GridLayout(0, 1, 5, 0));
scrollArea = new JScrollPane(panel);
addButtons();
add(scrollArea);
}
Here is where I create the Window. This is where the help is required. I don't know what values I should set. I have looked at the documentation and how the classes work.
private WindowComponent() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.exit(1);
}
setSize(new Dimension(1024, 900));
setLocationRelativeTo(null);
setTitle("GridBagConstraints");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
setJMenuBar(new MenuBarComponent());
c.gridx = 0;
c.gridy = 0;
c.weightx = 0.5;
c.weighty = 1;
c.anchor = GridBagConstraints.NORTHWEST;
add(FileViewerComponent.getInstance(), c);
c = new GridBagConstraints();
c.gridwidth = 2;
c.gridx = 1;
c.gridy = 0;
c.weightx = 0.5;
c.weighty = 1;
c.anchor = GridBagConstraints.NORTHEAST;
add(TabBarComponent.getInstance(), c);
addWindowListener(this);
setVisible(true);
}
Thank you for the help I hope to get.
http://imgur.com/a/JJ1kX#0
The first picture is original size, the second is when I make the window smaller. It works fine when I enlarge the window.
EDIT: Is there an API part from the one created by java that I could use or a tool I could use?
I have a JPanel(named mainJP) which has a few buttons and labels (uses BorderLayout). Next it adds another JPanel (named JP1) and inside it a ScrollPane with a JTable. I want to be able to resize JP2 and in turn all its child components (ScrollPane and JTable). So that I can see few more rows of the JTable without having to scroll. Also inorder to resize JP1, other siblings of JP1 should adjust themselves. Not sure how to achieve that.
As the image shows I already have a few features implemented - to entirely delete JP1, to expand/collapse JP1 view, to delete and add rows in the JTable.
So basically I want to be able to drag the mouse at bottom border of JP1 to vertically increase the size of JP1 and its child components (ScrollPane and JTable).
As described in a few of the below solutions, I am still confused at which level should I incorporate a JSpiltPane - as it allows only adding 2 components. I think all the JP1 should be in the JSplitPane. However there can be more than one JP1 components and they are dynamically added.
To add extra components to the JSplitPane is easy. Put a JPanel in each pane you want to show your components, then add the components to this panel -- you can customize the layout as needed.
Something like this will put a JSplitPane in an already create JFrame, add a JPanel to each Pane, and then add some JLabels to the left side, a JTextField to the right. The splitpane will expand to the size of the JFrame it's in.
JSplitPane splitPane = new JSplitPane();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JTextField textField = new JTextField();
GridBagConstraints gBC = new GridBagConstraints();
getContentPane().setLayout(new GridBagLayout());
leftPanel.setLayout(new GridBagLayout());
rightPanel.setLayout(new GridBagLayout());
// I'm not going to bother doing any layout of the label or textfield here
leftPanel.add(label1, new GridBagConstraints());
leftPanel.add(label2, new GridBagConstraints());
rightPanel.add(textField, new GridBagConstraints());
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
gBC.fill = GridBagConstraints.BOTH;
gBC.weightx = 1.0;
gBC.weighty = 1.0;
getContentPane().add(splitPane, gBC);
pack();
These are two different problems. Resizing a JPanel on a mouse drag -- the easiest way for you is going to be to use two nested JSplitPanes. You would use one so you can drag horizontally, and another to drag vertically.
Alternatively, if you don't want split panes, you can try something like this method and create a custom JPanel. The borders are there to make the effect more visible. I personally don't like it as it's overly complicated.
public class ResizablePanel extends JPanel {
private boolean drag = false;
private Point dragLocation = new Point();
public ResizablePanel() {
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
setPreferredSize(new Dimension(500, 500));
final JFrame f = new JFrame("Test");
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
drag = true;
dragLocation = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
drag = false;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (drag) {
if (dragLocation.getX()> getWidth()-10 && dragLocation.getY() > getHeight()-10) {
System.err.println("in");
setSize((int)(getWidth()+(e.getPoint().getX()-dragLocation.getX())),
(int)(getHeight()+(e.getPoint().getY()-dragLocation.getY())));
dragLocation = e.getPoint();
}
}
}
});
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(this,BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new ResizablePanel();
}
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
As for the children resizing with it's parent, that one is pretty easy with GridBagLayout.
The important parts to remember in the GridBagConstraints are the fill, weightx and weighty.
You can just do something like this in your frame -- it will put a scrollpane with a JTable in it that will resize with the frame:
JScrollPane jScrollPane1 = new JScrollPane();
JTable jTable1 = new JTable();
GridBagConstraints gBC = new GridBagConstraints();
getContentPane().setLayout(new GridBagLayout());
jScrollPane1.setViewPortView(jTable1);
gBC.fill = GridBagConstraints.BOTH;
gBC.weightx = 1.0;
gBC.weighty = 1.0;
getContentPane().add(jScrollPane1, gBC);