JLabel text bigger than JLabel size and turning to "..." - java

I'm really new to Java, and I wanted to make a simple GUI with a button which counts when you click it, I followed this tutorial on YouTube to get there. It went really nicely and everything worked. But one thing didn't, the end of the JLabel text goes from a number (9), to ....
Resizing the window manually brings the number back, so I tried resizing the font, window, button, and label sizes in the code when it launches, which does work, but I still get the same problem.
This is my code for the button:
JButton button = new JButton("Click me!");
button.addActionListener(this);
...which I believe would call this:
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Number of clicks: " + count);
}
I've tried some other solutions on other questions but they haven't helped at all.
My full code for the GUI is this:
package javaGUI;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI implements ActionListener {
private int count = 0;
private JLabel label;
private JFrame frame;
private JPanel panel;
public GUI() {
frame = new JFrame();
JButton button = new JButton("Click me!");
button.addActionListener(this);
button.setPreferredSize(new Dimension(10, 75));
label = new JLabel("Number of clicks: 0");
label.setFont(new Font("System", Font.PLAIN, 22));
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(60, 100, 30, 100));
panel.setLayout(new GridLayout(0, 1));
panel.add(button);
panel.add(label);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("GUI");
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new GUI();
}
#Override
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Number of clicks: " + count);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
}
}

When the frame is "packed" before it is made visible all the components are displayed at their preferred size.
The problem is that when you need to display multiple digits in the label, the labels preferred size increases but there is not enough space in the frame to display the label text completely so the text is truncated.
So the solution is to pack() the frame so the components in the GridLayout can once again be displayed at their preferred size:
label.setText("Number of clicks: " + count);
frame.pack();
Also note you should not set label properties in the ActionListener. The following properties should be set when you create the Label:
label = new JLabel("Number of clicks: 0");
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);

Basically, you have to give the JLabel room to grow.
Here's one way to do it.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ClickMe implements ActionListener, Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ClickMe());
}
private int count = 0;
private JLabel label;
private JFrame frame;
#Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Click Me");
JPanel buttonPanel = new JPanel();
JButton button = new JButton("Click me!");
button.addActionListener(this);
button.setFont(new Font("System", Font.PLAIN, 22));
button.setPreferredSize(new Dimension(300, 75));
buttonPanel.add(button);
frame.add(buttonPanel, BorderLayout.CENTER);
JPanel labelPanel = new JPanel();
label = new JLabel("Number of clicks: 0");
label.setFont(new Font("System", Font.PLAIN, 22));
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
labelPanel.add(label);
frame.add(labelPanel, BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Number of clicks: " + count);
}
}

Related

How to add JTextField whenever the button is clicked?

I am practising Java Swing and I am trying to create a GPA calculator. I am having a hard time with my code, how can I add text fields whenever the JButton "add" is clicked? I also want the text fields to align vertically when the button is clicked. Should I use a layout or something?
You can check my screenshot as well.
Here is my code:
import java.awt.event.ActionEvent;
import javax.swing.*;
public class gwa implements ActionListener, java.awt.event.ActionListener{
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
//button
JButton buttonAdd = new JButton("Add");
buttonAdd.setBounds(30, 30, 80, 34);
buttonAdd.addActionListener(new gwa());
//textfield
JTextField gradeField = new JTextField();
gradeField.setBounds(150, 30, 100, 35);
JTextField unitsField = new JTextField();
unitsField.setBounds(300, 30, 100, 35);
//panel
panel.setLayout(null);
panel.add(buttonAdd);
panel.add(gradeField);
panel.add(unitsField);
//frame
frame.add(panel);
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
}
One way – but not the only way – is to use GridBagLayout.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GwaAdder {
private static final int COLUMNS = 10;
private GridBagConstraints gbc;
private JPanel textFieldsPanel;
private void addTextField(ActionEvent event) {
JTextField textField = new JTextField(COLUMNS);
gbc.gridy++;
textFieldsPanel.add(textField, gbc);
textFieldsPanel.revalidate();
textFieldsPanel.repaint();
}
private void createAndDisplayGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTextFieldsPanel(), BorderLayout.CENTER);
frame.add(createButtons(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtons() {
JPanel panel = new JPanel();
JButton button = new JButton("Add");
button.addActionListener(this::addTextField);
panel.add(button);
return panel;
}
private JScrollPane createTextFieldsPanel() {
textFieldsPanel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.gridy = 0;
JTextField textField = new JTextField(COLUMNS);
textFieldsPanel.add(textField, gbc);
JScrollPane scrollPane = new JScrollPane(textFieldsPanel);
scrollPane.setPreferredSize(new Dimension(140, 200));
return scrollPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GwaAdder().createAndDisplayGui());
}
}
The ActionListener is implemented using method references. When you change the GUI after it is initially displayed (as the above code does in method addTextField), you usually need to call method revalidate (in class javax.swing.JComponent) followed by method repaint (in class java.awt.Component).
How it looks when I run the above code:
You should first give your button's Action event the panel, and then do the Action
My English is not good, so I use translation software to answer, please forgive me

