How would I create a layout with multiple layout styles - java

I am trying to create a game launcher and for this I would have a couple of JPanels with different kinds of layout styles, at this moment I just don't know what to use as there are a lot of layout styles and they all have their own pros and cons.
This is what I have at the moment:
This is how I did it:
This is the main frame, which has a couple of panels added.
public Frame() {
main = new Background();
menuPane = new MenuPane();
main.setLayout(new BorderLayout());
add(main);
main.add(menuPane, BorderLayout.NORTH);
setTitle("DelusionX Launcher");
setSize(700, 500);
setUndecorated(true);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
This is the background panel
public Background() {
try {
backgroundImg = ImageIO.read(new File("./Images/Background.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImg, (getWidth() - backgroundImg.getWidth(null)) / 2, 0, null);
}
This is the menu panel
public MenuPane() {
this.setBackground(new Color(0, 0, 0, 0.5f));
this.setLayout(new BorderLayout());
minimizeBtn = new Button();
minimizeBtn.addActionListener(this);
minimizeBtn.setIcon(minimizeImg);
this.add(minimizeBtn, BorderLayout.EAST);
closeBtn = new Button();
closeBtn.addActionListener(this);
closeBtn.setIcon(closeImg);
this.add(closeBtn, BorderLayout.EAST);
}
and this is the button object
public Button() {
setBorderPainted(false);
setBorder(null);
setMargin(new Insets(0, 0, 0, 0));
setContentAreaFilled(false);
}
As you can see I also have added a minimize button, but for some reason it is behind the close button, I suppose.
This is what I want to achieve:
This is how I thought the panels should be, but I am not sure if that is the best/easiest way.
My question in short: How would I create an JFrame that looks like the second image?

GridBagLayout is one of the most flexible layout managers in the default API, it lets you get away with some amazing things if you're willing to try
See How to Use GridBagLayout for more details
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(100, 0, 0, 0);
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(new ProxyPane(400, 300, Color.RED), gbc);
gbc.insets = new Insets(101, 1, 0, 1);
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.NORTH;
add(new ProxyPane(400, 50, Color.YELLOW), gbc);
gbc.insets = new Insets(0, 0, 0, 0);
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.NONE;
add(new ProxyPane(300, 200, Color.GREEN), gbc);
}
}
public class ProxyPane extends JPanel {
private Dimension size;
public ProxyPane(int width, int height, Color borderColor) {
size = new Dimension(width, height);
setBorder(new LineBorder(borderColor));
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return size;
}
}
}

Related

How do i add another button in JButton

I have 1 button i. but i need another. i added another JFrame and made a new class making the button. whenever i do
frame.add(new TestButton());
it never works. i already have
frame.add(new TestPanel());
which works. but its the only working one.
here is my TestButton code
package App.Gui.Buttons;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import App.Gui.Event.ExitEvent;
public class TestButton extends JPanel {
public TestButton() {
setLayout(new GridBagLayout());
JButton button = new JButton();
button.setBackground(new Color(0, 0, 0, 0));
button.setForeground(new Color(0, 0, 0, 0));
button.setBorderPainted(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ExitEvent.exit();
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.insets = new Insets(20, 50, 20, 50);
add(button, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
JPanel contentPane = new JPanel(new GridBagLayout());
contentPane.setBackground(Color.GREEN);
contentPane.add(new JLabel("Books app"));
add(contentPane, gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1200, 750);
}
public static void addButton() {
new TestButton();
}
}
i need to add another button to do more stuff like you would need in a software. but it either never starts or, it bugs the buttons.
pls help.
A JPanel can't be shown in of itself. It needs to be added to a container hierarchy which is backed by a window based class, like JFrame.
This is a pretty basic concept, which suggests that you might be better off spending some time going through Creating a GUI With Swing, especially How to Make Frames (Main Windows)
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestButton());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Also, JFrame uses a BorderLayout by default, so you'll only be able to present a single component at each of it's five available positions.
So, if instead, you used a GridLayout, you could get multiple instances of TestButton on the window at the same time, for example
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(2, 1));
frame.add(new TestButton());
frame.add(new TestButton());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Now, Swing components also don't support alpha based colors, they are either opaque or they are not (no translucency - you can fake it, but that's beyond the scope)
So, I'd modify you code to look more like...
JButton button = new JButton();
//button.setBackground(new Color(0, 0, 0, 0));
//button.setForeground(new Color(0, 0, 0, 0));
button.setBorderPainted(false);
button.setOpaque(false);
button.setContentAreaFilled(false);
Also, good luck on been able to click that button by the way
Full code...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestButton extends JPanel {
public TestButton() {
setLayout(new GridBagLayout());
JButton button = new JButton();
// button.setBackground(new Color(0, 0, 0, 0));
// button.setForeground(new Color(0, 0, 0, 0));
button.setBorderPainted(false);
button.setOpaque(false);
button.setContentAreaFilled(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//ExitEvent.exit();
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.insets = new Insets(20, 50, 20, 50);
add(button, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
JPanel contentPane = new JPanel(new GridBagLayout());
contentPane.setBackground(Color.GREEN);
contentPane.add(new JLabel("Books app"));
add(contentPane, gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1200, 750);
}
}
There are also issues with updating a realised window (adding/removing components once the window is visible on the screen). Swing is lazy and you are required to request a layout and paint pass on the container you've modified (invalidate and repaint).
But you might find CardLayout more suitable to your needs instead - but since we don't have a runnable example, it's hard to know

Automatically Resizing with BorderLayout in Java

This is my jFrame Form with BorderLayout where buttons will be placed in Navigation Bar Panel and jDesktopPane will be placed in Content Panel. The DesktopPane with CardLayout will be displaying different sizes of jPanel Form. I want Content Panel(including whole form) resize based on the different sizes of jPanel Form displayed. Is it possible to do this? If not then I've tried resizing the panel and even the whole form with codes, but it's not working.
I've trying playing with these few codes, but it's not working.
Main_Menu form = new Main_Menu();
form.pack();
form.setSize(900, 548);
form.setPreferredSize(new Dimension(900, 548));
form.validate();
So, based on the limited information available, I wrote a quick test which seems to work just fine
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
CardLayout layout = new CardLayout();
JDesktopPane pane = new JDesktopPane();
Navigator navigator = new Navigator(pane, layout);
pane.setLayout(layout);
pane.setBackground(Color.GREEN);
frame.add(new TopPane(), BorderLayout.NORTH);
frame.add(new NavigationPane(navigator), BorderLayout.WEST);
for (int index = 0; index < 5; index++) {
pane.add(new ContentPane(index), Integer.toString(index));
}
JLabel initial = new JLabel("All your content belong to us");
initial.setBorder(new EmptyBorder(20, 20, 20, 20));
pane.add(initial, "initial");
layout.show(pane, "initial");
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Navigator {
private JComponent parent;
private CardLayout layout;
public Navigator(JComponent parent, CardLayout layout) {
this.parent = parent;
this.layout = layout;
}
public void show(String name) {
layout.show(parent, name);
}
}
public class TopPane extends JPanel {
public TopPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.BLUE);
JLabel title = new JLabel("Top Panel");
title.setForeground(Color.WHITE);
add(title);
}
}
public class NavigationPane extends JPanel {
private Navigator navigator;
public NavigationPane(Navigator navigator) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.ORANGE);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
for (int index = 0; index < 5; index++) {
JButton btn = new JButton("Test " + index);
btn.setActionCommand(Integer.toString(index));
add(btn, gbc);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
navigator.show(name);
}
});
}
}
}
public class ContentPane extends JPanel {
public ContentPane(int value) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
setBackground(Color.MAGENTA);
add(new JLabel("Hello from " + Integer.toString(value)));
}
}
}
Avoid setPreferred/Minimum/MaximumSize, you're overriding the work which the components and the layout managers do in order to provide dynamic sizing hints
If this fails to solve your issue, then consider providing a Minimal, Complete, and Verifiable example
Try to use pack(); not form.pack();. Or setLayout or use CardLayout

