I have a JSpinner that displays decimal values from 0.0 to 999.0. It seems to work fine, except for when it displays a number in the editor box that is four-digits long, such as 123.4; it then cuts off part of the final digit because it is not long enough.
So my question is: Does anyone know how to increase the length of the editor window of a JSpinner?
Thanks!
You can get to the text field which in fact is a JFormattedTextField by
First calling getEditor() on your JSpinner to get the spinner's editor
cast the returned object to JSpinner.DefaultEditor
Then call getTextField() on this. Then you can set it's preferredSize if desired.
Edit: as noted by trashgod though, using a proper layout is paramount and being sure that the layouts you use are the best is probably the best way to solve this issue.
Edit 2: The above is wrong as setting the textfield's preferred size does nothing. You can however set the preferred size of the editor itself, and that works. e.g .,
import java.awt.Dimension;
import javax.swing.*;
public class SpinnerBigTextField {
private static void createAndShowGui() {
JSpinner spinner = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 999.0,
0.5));
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 100));
panel.add(spinner);
JComponent field = ((JSpinner.DefaultEditor) spinner.getEditor());
Dimension prefSize = field.getPreferredSize();
prefSize = new Dimension(200, prefSize.height);
field.setPreferredSize(prefSize);
JFrame frame = new JFrame("SpinnerBigTextField");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
The first Hovercraft answers is not bad at all. You can not change the size directly, but you can do something like this:
JComponent editor = mySpinner.getEditor();
JFormattedTextField tf = ((JSpinner.DefaultEditor) editor).getTextField();
tf.setColumns(4);
Where you can define the columns numbers showed by the editor. It will change the size of the spinner.
As FontMetrics vary from one platform to the next, it's better to rely on the component's own calculation of preferred size. This example shows a spectrum of JSpinner sizes for various min and max values. Note in particular that FlowLayout "lets each component assume its natural (preferred) size."
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
/** #see http://stackoverflow.com/questions/7374659 */
public class SpinnerTest extends Box {
private static final double STEP = 0.1d;
private static final String FORMAT = "0.0000000000";
public SpinnerTest(int axis) {
super(axis);
for (int i = 0; i < 8; i++) {
int v = (int) Math.pow(10, i);
this.add(genParamPanel((i + 1) + ":", -v, v));
}
}
private JPanel genParamPanel(String name, double min, double max) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
JLabel label = new JLabel(name, JLabel.TRAILING);
JSpinner js = new JSpinner(new SpinnerNumberModel(min, min, max, STEP));
js.setEditor(new JSpinner.NumberEditor(js, FORMAT));
panel.add(label);
panel.add(js);
return panel;
}
private void display() {
JFrame f = new JFrame("SpinnerTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new SpinnerTest(BoxLayout.Y_AXIS).display();
}
});
}
}
JSpinner spn=new JSpinner();
spn.setPreferredSize(new Dimension(100,25));
Here,look This is the easy Answer.
Changing the max value of a spinner will increase the size of the text box to accommodate the large number. If you do not wish to make the max value larger, i would recommend what #JorgeHortelano suggested...
JComponent editor = mySpinner.getEditor();
JFormattedTextField tf = ((JSpinner.DefaultEditor) editor).getTextField();
tf.setColumns(4);
Related
I am developing a simple application, and am currently working on the gui design using Swing. In my program I have a JPanel which I would like to have a background color black like so:
JPanel playerPanel = new JPanel();
playerPanel.setOpaque(true);
playerPanel.setBackground(Color.BLACK);
This code works fine. However, the problem is when I assign a Layout Manager to the panel:
JPanel playerPanel = new JPanel();
playerPanel.setOpaque(true);
playerPanel.setBackground(Color.BLACK);
playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.PAGE_AXIS));
For some reason, this makes the black color of the panel go away. This happens no matter where I place the .setLayout(...) command, before or after the .setBackground(...) and .setOpaque(true).
Why is this, and how do I work around this? How do I keep a black JPanel that uses a BoxLayout manager?
Verify that your panel's content is not obscuring the altered background. Resize the example below, which I've artificially enlarged, to see the effect.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/57785802/230513
*/
public class BoxTest {
public static final Random random = new Random();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new BoxTest().create();
}
});
}
void create() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.BLACK);
panel.add(Box.createVerticalGlue());
for (int i = 0; i < 4; i++) {
panel.add(new VariablePanel());
panel.add(Box.createVerticalGlue());
}
JFrame f = new JFrame("BoxTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setSize(f.getWidth(), f.getHeight() + 64);
}
}
/**
* A VariablePanel has a label showing its current size,
* as well as a variable number of text items.
*/
class VariablePanel extends JPanel {
private static final String text =
"Sed ut perspiciatis unde omnis iste natus error sit.";
private final JLabel sizeLabel = new JLabel("Size:");
public VariablePanel() {
this.setLayout(new GridLayout(0, 1));
this.add(sizeLabel);
int count = BoxTest.random.nextInt(5) + 1;
for (int i = 0; i < count; i++) {
this.add(new JLabel(text));
}
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int w = e.getComponent().getWidth();
int h = e.getComponent().getHeight();
sizeLabel.setText("Size: " + w + "\u00d7" + h);
}
});
}
}
Swing components (except JLabel) are opaque by default. This means:
you don't need playerPanel.setOpaque(true)
most components you add to the panel will be opaque and cover the background of your playerPanel.
Also, the BoxLayout respects the maximum size of any component you add to the panel. So if you add a component:
like a JButton which has a defined maximum size, you will see the button on top of the playerPanel and the background will surround the button.
like a JPanel, which does not have a defined maximum size, the panel will be resized to fill the entire area of the playerPanel and you won't see the background of the playerPanel.
If you want to see the background of the playerPanel show through a component added to the playerPanel, then you need to use setOpaque(false) on the component. For example:
JPanel child = new JPanel();
child.setOpaque( false );
playerPanel.add( child );
I have a GUI program which includes JLabels and JButtons and basically I want a layout that would help me display them as follows:
Label1 Button1
Label2 Button2
Label3 Button3
.....
Is there a layout that would allow me to achieve the above result?
I have looked at this example but is too complex and was wondering if there is anything automated that I can use?
This is one of the few things for which I'd recommend (a utility method and) GroupLayout as seen in this answer.
You can use GridLayout. Documentation here.
This is just for simplicity, and for your question. GUI is really dependent on what you would like to do and is really a thing that can be hardly automated..., and i don't think you only want those 6 elements on your GUI, but theoretically this will do it:
import java.awt.BorderLayout;
import java.awt.EventQueue;
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 GUITest {
private Box labelbox = new Box(BoxLayout.Y_AXIS);
//Y_AXIS means they are placed vertically in the box
private Box buttonbox = new Box(BoxLayout.Y_AXIS);
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
public void makeGUI1() {
for (int i = 1; i <= 3; i++) {
//if you want to save the references, you should make
//an ArrayList<JLabel> and add each of them to it
JLabel label = new JLabel("Label " + i);
labelbox.add(Box.createVerticalStrut(5));
//these are for giving the labels some extra space
//between them vertically to be in line with the buttons
labelbox.add(label);
labelbox.add(Box.createVerticalStrut(10)); //these are too
}
for (int i = 1; i <= 3; i++) {
//if you want to save the references, you should make
//an ArrayList<JButton> and add each of them to it
JButton button = new JButton("Button " + i);
buttonbox.add(button);
}
panel.add(labelbox, BorderLayout.EAST);
//you can find picture of each constant:
//http://download.java.net/jdk7/archive/b123/docs/api/java/awt/BorderLayout.html
panel.add(buttonbox, BorderLayout.WEST);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GUITest guitest = new GUITest();
guitest.makeGUI1();
}
});
}
}
You can also use obj.setBounds(LeftSpaceParameter,TopSpaceParameter) with which you can place the gui elements or objects at any position of your choice. You need to put the default layout to null
yet gridLayout is much easier. .
I'm trying to resize a label on MouseEnter, but on MouseExit, I want it back to the previous state. How would I do this?
I want the label to be bigger when it is moused over, but when the mouse exits, the label will back to normal size.
Can anybody explain to me how to do that?
If it's possible, I want to see the resize slowly.
This is the code:
package kk
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class ScrollGroup extends JPanel {
private static final int N = 8;
private static final int NN = N * N;
private static final int GAP = 5;
private static final int SIZE = 100;
public ScrollGroup() {
this.setLayout(new GridLayout(N, N, GAP, GAP));
for (int i = 0; i < NN; i++) {
final JLabel label = new JLabel();
label.setOpaque(true);
label.setBackground(Color.getHSBColor((float) i / NN, 1, 1));
label.setPreferredSize(new Dimension(SIZE, SIZE));
this.add(label);
label.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e) {
}
});
}
}
private void display() {
JFrame f = new JFrame("ScrollGroup");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane sp = new JScrollPane(this);
GroupLayout layout = new GroupLayout(f.getContentPane());
f.setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup().addComponent(sp)));
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup().addComponent(sp)));
f.pack();
f.setSize(N * SIZE, N * SIZE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScrollGroup().display();
}
});
}
}
I'm trying to resize a label in MouseEntred,
Define "resize".
You are adding your JLabels to a panel using a GridLayout. All the labels are already set to the maximum size permitted by the space available to the panel, so what do you expect the resize to do?
If you want it to appear that the label is getting bigger, then maybe you can assign a MatteBorder to each label. You can make the MatteBorder whatever size you want and then set the color equal to the background color of the panel.
If you want to animate then then you can use a Swing Timer. In the mouse#ntered you start the Timer. Every time the Timer fires you change the MatteBorder to be one less pixedl until the size is zero and you stop the Timer. On mouseExited, you just restore the default Border.
See the sections from the Swing tutorial on How to Use Timers and How to Use Borders for more information.
Trying to list the nodes in a JList so I can choose one from the list.
I have this code (and a lot more)...
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel row1 = new JPanel();
JPanel row2 = new JPanel();
JLabel flabel = new JLabel("Förbindelse från " + n1 +" till " + n2, JLabel.CENTER);
JScrollPane scroll = new JScrollPane(JLista);
DefaultListModel<Edge<Node>> Jlistan = new DefaultListModel<Edge<Node>>();
List<Edge<Node>> listan = listGraph.getEdgesBetween(n1,n2);
for (Edge<Node> listEdge : listan) {
Jlistan.addElement(listEdge);
}
JLista = new JList<Edge<Node>> (Jlistan);
JLista.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JLista.setLayoutOrientation(JList.HORIZONTAL_WRAP);
JLista.setVisibleRowCount(5);
JLista.setSize(100, 100);
getJlistVal();
row2.add(scroll);
row1.add(flabel);
add(row1);
add(row2);
}
...
public Edge<Node> getJlistVal(){
return JLista.getSelectedValue();
}
But when listing, i just get a little spot on the Jpanel, i think its a graphical dot, or a very very litte Jlist. :( cant publish a picture yet...
I thought it had to do with pixelsize but dont think so??
Do i have to specify size of the list??
The list to be displayed is a generic LIST as type Node. I have a method that i call, is the return type ok?
//thank you
-Help me StackOverflow. You are my only hope...
You create scroll instance with null list.
JScrollPane scroll = new JScrollPane(JLista);
Just move the line after
JLista = new JList<Edge<Node>> (Jlistan);
Not sure what you're doing wrong because your example won't compile without your other classes, But When I use the above code, adding in a bit of my own, it works. The only difference is I used a Box instead of BoxLayout, which is pretty much the same thing, just a Box uses a JPanel under the hood. I had to do this because it wasn't allowing be to use this from the JFrame subclass. You can test it
import javax.swing.Box;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
/**
*
* #author Paul SamSotha
*/
public class TestList extends JFrame {
public TestList() {
String[] list = {"Hello", "Jello", "Wello"};
JList JLista = new JList(list);
JPanel row1 = new JPanel();
JPanel row2 = new JPanel();
JLabel flabel = new JLabel("Förbindelse från ", JLabel.CENTER);
JScrollPane scroll = new JScrollPane(JLista);
JLista.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JLista.setLayoutOrientation(JList.HORIZONTAL_WRAP);
JLista.setVisibleRowCount(5);
JLista.setSize(100, 100);
row2.add(scroll);
row1.add(flabel);
Box box = Box.createVerticalBox();
box.add(row1);
box.add(row2);
add(box);
}
public static void createAndShowGui() {
JFrame frame = new TestList();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
"Do i have to specify size of the list??"
No, you can just call .pack() on the frame and let the pack do its magic
What you could do is, get the value in the getJlistVal() and return the value as a String.
String selected = jList1.getSelectedItem().toString();
and try to return that value. Tell me if it prints. I can't test it myself right now.
Just a suggestion to try, let me know how it goes.
Currently what your method getJListVal() is doing is, returning the value as an Element. Which may be your problem. Try returning it as a String, int or generic variable type, then try displaying it.
I want to set text above and below a JButton's icon. At the moment, in order to achieve this, I override the layout manager and use three JLabel instances (i.e. 2 for text and 1 for the icon). But this seems like a dirty solution.
Is there a more direct way of doing this?
Note -I'm not looking for a multi-line solution, I'm looking for a multi-label solution. Although this article refers to it as a multi-line solution, it actually seems to refer to a multi-label solution.
EXAMPLE
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public final class JButtonDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(new JMultiLabelButton());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static final class JMultiLabelButton extends JButton
{
private static final long serialVersionUID = 7650993517602360268L;
public JMultiLabelButton()
{
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JCenterLabel("Top Label"));
add(new JCenterLabel(UIManager.getIcon("OptionPane.informationIcon")));
add(new JCenterLabel("Bottom Label"));
}
}
private static final class JCenterLabel extends JLabel
{
private static final long serialVersionUID = 5502066664726732298L;
public JCenterLabel(final String s)
{
super(s);
setAlignmentX(Component.CENTER_ALIGNMENT);
}
public JCenterLabel(final Icon i)
{
super(i);
setAlignmentX(Component.CENTER_ALIGNMENT);
}
}
}
There is not way to split the text between the top/bottom of a JButton. This would involve custom painting.
Since I'm not sure of your exact requirement I'll just through out a few random ideas:
You can use a JButton with text & icon. There are methods in the API that allow you to controal where text is positioned relative to the icon. Then you would need a second label for the other line of text. Basically the same as you current solution but you only need two labels.
You could use the Text Icon and Compound Icon classes to create 1 Icon out of 3 separate Icons. Then you can just add the icon to a button.
Use a JTextPane. Its supports an insertIcon() method. So you could add a line of text, add the icon and then add the other line of text. You can play with the paragraph attributes of the text pane to align the text horizontally within the space if you don't want the text left justified. You can also play with the background color to make it look like a label.
Example using the CompoundIcon:
import java.awt.*;
import javax.swing.*;
public final class JButtonDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JButton button = new JButton();
CompoundIcon icon = new CompoundIcon(CompoundIcon.Axis.Y_AXIS,
new TextIcon(button, "Top Label"),
UIManager.getIcon("OptionPane.informationIcon"),
new TextIcon(button, "Bottom Label"));
button.setIcon( icon );
button.setFocusPainted( false );
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add( button );
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
you have two four options
1) use JLabel + Icon + Html (<= Html 3.2)
2) use XxxButtonUI and override all required methods from API
3) JLayeredPane with translucency???, another Layout with translucency, as JLabel or JComponent to the JButton,
4) there are around lots of Graphics SW that can to prepare Background as *.jpg for Icon, then is very simple to change whatever by Event, Action or actual setting for JButton
not correct way is looking for JLabel + Whatever instead of JButton, I think that is halfsized workaround
Find another LayoutManager, here: http://download.oracle.com/javase/tutorial/uiswing/layout/visual.html