Java-Eclipse-Trying to use JTextArea - java

I have spent the last few hours of the past two days trying to figure out why I can't get my GUI to work right. Here is where I come to all of you to see if you can help me at all.
Now what i'm trying to do is a Text Based game, simple right? Well I want to use buttons lined up on the left side of the screen, with your health and all that fun stuff on the bottom, with the main meat of the game, the TEXT, in the center, but no matter what i did i couldn't get it to fit right, then i stumbled upon pack() so i tried it, and yea...it did what it was supposed to do, sadly right now i have ONE WORD and the screen is tiny, any ideas as to how i could make the screen bigger, and remain big?
Going to edit this and throw you bits and peices of my code, including for the textarea (please note i have been using java for a whopping two days while not at work)
JTextArea textarea = new JTextArea("example");
frame.add(textarea);
//frame.pack();
And here i have pack commented out because i'm playing around with it.
Anything else you guys want to take a peek at?

There are so many things that could be going wrong, without more code it's difficult to pin point an exact problem...
A few things jump to mind...
Use appropriate layout managers, even compound layout managers
Provide additional information to the JTextArea to allow it to define a usable space, such as rows and columns
Add the JTextArea to a JScrollPane to ensure that it doesn't suddenly occupy more space then is actually available
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestLayout21 {
public static void main(String[] args) {
new TestLayout21();
}
public TestLayout21() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JPanel actions = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill= GridBagConstraints.HORIZONTAL;
actions.add(new JButton("Walk"), gbc);
actions.add(new JButton("Run"), gbc);
actions.add(new JButton("Jump"), gbc);
actions.add(new JButton("Eat"), gbc);
actions.add(new JButton("Drink"), gbc);
add(actions, BorderLayout.WEST);
add(new JProgressBar(), BorderLayout.SOUTH);
JTextArea textArea = new JTextArea(20, 40);
add(new JScrollPane(textArea));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}

You could try setting the preferred size on your objects or the panel/frames themselves:
myPanel.preferredSize(new Dimension(1000,500));
or
myFrame.preferredSize(new Dimension(1000,500));
or
myTextArea.preferredSize(new Dimension(300,200));

Pack will indeed just make your frame or panel only as big as needed to fit the components who are in it. Try preferredSize() method, and maybe post some code if it still isn't working.

Related

How to draw two JPanels on top of each other?

I am currently working on a N-Body simulation and I have made particles move on a black screen. My current problem is that there is no way of controlling it.
My plan:
Each color stands for a different JPanel. The blue one should contain the buttons and text fields, the red one the viewport.
But with my small knowledge in Java, I didn't succeed in creating this. I first tried with setBounds and setLayoutManager(null), in vain.
My structure goes like that:
Window class extends JFrame
Simulation class creating blueJPanel class (extends JPanel) and redJPanel,
adds them to the window.
But this is garbage code... So how would you draw these simple panels on top of each other?
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
As I said in my comment, you create two JPanels. Here's an example.
Here's the complete runable code to create this example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BorderLayoutExampleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorderLayoutExampleGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("BorderLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButtonPanel(), BorderLayout.NORTH);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 100));
panel.setBackground(Color.blue);
// Add the buttons and text fields
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 380));
panel.setBackground(Color.red);
// Add the drawing code
return panel;
}
}

Java Swing macOS buttons are grey instead of blue when selected

