Java. Prevent enlarging of Button - java

How to prevent Button from UpSize? I use a vertical Box with 2 lines, in first line → horizontal Box with many controls, in second line → Button, but button very enlarged, how to prevent this irritating behavior?
I was tried to set maximum size of button, it is works, but How to calculate this size correctly?
Sorry, I bad speak English.
Example:
import java.awt.Button;
import java.awt.Frame;
import java.awt.Label;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JProgressBar;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
public class TEST{
public static void main(String[] args){
Frame mainWindow = new Frame("hello");
Box vertBox = new Box(BoxLayout.Y_AXIS);
mainWindow.add(vertBox);
Box firstLine = new Box(BoxLayout.X_AXIS);
vertBox.add(firstLine);
SpinnerModel sm = new SpinnerNumberModel(100, 0, 200, 1);
for(int i = 0; i < 10; i++){
firstLine.add(new JSpinner(sm));
firstLine.add(new Label("Hello"));
}
Box secondLine = new Box(BoxLayout.X_AXIS);
vertBox.add(secondLine);
secondLine.add(new JProgressBar());
secondLine.add(new Button("RUN-THIS"));
mainWindow.pack();
mainWindow.setVisible(true);
}
}

Button, but button very enlarged, how to prevent this irritating behavior?
Don't use AWT components in a Swing application!
Swing components start with "J". You should be using JFrame, JLabel, JButton. This will fix your problem. A JButton will automatically calculate the maximum size equal to the preferred size and BoxLayout will respect this.
Also, class name should only start with a single upper case character. "TEST" should be "Test".

Related

Prevent JLabel with html from breaking line

Wondering if anyone knows how to disable line break when using html in JLabel.
Here is the code:
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.GridLayout;
public class Main
{
private static final int[] TEXT =
{ 0x05D0, 0x05B2, 0x05DC,
0x05B5, 0x05D9, 0x05DB,
0x05B6, 0x05DD
};
public static void main(String[] args)
{
String text = "";
for(int cp : TEXT)
text += Character.toString(cp);
String html = "<html>" + text + "</html>";
JLabel label = new JLabel(html);
JLabel msg = new JLabel("The text should at least go out to here.");
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2,1));
panel.add(label);
panel.add(msg);
JOptionPane.showMessageDialog(null, panel);
}
}
The bidi text breaks into two lines. I am trying to write html to a JTree node so it will support multiple font families. I can't get it to work with a JLabel. I'm thinking I might need to paint it in a cell renderer. I was hoping to get the html to work. It would make things a lot easier.
Any suggestions?
=== Edit ===
When my display setting in Windows is at 125% it breaks the line; however, when I change my display setting in Windows to 100% it does not break the line. Running 1920 x 1080 display. Anyone have any ideas? Or, is anyone able to repeat the breaking of the line?
=== Edit ===
Interestingly when I pass -Dsun.java2d.uiScale= with 1.0 or 2.0 it works. When I use 3.0, 4.0, 1.25 or 1.5 or 0.8 it does not work.
Well, I submitted a bug report. I managed to find a workaround that seems to work for all Windows Display Scale's but it is quite a hacky workaround. But it will be sufficient until the bug is fixed.
Here it is:
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.GridLayout;
import java.awt.font.FontRenderContext;
public class Main
{
private static final String TEXT =
"\u05D0\u05B2\u05DC\u05B5\u05D9\u05DB\u05B6\u05DD";
public static void main(String[] args)
{
JLabel label = new JLabel();
Graphics2D g2 = (Graphics2D)new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics();
FontRenderContext frc = g2.getFontRenderContext();
String[] split = TEXT.split("");
double width = 0;
for(String chr : split)
width += label.getFont().getStringBounds(chr, frc).getWidth();
double scale = Toolkit.getDefaultToolkit().getScreenResolution()/96.0;
String html = "<html><p style=\"width:"+Math.ceil(width/scale)+"px;\">" + TEXT + "</p></html>";
label.setText(html);
JLabel msg = new JLabel("The text should at least go out to here.");
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2,1));
panel.add(label);
panel.add(msg);
JOptionPane.showMessageDialog(null, panel);
}
}
Note: If I don't get the individual character lengths then the width doesn't come out right in a JTree node. Also, for some reason when I use bidi text the resultant width of the nodes JLabel is about twice the width of the text. Any shorter and it does not display correctly. However, the width is correct with Non-Bidirectional text. Also, width: does not work with span tag, it only works with p tag

Why don't size and preferredSize make this label bigger?