java not displaying jpanel in jframe after button press

I am simply making a user interface and all i want it to do after the button is pressed is display thanks... I am pretty new to this but from what i see there are no errors? I have tried playing around with the set visible and to no avail...Any help is great thanks
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JList;
public class GuiApp1 {
public static void main(String args[]) {
String title = (args.length == 0 ? "CheckBox Sample" : args[0]);
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel(new GridLayout(0, 1));
Border border = BorderFactory.createTitledBorder("Pizza Toppings");
panel.setBorder(border);
JLabel label1 = new JLabel("Enter name below:");
panel.add(label1);
JTextField field = new JTextField(20);
panel.add(field);
JCheckBox check = new JCheckBox("Car0");
panel.add(check);
check = new JCheckBox("Car1");
panel.add(check);
check = new JCheckBox("Car2");
panel.add(check);
check = new JCheckBox("Car3");
panel.add(check);
check = new JCheckBox("Car4");
panel.add(check);
JButton button = new JButton("Submit");
final JPanel listPanel = new JPanel();
listPanel.setVisible(false);
JLabel listLbl = new JLabel("Vegetables:");
listPanel.add(listLbl);
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
listPanel.setVisible(!listPanel.isVisible());
panel.setVisible(!panel.isVisible());
}
});
Container contentPane = frame.getContentPane();
contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);
frame.setSize(300, 300);
frame.setResizable(true);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
The reason for the vegetables panel not appearing is simple: Xou never add ist to the contentPane.
For the code to function properly you need to add/remove the panels in the ActionListener of the button:
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
listPanel.setVisible(!listPanel.isVisible());
panel.setVisible(!panel.isVisible());
if (listPanel.isVisible()) {
contentPane.remove(panel); // Vegetables are visible, so remove the Cars
contentPane.add(listPanel, BorderLayout.CENTER); // And add the Vegetables
} else {
contentPane.remove(listPanel); // Vice versa
contentPane.add(panel, BorderLayout.CENTER);
}
}
});
Then, you need to move the ActionListener below the contentPane declaration and make it final.
Also you should consider putting the different checkboxes is different variables, so you can read the state of them. If you don't want to have so many variables hanging you could put them into an array.
JCheckBox[] checks = new JCheckbox[5];
checks[0] = new JCheckBox("Car0");
panel.add(checks[0]);
...

Open a menu from buttons