I have a bug in my Swing program where the background of JButton and JToggleButton components is grey instead of blue, when the component is selected. Here is a screenshot of the issue on a JToggleButton, but the same issue occurs when pressing down on a JButton.
I have tried manually setting the background with
button.setBackground(Color.BLUE);
button.setOpaque(true);
but that just paints a small border around the button:
Also added button.setBorderPainted(false); which removes the border but also removes the macOS button look entirely + gives the text a darker background color:
It looks like the border (AquaButtonBorder) blocks the background color from changing or something? Because simply setting button.setBackground(Color.BLUE); does absolutely nothing.
The look and feel is set to UIManager.getSystemLookAndFeelClassName(), but also tried UIManager.getCrossPlatformLookAndFeelClassName() which was unsuccessful.
Java specifications: running on Java 11, but the same issue persists in Java 17
System specifications: M1 MacBook Pro, macOS version 12.4
Sooo, I spent WAY to much time digging into the source code for the "Aqua" look and feel, and I found that the AquaButtonUI has a "button type" client property which is used to (amongst a couple of other things) determine the border type.
Sooo, I pulled all the internal "types" and did a quick test...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("user.dir"));
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String[] keys = new String[]{
"toolbar",
"icon",
"text",
"toggle",
"combobox",
"comboboxInternal",
"comboboxEndCap",
"square",
"gradient",
"bevel",
"textured",
"roundRect",
"recessed",
"well",
"help",
"round",
"texturedRound",
"segmented-first",
"segmented-middle",
"segmented-last",
"segmented-only",
"segmentedRoundRect-first",
"segmentedRoundRect-middle",
"segmentedRoundRect-last",
"segmentedRoundRect-only",
"segmentedTexturedRounded-first",
"segmentedTexturedRounded-middle",
"segmentedTexturedRounded-last",
"segmentedTexturedRounded-only",
"segmentedTextured-first",
"segmentedTextured-middle",
"segmentedTextured-last",
"segmentedTextured-only",
"segmentedCapsule-first",
"segmentedCapsule-middle",
"segmentedCapsule-last",
"segmentedCapsule-only",
"segmentedGradient-first",
"segmentedGradient-middle",
"segmentedGradient-last",
"segmentedGradient-only",
"disclosure",
"scrollColumnSizer"
};
public TestPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new BorderLayout());
JPanel contentPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (String key : keys) {
JToggleButton btn = new JToggleButton(key);
btn.putClientProperty("JButton.buttonType", key);
contentPane.add(btn, gbc);
}
add(new JScrollPane(contentPane));
}
}
}
Generally, I found that bevel and segmented-only will achieve your desired result (although segment-first/middle/last looks interesting)

jPanel and jButton customization

I'm trying to learn how to code Conway's game of life in Java, and I'm getting stuck creating the GUI. I want to make a JPanel within the JFrame, with a larger border at South, and then two buttons in the south border, one for "Play" and one for "Restart." But the Design element won't let me resize or move anything around. I was able to resize the JPanel by going into the code and creating a larger border in the South, but I can't figure out how to resize the JButton. Any ideas?
(I'm using Eclipse Kepler...I hear NetBeans is better at this kind of stuff, should I just ditch Eclipse and try it with NetBeans?)
Here's my code so far:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JButton;
public class GameOfLife extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameOfLife frame = new GameOfLife();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GameOfLife() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 518, 508);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(10, 10, 50, 10));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
panel.setBackground(Color.GRAY);
contentPane.add(panel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
contentPane.add(btnNewButton, BorderLayout.SOUTH);
}
}
Basically, instead of doing BorderLayout.SOUTH, I want to manually place it where I want it within the frame. I'd also love to be able to do that with the JPanel--the whole North/West/South/East/Center thing in general seems very constricting. What's the way around it?
Maybe you should look at Swing Layouts in Java documentation:
A Visual Guide to Layout Managers
And the layout which is able to give you the most flexibility is the GridBagLayout but you will write much code to display the User Interface as your needs.
You will have a detailled way to go with the following official tutorial:
How to Use GridBagLayout
In your code, you are using the simple BorderLayout which is very simple but not so much configurable.

Fixed sized items in Swing