Java Set Layout

I need to create a JFrame which has three JPanels laid out as shown:
Could anybody please tell me how I can achieve this layout? I have already tried using BorderLayout, but in BorderLayout, if I add the topmost pane at BorderLayout.NORTH, the one in the center at BorderLayout.CENTER, and the one at the bottom to BorderLayout.SOUTH, the topmost pane becomes too small (in height) and the pane in the center becomes too big (in height).
P.S. I have already made the 3 panes and set their preferred sizes properly.
You could use all sorts of things, compound layouts (using two BorderLayouts for example) or other layouts, it will depend on what you ultimately want to achieve.
For simplicity, I'd use a GridBagLayout, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestLayout {
public static void main(String[] args) {
new TestLayout();
}
public TestLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(new ABigPanel(), gbc);
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new ASmallPanel(), gbc);
add(new ASmallerPanel(), gbc);
}
}
public class ABigPanel extends JPanel {
public ABigPanel() {
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
}
public class ASmallPanel extends JPanel {
public ASmallPanel() {
setBackground(Color.GREEN);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 180);
}
}
public class ASmallerPanel extends JPanel {
public ASmallerPanel() {
setBackground(Color.CYAN);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 40);
}
}
}
See How to Use GridBagLayout for more details

How can I make my Panel wrap text and increase in height instead of width when contained in a GridBagLayout?

