How do I correctly alter checkbox text rendering behaviour? - java

I am using the Nimbus look and feel.
I have two JCheckBoxes, and by default, the text is black when the JCheckBox is enabled, and greyed out when it is disabled. My new requirement is that the program should ignore the enabled state of the JCheckBox, and instead be greyed out when isSelected() is false, and display the text in a specified colour when isSelected() is true.
I have attempted to do this by:
Extending BasicCheckBoxUI
Overriding the paintText method
Copying the contents of BasicButtonUI.paintText() and modifying the behaviour
Calling setUI on the JCheckBoxes in question with an instance of my new UI class
private static class MyCheckBoxUI extends BasicCheckBoxUI
{
private Color selectedColor;
public MyCheckBoxUI( Color selectedColor )
{
this.selectedColor = selectedColor;
}
#Override
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text )
{
ButtonModel model = b.getModel();
FontMetrics fm = SwingUtilities2.getFontMetrics(b, g);
int mnemonicIndex = b.getDisplayedMnemonicIndex();
if( model.isSelected() )
{
/*** paint the text normally */
g.setColor( selectedColor );
SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
textRect.x + getTextShiftOffset(),
textRect.y + fm.getAscent() + getTextShiftOffset());
}
else
{
/*** paint the text disabled ***/
g.setColor(b.getBackground().brighter());
SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
textRect.x, textRect.y + fm.getAscent());
g.setColor(b.getBackground().darker());
SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
textRect.x - 1, textRect.y + fm.getAscent() - 1);
}
}
}
In the constructor of my JPanel, I have the following:
jCheckBox1.setUI( new MyCheckBoxUI( Color.red ) );
jCheckBox2.setUI( new MyCheckBoxUI( Color.black ) );
This appears to work as expected, except there is a side effect. Now, the check box will not render the tick in the box when it is selected like it used to (I did not expect this as I have only overridden the paintText method). What have I missed?
Additionally, the use of SwingUtilities2 disturbs me, as I am warned that it is an internal proprietary API that could be removed in a future release. Is there a better way to do this?

You need to play with the UIManager color properties...
Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
Object enabledTextForeground = UIManager.get("CheckBox.foreground");
UIManager.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
UIManager.put("CheckBox[Enabled].textForeground", disabledTextForeground);
UIManager.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);
This example will allow you to modify the values at a global level, meaning that every JCheckBox you create will have the same values
For example...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestNimbus {
public static void main(String[] args) {
new TestNimbus();
}
public TestNimbus() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
Object enabledTextForeground = UIManager.get("CheckBox.foreground");
UIManager.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
UIManager.put("CheckBox[Enabled].textForeground", disabledTextForeground);
UIManager.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);
JCheckBox cb1 = new JCheckBox("Option #1");
JCheckBox cb2 = new JCheckBox("Option #2");
JCheckBox cb3 = new JCheckBox("Option #3");
cb1.setSelected(true);
cb3.setEnabled(false);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
frame.add(cb1, gbc);
frame.add(cb2, gbc);
frame.add(cb3, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
To affect only given instance of JCheckBoxs, you would need to supply the overrides directly to each instance of the JCheckBox you want to effect...
The top three have their values overridden, while the bottom three remain unaffected and use the UI default values
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestNimbus {
public static void main(String[] args) {
new TestNimbus();
}
public TestNimbus() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
UIDefaults checkBoxDefaults = new UIDefaults();
Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
Object enabledTextForeground = UIManager.get("CheckBox.foreground");
checkBoxDefaults.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
checkBoxDefaults.put("CheckBox[Enabled].textForeground", disabledTextForeground);
checkBoxDefaults.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);
JCheckBox cb1 = new JCheckBox("Option #1");
JCheckBox cb2 = new JCheckBox("Option #2");
JCheckBox cb3 = new JCheckBox("Option #3");
JCheckBox cb4 = new JCheckBox("Normal #1");
JCheckBox cb5 = new JCheckBox("Normal #2");
JCheckBox cb6 = new JCheckBox("Normal #3");
configure(cb1, checkBoxDefaults);
configure(cb2, checkBoxDefaults);
configure(cb3, checkBoxDefaults);
cb1.setSelected(true);
cb4.setSelected(true);
cb3.setEnabled(false);
cb6.setEnabled(false);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
frame.add(cb1, gbc);
frame.add(cb2, gbc);
frame.add(cb3, gbc);
frame.add(cb4, gbc);
frame.add(cb5, gbc);
frame.add(cb6, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void configure(JCheckBox checkbox, UIDefaults uiDefaults) {
checkbox.putClientProperty("Nimbus.Overrides", uiDefaults);
// checkbox.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
}
});
}
}

