Controlling the scroll pane in JComboBox

A

Aaron Fude

Hi,

I'm having all sorts of problems controlling dimensions in Swing with
LayoutManagers. (Is there an article somewhere about this?)

Here's an example. I have a custom ComboBox that narrows down the
choices depending on the input. I implement ListCellRenderer, which:
if there is no input, returns a JLabel; if there is input, it returns
a panel with three labels with the middle one "highlighting" the
selection. You can see the demo here:

file:///C:/pg/InstantDemo/Projects/ComboBox.html

Question: How come the scroll bars appear for the labels but not for
the panels?

The panel uses a BoxLayout.

If you need more information, I'm happy to provide it.

Thanks!
 
A

Aaron Fude

Good suggestion, Pete! The code is below.

I welcome comments about all aspects of my code, but for now I'm
mostly interested in why there are no scroll bars when there is a
query and a panel is used for rendering...

Many thanks in advance,

Aaron

package pmg;

import java.awt.*;

import javax.swing.*;
import javax.swing.event.*;

import java.awt.event.*;
import java.util.ArrayList;

public class ChoiceGui extends JComboBox {
private ArrayList<String> myList = new ArrayList<String>();
private boolean mySettingItem = false;
private boolean myRespondingToChangedQuery = false;


public static void main(String[] args) {

ArrayList<String> choices = new ArrayList<String>();
choices.addAll(java.util.Arrays.asList(
"Hello;Hello, World!;A very looooooooooooooong String;Very
Slow;Bad dog, bad!".split(";")));

JFrame frame = new JFrame("Choice");
frame.getContentPane().add(new ChoiceGui(choices));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}

public ChoiceGui(ArrayList<String> choices) {

myList = choices;

setEditor(new Editor());
setRenderer(new Renderer3());
setBackground(Color.getHSBColor(1f/6, .2f, 1f));

this.setPreferredSize(new Dimension(150, 22));

for (int s = 0; s < myList.size(); s++)
this.addItem(myList.get(s));

this.setSelectedIndex(-1);

this.setEditable(true); // This is when the first setItem() is
called!
}


public class Editor implements ComboBoxEditor {
private JTextField myTextField = new JTextField();

public void addActionListener(ActionListener l)
{ myTextField.addActionListener(l); }
public void removeActionListener(ActionListener l) { }
public void setItem(Object item) {
if (myRespondingToChangedQuery)
return;

System.out.println("setItem called!!!");
mySettingItem = true;
if (item != null) {
myTextField.setText(item.toString());
myTextField.setCaretPosition(0);
}
else if (!myRespondingToChangedQuery) // The value of
SuperChoice changed for a different reason, so the query must be
reset.
myTextField.setText("");

mySettingItem = false;
}
public void selectAll() { myTextField.selectAll(); }
public Object getItem() { return null; }
public Component getEditorComponent() { return myTextField; }


public Editor() {
myTextField.getDocument().addDocumentListener(new
DocumentListener() {
public void dodo() {

javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
myRespondingToChangedQuery = true;

String q =
((JTextField)getEditor().getEditorComponent()).getText();
removeAllItems();
for (int i = 0; i < myList.size(); i++)
if
(myList.get(i).toUpperCase().contains(q.toUpperCase()))
addItem(myList.get(i));

setPopupVisible(true);

myRespondingToChangedQuery = false;

}
});
}

public void changedUpdate(DocumentEvent e) {
if (mySettingItem)
return;
dodo();
}
public void insertUpdate(DocumentEvent e) {
if (mySettingItem)
return;
dodo();
}
public void removeUpdate(DocumentEvent e) {
if (mySettingItem)
return;

dodo();
}
});

}
}
class Renderer3 implements ListCellRenderer {
JPanel panel = new JPanel();
JLabel label = new JLabel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();

public Renderer3() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

panel.add(label1);
panel.add(label2);
panel.add(label3);

panel.setOpaque(true);
panel.setBackground(Color.RED);
Font font = label1.getFont();
label.setFont(new Font(font.getName(), Font.PLAIN,
font.getSize()-2));
label1.setFont(new Font(font.getName(), Font.PLAIN,
font.getSize()));
label2.setFont(new Font(font.getName(), Font.BOLD,
font.getSize()));
label3.setFont(new Font(font.getName(), Font.PLAIN,
font.getSize()));

label.setOpaque(true);
panel.setBackground(Color.getHSBColor(1f/6, .2f, 1f));
}

public Component getListCellRendererComponent(JList list, Object
value, int index, boolean isSelected, boolean cellHasFocus) {
String str = (value!=null)?value.toString():"null";
String q =
((JTextField)getEditor().getEditorComponent()).getText();
if (q.length() != 0 &&
str.toUpperCase().indexOf(q.toUpperCase()) != -1) {
int start = str.toUpperCase().indexOf(q.toUpperCase());
label1.setText(str.substring(0, start));
label2.setText(str.substring(start, start + q.length()));
label3.setText(str.substring(start + q.length()));
panel.setBackground(isSelected?
list.getSelectionBackground():list.getBackground());
panel.setForeground(isSelected?
list.getSelectionForeground():list.getForeground());

return panel;
}
else {
Font font = label.getFont();
label.setFont(new Font("Dialog", Font.PLAIN, 12));
label.setBackground(isSelected?
list.getSelectionBackground():list.getBackground());
label.setForeground(isSelected?
list.getSelectionForeground():list.getForeground());
label.setText(" " + str);
return label;
}

}
}

}
 
C

cherryx

Use the setUI() method
and an extended BasicComboBoxUI class.

also import javax.swing.plaf.basic.*;

regards