I'm building up a panel that will go in a larger program; the following program still illustrates my question, but it looks a bit more complicated than it absolutely has to because there are places I will add things later.
package sandbox;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SpacingPlay extends JFrame
{
private static final long serialVersionUID = 1L;
public static void main(String[] args)
{
SpacingPlay sp = new SpacingPlay();
sp.setVisible(true);
}
public SpacingPlay()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new DragNDropPanel();
add(panel);
pack();
}
class DragNDropPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public DragNDropPanel()
{
JPanel currentImagePanel = getCurrentImagePanel();
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
leftPanel.add(currentImagePanel);
// other things will go here; I cut them out to make this simpler.
setLayout(new BorderLayout());
// put things in a containing panel so that they aren't stretched being in the WEST part of a borderlayout.
JPanel leftContainingPanel = new JPanel();
leftContainingPanel.add(leftPanel);
add(leftContainingPanel, BorderLayout.WEST);
}
private Component createStandardSpace()
{
return Box.createRigidArea(new Dimension(0, 15));
}
private JPanel getCurrentImagePanel()
{
JPanel currentImagePanel = new JPanel();
currentImagePanel.setLayout(new BoxLayout(currentImagePanel, BoxLayout.PAGE_AXIS));
JLabel currentImageLabel = new JLabel("none");
currentImageLabel.setBorder(BorderFactory.createDashedBorder(Color.BLUE));
currentImageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
Dimension defaultLabelSize = new Dimension(150,150); // was expecting this to enlarge the label.
currentImageLabel.setPreferredSize(defaultLabelSize);
currentImageLabel.setSize(defaultLabelSize);
JButton clearButton = new JButton("Clear");
clearButton.setAlignmentX(Component.CENTER_ALIGNMENT);
clearButton.setBorder(BorderFactory.createLineBorder(Color.GREEN));
currentImagePanel.add(currentImageLabel);
currentImagePanel.add(createStandardSpace());
currentImagePanel.add(clearButton);
currentImagePanel.setBorder(BorderFactory.createLineBorder(Color.ORANGE));
return currentImagePanel;
}
}
}
I would like the currentImageLabel to be a standard size; I intend for it to get different images put into it during the program, and want it to get these without changing size. My idea was to set a size and preferred size and then scale the images I put there to that size.
However, the defaultLabelSize doesn't have the effect I thought it would. The label goes into a boxLayout panel; it is added, then a rigid space, then a button. I expected the label to be the default size, not shrunk to min allowed. I've put in colored borders to try to understand better what's happening; it appears that the preferred size is honored for the overall boxLayout panel, but not for the placement of the button below the label. EDIT: In other words, I want the button below the label to be placed below the label when the label is forced to be bigger. But the size I put on the label doesn't seem to work.
What do I need to do to fix the size of currentImageLabel?
Not 100% why the label is only sized to the text and not the (hard coded) preferred size. I have not been able to duplicate this behaviour using other combinations of panels and layout managers.
You are using pack so all components should be sized to their preferred sizes.
Dimension defaultLabelSize = new Dimension(150,150); // was expecting this to enlarge the label.
currentImageLabel.setPreferredSize(defaultLabelSize);
currentImageLabel.setSize(defaultLabelSize);
A few comments:
Setting the size will never work. The layout manager will always override the size/location based on the rules of the layout manager.
The layout manager can use (or ignore) the preferred, minimum and maximum sizes of a component. In the case of the BoxLayout is does attempt to use the preferred size but will respect the minimum and maximum sizes (depending on the available space in the parent panel).
What do I need to do to fix the size of currentImageLabel?
So, to achieve your desired goal of a fixed preferred size for the JLabel you can use:
Dimension defaultLabelSize = new Dimension(150,150); // was expecting this to enlarge the label.
currentImageLabel.setPreferredSize(defaultLabelSize);
currentImageLabel.setMinimumSize(defaultLabelSize);
currentImageLabel.setMaximumSize(defaultLabelSize);
//currentImageLabel.setSize(defaultLabelSize);
Edit:
was looking for why this doesn't seem to work
For further clarification, change your original code to:
currentImageLabel.setPreferredSize(defaultLabelSize);
System.out.println(currentImageLabel.getPreferredSize());
System.out.println(currentImageLabel.getMinimumSize());
System.out.println(currentImageLabel.getMaximumSize());
You will see the min/max sizes of the label are not affected.
From point 2 above you will see that the BoxLayout is respecting the maximum size.
Therefore, by also overriding the maximum size, you allow the label to be displayed at is preferred size.
However, when you calculate the preferred size of the "currentImagePanel" the ( hardcoded) preferred size of the label is used in the preferred size calculation of the panel, so that panel is displayed at the preferred size.
Another note. The "leftContainingPanel" is not needed. You can just add the "leftPanel" to the BorderLayout.WEST, since the BorderLayout will respect the width of the component you add.