Related

Disable JToggleButton without graying it

I want to set my JToggleButton in a disabled state, i.e. so that the user can't toggle it by clicking. I tried btn.setEnabled(false); but it grays out my icon and I don't want that. Is there any other method which doesn't gray out the icon, but doesn't let the user toggle the button?
but my own custom icon to be displayed.
You can also specify a "disabled icon" to be used by the toggle button. It could be the same Icon you use by default, or a slightly different icon.
When you specify your own Icon you don't get the greyed out effect.
You could disassociate the icon from the button and use appropriate layout constraints to provide a visual clue to the relationship instead, using a JLabel to display the icon instead, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
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);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
BufferedImage img = ImageIO.read(new File("/Volumes/Disk02/Dropbox/MegaTokyo/thumnails/2.jpg"));
JLabel label = new JLabel(new ImageIcon(img));
add(label, gbc);
JToggleButton btn = new JToggleButton("Click");
btn.setEnabled(false);
add(btn, gbc);
}
}
}
Personally, I'm thinking a JCheckBox might be more appropriate for this style
To allow the JToggleButton to be clicked only once.
If there are N JToggleButtons, declare N number of int class variables equal to 0.
(int jtbIntValue1=0, jtbIntValue1=0 ,...jtbIntValueN = 0)
Before allowing the user to press the JToggle button check if(jtbIntValueN != 0)
when a JToggle button is clicked update the corresponding JToggleButton int value equal to 1. (From jtbIntValueN = 0 to jtbIntValueN = 1).
public class Development1
{
int b1 = 0 ; // For one Button
public Development1()
{
...........
...........
JToggleButton jtb1 = new JToggleButton();
jtb1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e1)
{
if(b1!=1)
{
if(SwingUtilities.isRightMouseButton(e1) && e1.getClickCount() == 1)
{
jtb1.setIcon(icRight); // Or do whatever you want to
}
else if(SwingUtilities.isLeftMouseButton(e1) && e1.getClickCount() == 1)
{
jtb1.setIcon(icLeft);
}
}
b1 = 1;
}
});

Prompt for JTextField makes it shade gray