Chinthaka Weerasinghe - Your friendly java tutor
(e-mail address removed)



package pmg;

import java.awt.*;

import javax.swing.*;
import javax.swing.event.*;

import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.plaf.basic.*;

public class ChoiceGui extends JComboBox {
private ArrayList<String> myList = new ArrayList<String>();
private boolean mySettingItem = false;
private boolean myRespondingToChangedQuery = false;

public static void main(String[] args) {

ArrayList<String> choices = new ArrayList<String>();
choices.addAll(java.util.Arrays.asList("Hello;Hello, World!;A very
looooooooooooooong String;Very Slow;Bad dog, bad!".split(";")));

JFrame frame = new JFrame("Choice");
frame.getContentPane().add(new ChoiceGui(choices));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}

public ChoiceGui(ArrayList<String> choices) {

myList = choices;

setEditor(new Editor());
setRenderer(new Renderer3());
setBackground(Color.getHSBColor(1f/6, .2f, 1f));

this.setPreferredSize(new Dimension(150, 22));

for (int s = 0; s < myList.size(); s++)
this.addItem(myList.get(s));

this.setSelectedIndex(-1);

this.setEditable(true); // This is when the first setItem() is
called!
setUI(new myComboUI());
}

public class myComboUI extends BasicComboBoxUI{
protected ComboPopup createPopup(){
BasicComboPopup popup = new BasicComboPopup(comboBox){
protected JScrollPane createScroller() {
return new JScrollPane( list,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED );
}// end of method createScroller
};
return popup;
}// end of method createPopup
}// end of inner class myComboUI



public class Editor implements ComboBoxEditor {
private JTextField myTextField = new JTextField();

public void addActionListener(ActionListener l)
{ myTextField.addActionListener(l); }
public void removeActionListener(ActionListener l) { }
public void setItem(Object item) {
if (myRespondingToChangedQuery)
return;

System.out.println("setItem called!!!");
mySettingItem = true;
if (item != null) {
myTextField.setText(item.toString());
myTextField.setCaretPosition(0);
}
else if (!myRespondingToChangedQuery) // The value of SuperChoice
changed
// for a different reason, so the
// query must be reset.
myTextField.setText("");

mySettingItem = false;
}
public void selectAll() { myTextField.selectAll(); }
public Object getItem() { return null; }
public Component getEditorComponent() { return myTextField; }

public Editor() {
myTextField.getDocument().addDocumentListener(new
DocumentListener() {
public void dodo() {

javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
myRespondingToChangedQuery = true;

String q =
((JTextField)getEditor().getEditorComponent()).getText();
removeAllItems();
for (int i = 0; i < myList.size(); i++)
if (myList.get(i).toUpperCase().contains(q.toUpperCase()))
addItem(myList.get(i));

setPopupVisible(true);

myRespondingToChangedQuery = false;

}
});
}

public void changedUpdate(DocumentEvent e) {
if (mySettingItem)
return;
dodo();
}
public void insertUpdate(DocumentEvent e) {
if (mySettingItem)
return;
dodo();
}
public void removeUpdate(DocumentEvent e) {
if (mySettingItem)
return;

dodo();
}
});

}
}
class Renderer3 implements ListCellRenderer {
JPanel panel = new JPanel();
JLabel label = new JLabel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();

public Renderer3() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));

panel.add(label1);
panel.add(label2);
panel.add(label3);

panel.setOpaque(true);
panel.setBackground(Color.RED);
Font font = label1.getFont();
label.setFont(new Font(font.getName(),
Font.PLAIN,font.getSize()-2));
label1.setFont(new Font(font.getName(),
Font.PLAIN,font.getSize()));
label2.setFont(new Font(font.getName(), Font.BOLD,font.getSize()));
label3.setFont(new Font(font.getName(),
Font.PLAIN,font.getSize()));
label.setOpaque(true);
panel.setBackground(Color.getHSBColor(1f/6, .2f, 1f));
}

public Component getListCellRendererComponent(JList list, Object
value, int index, boolean isSelected, boolean cellHasFocus) {
String str = (value!=null)?value.toString():"null";
String q =
((JTextField)getEditor().getEditorComponent()).getText();
if (q.length() != 0 && str.toUpperCase().indexOf(q.toUpperCase()) !
= -1) {
int start = str.toUpperCase().indexOf(q.toUpperCase());
label1.setText(str.substring(0, start));
label2.setText(str.substring(start, start + q.length()));
label3.setText(str.substring(start + q.length()));
panel.setBackground(isSelected?
list.getSelectionBackground():list.getBackground());
panel.setForeground(isSelected?
list.getSelectionForeground():list.getForeground());

return panel;
}
else {
Font font = label.getFont();
label.setFont(new Font("Dialog", Font.PLAIN, 12));
label.setBackground(isSelected?
list.getSelectionBackground():list.getBackground());
label.setForeground(isSelected?
list.getSelectionForeground():list.getForeground());
label.setText(" " + str);
return label;
}
}
}
}
 
A

Aaron Fude

Thanks!

But can you explain why it makes a difference?
Why would, in the original solution, the scroll bars not appear for
JPanels but appear for the labels?

Also, how do I control the numbers of rows that is shown in the popup?

Thanks!
 
A

Andrew Thompson

Hi,

I'm having all sorts of problems controlling dimensions in Swing with
LayoutManagers. (Is there an article somewhere about this?)


--
Patty T.


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"This is Preservation Month.
I appreciate preservation.
It's what you do when you run for president.
You gotta preserve."

--- Adolph Bush,
Speaking during "Perseverance Month"
at Fairgrounds Elementary School in Nashua, N.H.
As quoted in the Los Angeles Times, Jan. 28, 2000
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top