[FINAL EDIT]
Ok folks.
I don't know why it does not work in my chat program... but I managed to fix the SSCCE.. with the scrollable implementation it works now. Thank you all!
Code:
package de.sky.cjat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.UIManager;
public class MyKskb {
private int row;
class SomethingPanel extends JPanel implements Scrollable {
public SomethingPanel(LayoutManager manager){
super(manager);
}
#Override
public Dimension getPreferredScrollableViewportSize(){
return getPreferredSize();
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
#Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
#Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
}
public MyKskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final SomethingPanel content = new SomethingPanel(new GridBagLayout());
// final JPanel empty = new JPanel();
// empty.setPreferredSize(new Dimension(0, 0));
// GridBagConstraints gbc = new GridBagConstraints();
// content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
p.setBackground(Color.GRAY);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridx = 0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
// content.remove(empty);
// gbc.gridy = row;
// gbc.weighty = 1.0;
// content.add(empty, gbc);
JTextArea text = new JTextArea(
Math.random() > 0.5 ?
"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC" :
"FFFFFFFFFFFFABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap(true);
p.add(text);
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new MyKskb();
}
}
[END]
[QUESTION]
I'm writing a Chat Program, and the layout looks like this:
The Panel with the messages has a GridBagLayout and is wrapped in a JScrollPane.
The problem is, if the message is too long, the message panel stretches and gets too big:
So what I want to achieve, is to limit the size of the panel, which is wrapped in the JScrollPane - I want the gray panels with the message text to increase their height, if the text gets longer, not wider. I.e. wrap the text, without increasing the panel width.
Is there a way to achieve this with the grid bag layout, or am I missing something? Or should I use another layout manager?
Edit: The full Hierarchy:
JScrollPane
JPanel (gbl)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
....
edit: I tried to implement Scrollable like this:
#Override
public Dimension getPreferredScrollableViewportSize(){
return new Dimension(100, getHeight());
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
#Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
#Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
but the same thing happens if the text gets too long... I don't know what getPreferredScrollableViewportSize should return, but also getSize() didn't work...
EDIT: here is a SSCCE, it shows the basic structure of my GUI: (press enter to add new component)
package de.sky.cjat;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Kskb {
private int row;
public Kskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
final JPanel content = new JPanel(new GridBagLayout());
final JPanel empty = new JPanel();
empty.setPreferredSize(new Dimension(0, 0));
GridBagConstraints gbc = new GridBagConstraints();
content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel();
p.setBackground(Color.GRAY);
JLabel text = new JLabel("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
p.add(text);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTHWEST;
content.add(p, gbc);
content.remove(empty);
gbc.gridy = row;
gbc.weighty = 1.0;
content.add(empty, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
Following up on #durandal's advice, the problem is the JLabel. A JLabel does not wrap text. So you need to use a different component. Here is your code modified with a JTextArea:
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.*;
public class Kskb {
private int row;
public Kskb()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final ScrollablePanel content = new ScrollablePanel(new GridBagLayout());
content.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
final GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "");
content.getActionMap().put("", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e)
{
JPanel p = new JPanel( new BorderLayout() );
p.setBorder( new EmptyBorder(10, 10, 10, 10) );
p.setBackground(Color.GRAY);
JTextArea text = new JTextArea();
text.append("ABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCA BCABCABCABCABCABCABCAB CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap( true );
p.add(text);
gbc.gridy = row++;
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
The key is the Scrollable implementation which forces the panels width to be adjusted ad the frame is adjusted. This code uses the Scrollable Panel, which is just a reusable implementation of the Scrollable interface that you can configure with methods instead of creating a new class and overriding the methods.
This is an effect of the interaction between JScrollPane and its content. A scroll pane will (by default) provide as much space as the contents desires.
So in that sense, the layout is working perfectly.
To give the component shown in a scroll pane actually control of the size of the container it shows, the contained component can implement the interface javax.swing.Scrollable.
Try something like this:
public class MyVerticalPanel extends JPanel implements Scrollable {
#Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
// other method and implementation
}
More documentation is available here: https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#scrollable
I managed to get something working that is along the lines of what you want:
public class Chatter extends JFrame {
JTextField enterTextField = new JTextField("This is a lot of text it's way too loooooooooooooooong to fit in one line but it is used to check for wrapping by words and characters some more text just for fun no punctuation");
JPanel historyPanel = new JPanel();
public Chatter() {
enterTextField.addActionListener(new enterTextActionListener());
historyPanel.setLayout(new BoxLayout(historyPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(historyPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(enterTextField, BorderLayout.PAGE_END);
getContentPane().add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private class enterTextActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JTextArea textArea = new JTextArea(enterTextField.getText());
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.RED, 5));
scrollPane.setPreferredSize(textArea.getPreferredSize());
historyPanel.add(scrollPane);
historyPanel.add(Box.createRigidArea(new Dimension(0,10)));
historyPanel.revalidate();
// enterTextField.setText(""); // Commented out for convenience while testing.
}
}
public static void main(String args[]) {
new Chatter();
}
}
Explanation:
I use JTextAreas to display the text since it has text wrapping support. Each text area is inside a JScrollPane in order to allow vertical scrolling as a last resort if there is not enough space to display the text.
Notes:
I used a JTextField as the input method for text, you can use a multiline text component instead.
The initial text is just for testing.
The text is not cleared with every entry for testing (see the commented line in the code).
I used BoxLayout for the panel which holds the text messages because it seemed simpler and more natural. GridBagLayout could surely be used instead.
I set setWrapStyleWord(true) because it's probably the right behavior to wrap by words. If you want to wrap by characters then delete this line.
I added a border and spaces for testing. Use whatever styling you want instead.
I think you can do this.
Jpanel.setPreferredSize(new Dimension(x size, y size));
Jframe.add(Jpanel);
I think most layout managers work better with setPreferredSize than setSize.

How can I attach the progress bar to when the JFrame Opens?

I want to attached the progress bar to the Frame and not the test start button that I have currently. The progress bar works but I want it run when the window is opened for the time being and then I can attach it to whatever I want later on.
Code:
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.JProgressBar;
import javax.swing.JButton;
public class ProgressBarWindow extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ProgressBarWindow frame = new ProgressBarWindow();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public ProgressBarWindow() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) { }
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 183);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JProgressBar progressBar = new JProgressBar();
progressBar.setBounds(22, 77, 386, 27);
contentPane.add(progressBar);
JButton btnNewButton = new JButton("Cancel");
btnNewButton.setBounds(319, 111, 89, 23);
btnNewButton.addMouseListener(new myMouseListener2());
contentPane.add(btnNewButton);
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new btnDoAction(progressBar));
btnStart.setBounds(220, 111, 89, 23);
contentPane.add(btnStart);
}
}
class myClose implements MouseListener {
myClose() { }
#Override
public void mouseClicked(MouseEvent e) {
final Component source = e.getComponent();
final JFrame frame = (JFrame) SwingUtilities.getRoot(source);
frame.dispose();
}
#Override
public void mousePressed(MouseEvent e) {
final Component source = e.getComponent();
final JFrame frame = (JFrame) SwingUtilities.getRoot(source);
frame.dispose();
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
class btnDoAction implements ActionListener{
JProgressBar temp = new JProgressBar();
btnDoAction(JProgressBar p) {
this.temp = p;
}
public void actionPerformed (ActionEvent e){
new Thread(new thread1(temp)).start(); //Start the thread
}
}
class thread1 implements Runnable{
JProgressBar pBar = new JProgressBar();
thread1(JProgressBar u) {
this.pBar = u;
}
public void run(){
for (int i=0; i<=100; i++){ //Progressively increment variable i
pBar.setValue(i); //Set value
pBar.repaint(); //Refresh graphics
try{Thread.sleep(50);} //Sleep 50 milliseconds
catch (InterruptedException err){}
}
}
}
If I understand correctly, instead of using a JFrame as you base component, extend your class from a JPanel, this way you can add it to anything you want.
You could then provide setter and getter methods to adjust the progress bar, but I'd do this via some kind of interface contract .
Don't use null layouts. You don't control aspects like fonts, font metrics, rendering pipelines and other properties which effect the amount of space components need in order to be rendered properly across multiple systems (even those running the same OS)
Don't use MouseListeners on buttons, use ActionListeners instead. To takes into account when the use clicks on the button and presses space/Zener
Don't update the UI from any thread other then the a Event Dispatching Thread. See Concurrency in Swing for more details. Consider using a SwingWorker instead, it has functionality to sync the background thread with the EDT and in built progress support
Updated
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class LayoutExample {
public static void main(String[] args) {
new LayoutExample();
}
public LayoutExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ProgressPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ProgressPane extends JPanel {
private JProgressBar pb;
private JButton start;
private JButton cancel;
public ProgressPane() {
pb = new JProgressBar();
start = new JButton("Start");
cancel = new JButton("Cacnel");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(50, 10, 5, 10);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridwidth = 2;
add(pb, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.insets = new Insets(0, 0, 0, 5);
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 1;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.EAST;
add(start, gbc);
gbc.weightx = 0;
gbc.gridx = 1;
gbc.insets = new Insets(0, 0, 0, 10);
gbc.anchor = GridBagConstraints.WEST;
add(cancel, gbc);
}
}
}

Categories