I am playing around with Prompt's with JTextFields,
Just one problem:
As you can see, The background is shaded gray a little, I even tried to set the background color to white and it is still gray. Heres my current code for setting a prompt:
final JTextField aText = new JTextField(6);
final JTextField bText = new JTextField(6);
PromptSupport.setPrompt("Digit", aText);
Is this correct? Thanks.
This seems to be a bug between PromptSupport and MaxOS X (or at least that's where I had problems)
I tried using PromprtSupport.setBackground but that didn't seem to work, so I ended up using PromptSupport.setBackgroundPainter instead
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.prompt.PromptSupport;
public class TestPrompt {
public static void main(String[] args) {
new TestPrompt();
}
public TestPrompt() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JTextField prompt = new JTextField(20);
PromptSupport.setPrompt("Go ahead, make my day", prompt);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.SHOW_PROMPT, prompt);
PromptSupport.setBackgroundPainter(new Painter() {
#Override
public void paint(Graphics2D g, Object object, int width, int height) {
g.setColor(UIManager.getColor("TextField.background"));
g.fillRect(0, 0, width, height);
}
}, prompt);
prompt.setOpaque(true);
JTextField noPrompt = new JTextField(20);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(4, 4, 4, 4);
frame.add(prompt, gbc);
frame.add(noPrompt, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This is a work around, not a solution as there are still some issues...

How to set Text like Placeholder in JTextfield in swing

I want to put some texts in text-Field when the form is load which instruct to user and when user click on that text-filed the texts remove automatically.
txtEmailId = new JTextField();
txtEmailId.setText("Email ID");
i have wrote above code but it display the text and keep as it is when user click on that text button i want to remove it.
is there any way to do this task?
I use to override the text fields paint method, until I ended up with more custom text fields then I really wanted...
Then I found this prompt API which is simple to use and doesn't require you to extend any components. It also has a nice "buddy" API
This has now been included in the SwingLabs, SwingX library which makes it even eaiser to use...
For example (this uses SwingX-1.6.4)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.swingx.prompt.PromptSupport;
public class PromptExample {
public static void main(String[] args) {
new PromptExample();
}
public PromptExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTextField bunnies = new JTextField(10);
JTextField ponnies = new JTextField(10);
JTextField unicorns = new JTextField(10);
JTextField fairies = new JTextField(10);
PromptSupport.setPrompt("Bunnies", bunnies);
PromptSupport.setPrompt("Ponnies", ponnies);
PromptSupport.setPrompt("Unicorns", unicorns);
PromptSupport.setPrompt("Fairies", fairies);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, bunnies);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIGHLIGHT_PROMPT, ponnies);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.SHOW_PROMPT, unicorns);
PromptSupport.setFontStyle(Font.BOLD, bunnies);
PromptSupport.setFontStyle(Font.ITALIC, ponnies);
PromptSupport.setFontStyle(Font.ITALIC | Font.BOLD, unicorns);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(bunnies, gbc);
frame.add(ponnies, gbc);
frame.add(unicorns, gbc);
frame.add(fairies, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
JTextField busqueda = new JTextField(20);
add(busqueda);
busqueda.setHorizontalAlignment(SwingConstants.CENTER);
if (busqueda.getText().length() == 0) {
busqueda.setText("Buscar");
busqueda.setForeground(new Color(150, 150, 150));
}
busqueda.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
busqueda.setText("");
busqueda.setForeground(new Color(50, 50, 50));
}
#Override
public void focusLost(FocusEvent e) {
if (busqueda.getText().length() == 0) {
busqueda.setText("Buscar");
busqueda.setForeground(new Color(150, 150, 150));
}
}
});
You can download this NetBeans plugin which you can use to create a placeholder with just one line.

Java - swing listen an action in a text field of a form

I would like to develop a form with some text field.
example:
Name
SecondName
the idea is that every text field have inside a text like:
Insert your name
Insert your second name
when you click on the first text field to write your name, the text "Insert your name" have to be deleted... the same have to happen for the second text field (SecondName).
The effect have to be this:
I think that i just need an Action on the text field that have to wake up when the user press on the mouse on the text field, it's possible?
Thank you
Take a look at PromptSupport in SwingLabs SwingX Library
For Example
When the fields have focus, the "prompt" will be hidden, but you can control this, making it shown until the user types something or highlight when focus is gained.
import java.awt.Dimension;
import java.awt.EventQueue;
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.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.swingx.prompt.BuddySupport;
import org.jdesktop.swingx.prompt.PromptSupport;
public class PromptSupportTest {
public static void main(String[] args) {
new PromptSupportTest();
}
public PromptSupportTest() {
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() {
JTextField firstName = new JTextField(10);
PromptSupport.setPrompt("First Name", firstName);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, firstName);
JTextField lastName = new JTextField(10);
PromptSupport.setPrompt("Last Name", lastName);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, lastName);
JTextField picture = new JTextField(10);
PromptSupport.setPrompt("Picture", picture);
PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, picture);
JButton browse = new JButton("...");
browse.setMargin(new Insets(0, 0, 0, 0));
browse.setContentAreaFilled(false);
browse.setFocusPainted(false);
browse.setFocusable(false);
browse.setOpaque(false);
// Add action listener to brose button to show JFileChooser...
BuddySupport.addRight(browse, picture);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
add(firstName, gbc);
add(lastName, gbc);
add(picture, gbc);
gbc.anchor = GridBagConstraints.CENTER;
add(new JButton("Ok"), gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
I've also added an example of BuddySupport which is part of the same API, which allows you to "buddy" another component with a text component. Here I've done the classic "file browser" combination, but I do "search" style fields like this all the time...
Take a look at Text Prompt for a simple solution that allows you to control when the text is displayed/hidden as well as the font/color of the text.
It will work with regular text components. In its simplest form you only need one extra line of code:
JTextField firstName = new JTextField(10);
TextPrompt tp = new TextPrompt("First Name", firstName);
see this example
import java.awt.Color;
import java.awt.Font;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JTextField;
public class HintTextField extends JTextField {
Font gainFont = new Font("Tahoma", Font.PLAIN, 11);
Font lostFont = new Font("Tahoma", Font.ITALIC, 11);
public HintTextField(final String hint) {
setText(hint);
setFont(lostFont);
setForeground(Color.GRAY);
this.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
if (getText().equals(hint)) {
setText("");
setFont(gainFont);
} else {
setText(getText());
setFont(gainFont);
}
}
#Override
public void focusLost(FocusEvent e) {
if (getText().equals(hint)|| getText().length()==0) {
setText(hint);
setFont(lostFont);
setForeground(Color.GRAY);
} else {
setText(getText());
setFont(gainFont);
setForeground(Color.BLACK);
}
}
});
}
}