hello eveybody i created this code :
package project1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageProducer;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
public class ccc {
public static void main(String[] args){
JFrame frame = new JFrame("Food delivery"); // Create a frame
frame.setSize(1600, 1400); // Set the frame size
frame.setLocationRelativeTo(null); // New since JDK 1.4
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); // Display the frame
JPanel panel = new JPanel(new FlowLayout());
JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
ImageIcon icon = new ImageIcon("hamburger.jpg");
frame.setIconImage(icon.getImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
try {
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("fd12.jpg")))));
} catch (IOException e) {
e.printStackTrace();
}
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
JLabel label = new JLabel("Welcome to Food Delivery");
label.setFont(new Font("Courier New", Font.BOLD, 38));
label.setForeground(Color.black);
System.out.println("");
JButton btn1= new JButton("Breakfast");
btn1.setFont(new Font("Courier New", Font.BOLD, 16));
btn1.setForeground(Color.BLACK);
JButton btn2= new JButton("Starters");
btn2.setFont(new Font("Courier New", Font.BOLD, 16));
btn2.setForeground(Color.BLACK);
JButton btn3= new JButton("Main Dishes");
btn3.setFont(new Font("Courier New", Font.BOLD, 16));
btn3.setForeground(Color.BLACK);
JButton btn4= new JButton("Deserts");
btn4.setFont(new Font("Courier New", Font.BOLD, 16));
btn4.setForeground(Color.BLACK);
JButton btn5= new JButton("Drinks");
btn5.setFont(new Font("Courier New", Font.BOLD, 16));
btn5.setForeground(Color.BLACK);
frame.add(label);
frame.add(new JSeparator());
frame.add(btn1);
frame.add(btn2);
frame.add(btn3);
frame.add(btn4);
frame.add(btn5);
frame.pack();
frame.setVisible(true);
}}
screen shot :
enter image description here
I would love to get a new page inside the page that get opens for each buttons and inside I will write the menu of the food to select and near to it have the prices written ?? please help me I couldn't not do it at all and can know how ...
Thanks
You can use JPanel to draw things inside other Containers. (JPanel and JFrame are Containers)
But u said u just want to write text. So u can use a JTextArea.
Javadoc will help u.
As noted in the comments by Emz, a CardLayout is the best fist for this scenario. Create a JPanel for each of the menus and add them to a JPanel with CardLayout. Then use the buttons to switch between the panels.
Here is an example:
public class Example extends JPanel {
Example() {
JPanel starters = new JPanel(new FlowLayout());
starters.add(new JLabel("starters..."));
JPanel drinks = new JPanel(new FlowLayout());
drinks.add(new JLabel("drinks..."));
JPanel main = new JPanel(new CardLayout());
main.add(starters, "starters");
main.add(drinks, "drinks");
JPanel buttons = new JPanel();
JButton startersButton = new JButton("Starters");
startersButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout)(main.getLayout());
cl.show(main, "starters");
}
});
JButton drinksButton = new JButton("Starters");
drinksButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout)(main.getLayout());
cl.show(main, "drinks");
}
});
buttons.add(startersButton);
buttons.add(drinksButton);
setLayout(new BorderLayout());
add(main);
add(buttons, BorderLayout.PAGE_START);
}
}
Add to a frame and run.

Centering image in a JFrame?