I am rather new to this whole Swing, but nevertheless it already got me quite annoyed.
I am trying to do something simple, that behaves like WPF's list with custom item template. That is, item are of fixed size and as it overflows the given area a scroll bar pops up.
And I've been trying and trying, but I just can't get it to work. The closest I got was with BoxLayout, the problem there however, is that if there are too few items to take available space, they get stretched -.-
I bet there is some simple way to achieve that, I just don't know about. Thanks in advance.
Here's the code I got (java):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class App
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new MainFrame();
}
});
}
}
class MainFrame extends JFrame
{
private JPanel itemsPanel;
private JButton addButton;
public MainFrame()
{
// create components
itemsPanel = new JPanel();
addButton = new JButton("Add");
// layout
itemsPanel.setLayout(new BoxLayout(itemsPanel, BoxLayout.Y_AXIS));
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttons.add(addButton);
setLayout(new BorderLayout());
add(new JScrollPane(itemsPanel), BorderLayout.CENTER);
add(buttons, BorderLayout.SOUTH);
// actions
addButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent arg0)
{
itemsPanel.add(new SampleItem());
itemsPanel.revalidate();
}
});
// frame size and close action
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension size = new Dimension(300, 300);
setMinimumSize(size);
setSize(size);
setVisible(true);
}
}
class SampleItem extends JPanel
{
public SampleItem()
{
setBorder(BorderFactory.createLineBorder(Color.black));
setPreferredSize(new Dimension(200, 100));
}
}
EDIT:
I ended up writing custom renderer and editor thanks to rcook's answer.
EDIT2:
Eh, after turning it in, I got scolded really badly for this... Apparently the problem is that JScrollPane resizes viewport so that the control fills all available space and the solution is to create JPanel implements Scrollable and return false in public boolean getScrollableTracksViewportHeight(). Oh well, I hope someone will find it useful, editors are just so much pain.
Use a JList, put it inside a JScrollPane, put that within a pane in the middle part of a BorderLayout; BorderLayout is the default for a JFrame, so you may not need to create one. Put the lower button on the bottom portion of the BorderLayout.

Unicode characters in javax.swing only display when using the default font-size

I'm trying to display a few Unicode characters inside of a jLabel. Take for example, the "degrees Fahrenheit" character (℉ or "\u2109"). This character is only being displayed when I use the default font-size, which happens to be 11. When I change the font-size, the character is replaced with an empty square. I've tried several different sizes and several different fonts that supposedly support a wide range of unicode characters. Can anyone tell me why Swing only displays this unicode character under a specific font-size?
Proof:
All the code related to the UI is auto-generated by NetBeans using the designer, but here is how I'm supplying the text to the jLabel:
private void btnConvertActionPerformed(java.awt.event.ActionEvent evt) {
if(optToFarenheit.isSelected())
{
int tempFahr = (int)((Double.parseDouble(txtInput.getText()))
* 1.8 + 32);
lblResult.setText(tempFahr + " ℉");
//lblResult.setText(tempFahr + " \u2109"); <-- Tried this too
}
}
Instead of "changing" the font, which might lead you to a font that is incompatible, try simply changing the label's "default" font's size
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestUnicodeFont {
public static void main(String[] args) {
new TestUnicodeFont();
}
public TestUnicodeFont() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
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;
JLabel normal = new JLabel("Normal - ?");
JLabel byCode = new JLabel("Normal code - \u2109");
JLabel normalLarger = new JLabel("Large - ?");
normalLarger.setFont(normalLarger.getFont().deriveFont(48f));
JLabel byCodeLatger = new JLabel("Large code - \u2109");
byCodeLatger.setFont(byCodeLatger.getFont().deriveFont(48f));
add(normal, gbc);
add(byCode, gbc);
add(normalLarger, gbc);
add(byCodeLatger, gbc);
}
}
}
When changing the font in Netbeans for you component, there is a checkbox in the font dialog "Derive the font from the default font", make sure it is selected and it should work.
Or you have to make sure the new font does support unicode characters. For example, "Arial Unicode MS" should work as well (it is mentioned on your wiki page)/
I solved a similar problem, using symbols in the text of a label in the NetBeans editor, by first produce the text with symbols in Word and simply copy that in the text field of the label.

Categories