Fill horizontal but scroll vertical

I am having a JFrame looking like this:
When it is resized, it will make the JComboBoxes adapt to the size of the JFrame like this:
which is what I want. But when I add a JScrollPane, the JComboBoxes no longer adapt:
Any ideas how to make the JComboBoxes still fill HORIZONTAL with the added JScrollPane?(making the JScrollPane only effect the VERTICAL scrolling)
public class FillHorizonScrollVertical extends JFrame {
private boolean withScroller = true;
private JPanel content;
public FillHorizonScrollVertical() {
// FILL = BOTH for JFrame
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
this.setLayout(new GridBagLayout());
// GridLayout = All content gets the same size
content = new JPanel(new GridLayout());
// ADD TO THE FRAME
JScrollPane scroller = new JScrollPane(content);
if (withScroller)
this.add(scroller, c);
else
this.add(content, c);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
// ADDING THE BOXES AFTER SETTING VISIBLE
addBoxes();
this.pack();
}
/**
* Create JComboBoxes and adding them to the JPanel
*/
private void addBoxes() {
// CREATE JCOMBOBOXES
JComboBox cb1 = new JComboBox();
cb1.addItem("");
cb1.addItem("aaaaaaaaaaaaaaaaaa");
JComboBox cb2 = new JComboBox();
cb2.addItem("");
JComboBox cb3 = new JComboBox();
cb3.addItem("");
content.add(cb1);
content.add(cb2);
content.add(cb3);
}
public static void main(String[] args) {
new FillHorizonScrollVertical();
}
}
You make use of the Scrollable interface which will allows you to flag of it should track the viewports width or height. In this case, you want to track the width, which will force the view to always be the same size as the view port...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Rectangle;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScrollableExample {
public static void main(String[] args) {
new ScrollableExample();
}
public ScrollableExample() {
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 JScrollPane(new TestPane()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
public TestPane() {
setLayout(new GridLayout());
JComboBox cb1 = new JComboBox();
cb1.addItem("");
cb1.addItem("aaaaaaaaaaaaaaaaaa");
JComboBox cb2 = new JComboBox();
cb2.addItem("");
JComboBox cb3 = new JComboBox();
cb3.addItem("");
add(cb1);
add(cb2);
add(cb3);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
Take a look at How to use scroll panes for more details
You can set the scrolling policy on the JScrollPane:
JScrollPane scroller = new JScrollPane(content,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
You might want to check out the Scrollable interface too, which allows fine-tuning of scrolling behaviour.
Solved by adding:
cb1.setPreferredSize(new Dimension(0, 30));
cb2.setPreferredSize(new Dimension(0, 30));
cb3.setPreferredSize(new Dimension(0, 30));

Categories