Java - TitledBorder takes up too much vertical space (on Windows only)

I want to use a TitledBorder around a JTextField without it taking up too much vertical space.
In the top it applies way more spacing for title font than is needed. Also in the bottom there's a whopping 4 pixels I can't use.
This occurs only on Windows; on Mac OSX the example below looks fine while on W10 the JTextField content is horribly cropped.
Can I reduce this in any way?
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
public class MoreSpace {
static public void main(String args[]) {
EmptyBorder eb = new EmptyBorder(0, 0, 0, 0);
TitledBorder tb = new TitledBorder(eb, "Title");
Font font = new Font("dialog", Font.BOLD, 10);
tb.setTitleFont(font);
JTextField textField = new JTextField();
textField.setPreferredSize(new Dimension(300,26));
textField.setBorder(tb);
textField.setText("I cant breathe in here");
JOptionPane.showMessageDialog(null, textField, "",JOptionPane.PLAIN_MESSAGE);
}
}
Create a custom TitledBorder class(from package javax.swing.border) and reduce the maximum EDGE_SPACING as desired.
// Space between the border and the component's edge
static protected final int EDGE_SPACING = 2;
this means 2 pixels above and below as padding by default for the TitledBorder. This should explain the 4 pixels you are seeing.
Setting EDGE_SPACING to 0 will do what you are looking for. :)

How to set JButton to change color gradually when clicked

I wanted to create JButton to change color every time it is clicked but it doesn't change after second click.
It is strange because with Random().nextInt(250) instead of i it works.
What could be the problem?
Here's the code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout(100, 100));
JButton l = new JButton("Hello");
l.setBackground(new Color(245, 12, 53));
jp.add(l, BorderLayout.EAST);
jf.add(jp);
jf.setSize(200, 200);
jf.setLocationRelativeTo(null);
jf.setVisible(true);
l.addActionListener(new ActionListener() {
Integer i = new Integer(0);
Color c = new Color(150, 10, i);
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (i < 200) {
i += 50;
c = new Color(150, 10, i);
l.setBackground(c);
} else
i = 0;
}
});
}
}
I debugged your code and saw that the value of c change, every time I click the button. The first value is (r=150,g=10,b=50), then turns into (r=150,g=10,b=100), then (r=150,g=10,b=150) etc.
This means that the color is indeed changing. It's just that the difference is too small for you to notice.
So why does random.nextInt work?
With a random value in the blue component. The value can jump very suddenly from 0 to 200. The color difference is so large that your eyes can see it. But with a gradual change of 50 every time, you only notice it the first time.
Just test it with new Color(0, 0, i). I think that will make a bigger difference. It will go from black to blue!
Works fine for me.
Although the code should probably be something like:
if (i < 200)
i += 50;
else
i = 0;
c = new Color(150, 10, i);
l.setBackground(c);
Otherwise there will be one click that doesn't change the color.
You may want to consider using HSL Color this will allow you to change the Color in a more meaningful way by either changing the hue of the Color or shade/tone of the Color.

Java Swing: components not added to JPanel with JScrollPane

This code is just a silly example which I need to understand to solve a much bigger problem about another project I am working on: as you can see, in the for cycle, 23 buttons are supposed to be added to JPanel. As they cannot be shown all together I decided to add a JScrollPane but a strange thing happens: only 19 are shown and I do not understand why. The size matrix has 1 column for 23 rows so it is correct. Do you know why this happens? Thanks
package proveGUI;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import layout.TableLayout;
public class Main {
public static void main(String argv[]) {
JFrame jframe = new JFrame("Protocollo UTL");
//jframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
jframe.setSize(1200, 450);
JPanel body = new JPanel();
double[][] size = {
{0.05},
{0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05}
};
body.setLayout(new TableLayout(size));
for(int i=0; i<22; i++) {
body.add(new JButton(String.valueOf(i)), "0,"+String.valueOf(i));
}
JScrollPane scrollPane = new JScrollPane(body,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jframe.add(scrollPane);
jframe.setVisible(true);
}
}
The problem stems from you using size values between 0.00 and 1.00. These are interpreted as relative sizes/percentages, in this case 5%. That's why it's showing 20 rows only (0 to 19 inclusive). Try using "50.0" instead and the problem goes away. Or use TableLayout.PREFERRED.
I don't know much about TableLayout because I've didn't ever use it. If it is your first experience with Swing, try the common Swing Layouts.
For your case, you can simple try
body.setLayout(new BoxLayout(body, BoxLayout.Y_AXIS)); // instead of TableLayout
When U'll understand how layouts work in Swing, use GridBagLayout, because it is the most adjustable layout.

Categories

Resources