I'm creating an about JFrame for my program. I have an icon which I used for the program and I have that show up as the first thing on the about JFrame, but I'm having issues trying to center the image. If I do some kind of centering it screws up the whole alignment of everything else.
I'm trying to have all the JLabels, other than the icon, to be left aligned. Then have the icon aligned to the center.
I had to remove some personal information, whatever I did remove I put them between "[]".
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class About extends JFrame {
public About() {
super("About [PROGRAM]");
setIconImage([PROGRAM].getInstance().setIcon());
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
main.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
JLabel icon = new JLabel("", new ImageIcon(getClass().getResource(Constants.ICON_FULL)), JLabel.CENTER);
JLabel name = new JLabel("[PROGRAM]");
JLabel expandedName = new JLabel("[PROGRAM DESCRIPTION]");
JLabel copyright = new JLabel("[COPYRIGHT JUNK]");
JLabel credits = new JLabel("[CREDITS]");
name.setFont(new Font(name.getFont().getFamily(), Font.BOLD, 18));
copyright.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
main.add(icon);
main.add(Box.createRigidArea(new Dimension(0, 10)));
main.add(name);
main.add(expandedName);
main.add(copyright);
main.add(credits);
add(main);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
Consider using some layouts to help you out. Ones that come to mind include BorderLayout with the icon in the BorderLayout.CENTER position. You can stack stuff on one side using a BoxLayout using JPanel that is added to the main BorderLayout-using JPanel.
e.g.,
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class About extends JDialog {
public static final String IMAGE_PATH = "http://upload.wikimedia.org/wikipedia/"
+ "commons/thumb/3/39/European_Common_Frog_Rana_temporaria.jpg/"
+ "800px-European_Common_Frog_Rana_temporaria.jpg";
public About(JFrame frame) {
super(frame, "About [PROGRAM]", true);
ImageIcon myIcon = null;
try {
URL imgUrl = new URL(IMAGE_PATH);
BufferedImage img = ImageIO.read(imgUrl);
myIcon = new ImageIcon(img);
} catch (MalformedURLException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JPanel main = new JPanel(new BorderLayout());
main.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel centerLabel = new JLabel(myIcon);
JLabel name = new JLabel("[PROGRAM]");
JLabel expandedName = new JLabel("[PROGRAM DESCRIPTION]");
JLabel copyright = new JLabel("[COPYRIGHT JUNK]");
JLabel credits = new JLabel("[CREDITS]");
name.setFont(new Font(name.getFont().getFamily(), Font.BOLD, 18));
copyright.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
int eb = 20;
centerLabel.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
leftPanel.add(name);
leftPanel.add(Box.createVerticalGlue());
leftPanel.add(expandedName);
leftPanel.add(copyright);
leftPanel.add(credits);
leftPanel.add(Box.createVerticalGlue());
main.add(centerLabel, BorderLayout.CENTER);
main.add(leftPanel, BorderLayout.LINE_START);
add(main);
pack();
}
public static void main(String[] args) {
final JFrame frame = new JFrame("GUI");
JPanel panel = new JPanel();
panel.add(new JButton(new AbstractAction("About") {
#Override
public void actionPerformed(ActionEvent e) {
About about = new About(frame);
about.setLocationRelativeTo(frame);
about.setVisible(true);
}
}));
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

MigLayout resizing with JScrollPane

I searched a little bit and did not find a good answer to my problem.
I am working on a gui that has to be resizable. It contains a status JTextArea that is inside a JScrollPane. And this is my problem. As long as I don't manually resize my JFrame, the "initial" layout is kept and everything looks fine. As soon as I manually resize (if the JTextArea is already in scrolled mode), the layout gets messed up.
Here is a SSCCE (I got rid of most of the parts while keeping the structure of the code. I hope it's more readable that way):
import java.awt.Color;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import net.miginfocom.swing.MigLayout;
public class Tab extends JFrame {
private static final long serialVersionUID = 1L;
private JTextArea messageTextArea;
private JPanel optionPanel, messagePanel;
private JTabbedPane plotTabPane;
public static void main(String[] args) {
final Tab tab = new Tab();
tab.setSize(1000, 600);
tab.setVisible(true);
new Thread(new Runnable() {
#Override
public void run() {
int count = 0;
tab.printRawMessage("start");
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
tab.printRawMessage("\ntestMessage" + count++);
}
}
}).start();
}
public Tab() {
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents();
}
private void initComponents() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new MigLayout("insets 0", "", ""));
mainPanel.add(getLeftTopPanel(), "shrinky, top, w 450!");
mainPanel.add(getRightPanel(), "spany 5, wrap, grow, pushx, wmin 400");
mainPanel.add(getMessagePanel(), "pushy, growy, w 450!");
JScrollPane contentScrollPane = new JScrollPane(mainPanel);
contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
setContentPane(contentScrollPane);
}
protected JPanel getLeftTopPanel() {
if (optionPanel == null) {
optionPanel = new JPanel();
optionPanel.setBorder(BorderFactory.createTitledBorder(null, "Configuration", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
optionPanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));
JLabel label = new JLabel("Choose");
label.setHorizontalAlignment(JLabel.RIGHT);
optionPanel.add(label, "w 65!");
optionPanel.add(new JSeparator(JSeparator.VERTICAL), "spany 5, growy, w 2!");
optionPanel.add(new JComboBox(new String[] {"option1", "option2", "option3"}), "span, growx, wrap");
optionPanel.add(new JLabel("Type"), "right");
optionPanel.add(new JTextField("3"), "w 65!, split 2");
optionPanel.add(new JLabel("Unit"), "wrap");
optionPanel.add(new JLabel("Slide"), "right");
optionPanel.add(new JSlider(0, 100), "span, growx, wrap");
}
return optionPanel;
}
protected JTabbedPane getRightPanel() {
if (plotTabPane == null) {
plotTabPane = new JTabbedPane();
plotTabPane.add("Tab1", new JPanel());
plotTabPane.add("Tab2", new JPanel());
}
return plotTabPane;
}
protected JPanel getMessagePanel() {
if (messagePanel == null) {
messagePanel = new JPanel();
messagePanel.setBorder(BorderFactory.createTitledBorder(null, "Status Console", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
messagePanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));
messagePanel.add(new JScrollPane(getMessageTextArea()), "push, grow");
}
return messagePanel;
}
protected JTextArea getMessageTextArea() {
if (messageTextArea == null) {
messageTextArea = new JTextArea();
messageTextArea.setEditable(false);
messageTextArea.setFont(new Font(null, Font.PLAIN, 20));
messageTextArea.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
}
return messageTextArea;
}
public void printRawMessage(String rawMessage) {
getMessageTextArea().append(rawMessage);
getMessageTextArea().setCaretPosition(getMessageTextArea().getText().length());
}
}
The layout stuff basically happens in initComponents().
To see the problem:
Start the Application (I used miglayout-4.0-swing.jar).
Wait a bit (don't resize the window), until there are enough messages to create the scrollbar in the status text area.
Now this is what I want. The JTextArea goes all the way to the bottom of the JFrame and is scrolled if neccessary.
Now resize the window. As you can see, everything gets messed up. It will only be fine, if the window is maximized.
Here are two screenshots. The first one is how I want it to be:
The second one is after resizing:
My question: Can somebody tell me, how I keep the layout the way it is before resizing? I want to have the JTextArea go all the way down to the bottom of the window. And if neccessary, the scrollbar should appear. The only way, the status panel can go below the bottom of the window is, if the window is too small (because the configuration panel has a fixed height).
I hope I made myself clear. If not, please ask. ;)
EDIT: You can see the behaviour I want, if you remove the top JScrollPanel (the one that holds all the components). Just change
JScrollPane contentScrollPane = new JScrollPane(mainPanel);
contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
setContentPane(contentScrollPane);
to
setContentPane(mainPanel);
to see what I mean. Unfortunately, this way I loose the scrollbars if the window is very small.
Focusing on your status area and using nested layouts produces the result shown below. Note in particular,
Use invokeLater() to construct the GUI on the EDT.
Use javax.swing.Timer to update the GUI on the EDT.
Use pack() to make the window fit the preferred size and layouts of its subcomponents.
Use the update policy of DefaultCaret to control scrolling.
Avoid needless lazy instantiation in public accessors.
Avoid setXxxSize(); override getXxxSize() judiciously.
Critically examine the decision to extend JFrame.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import javax.swing.text.DefaultCaret;
public class Tab extends JFrame {
private JTextArea messageTextArea;
private JPanel optionPanel, messagePanel;
private JTabbedPane plotTabPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final Tab tab = new Tab();
tab.setVisible(true);
Timer t = new Timer(200, new ActionListener() {
int count = 0;
#Override
public void actionPerformed(ActionEvent e) {
tab.printRawMessage("testMessage" + count++);
}
});
t.start();
}
});
}
public Tab() {
initComponents();
}
private void initComponents() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel(new GridLayout(1, 0));
Box leftPanel = new Box(BoxLayout.Y_AXIS);
leftPanel.add(getLeftTopPanel());
leftPanel.add(getMessagePanel());
mainPanel.add(leftPanel);
mainPanel.add(getRightPanel());
this.add(mainPanel);
this.pack();
this.setLocationRelativeTo(null);
}
protected JPanel getLeftTopPanel() {
optionPanel = new JPanel();
optionPanel.setBorder(BorderFactory.createTitledBorder(null,
"Configuration", TitledBorder.LEFT, TitledBorder.TOP,
new Font("null", Font.BOLD, 12), Color.BLUE));
JLabel label = new JLabel("Choose");
label.setHorizontalAlignment(JLabel.RIGHT);
optionPanel.add(label);
optionPanel.add(new JSeparator(JSeparator.VERTICAL));
optionPanel.add(new JComboBox(
new String[]{"option1", "option2", "option3"}));
optionPanel.add(new JLabel("Type"));
optionPanel.add(new JTextField("3"));
return optionPanel;
}
protected JTabbedPane getRightPanel() {
plotTabPane = new JTabbedPane();
plotTabPane.add("Tab1", new JPanel());
plotTabPane.add("Tab2", new JPanel());
return plotTabPane;
}
protected JPanel getMessagePanel() {
messagePanel = new JPanel(new GridLayout());
messagePanel.setBorder(BorderFactory.createTitledBorder(null,
"Status Console", TitledBorder.LEFT, TitledBorder.TOP,
new Font("null", Font.BOLD, 12), Color.BLUE));
final JScrollPane sp = new JScrollPane(getMessageTextArea());
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
messagePanel.add(sp);
return messagePanel;
}
protected JTextArea getMessageTextArea() {
messageTextArea = new JTextArea("", 10, 19);
messageTextArea.setEditable(false);
messageTextArea.setFont(new Font(null, Font.PLAIN, 20));
messageTextArea.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
DefaultCaret caret = (DefaultCaret) messageTextArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
return messageTextArea;
}
public void printRawMessage(String rawMessage) {
messageTextArea.append(rawMessage + "\n");
}
}
Add size constraints to your mainPanel in the initComponents method. For instance :
mainPanel.setMinimumSize(new Dimension(400, 400));
mainPanel.setPreferredSize(new Dimension(400, 400));
mainPanel.setMaximumSize(new Dimension(400, 400));

Categories