How can one resize the scrollelements of a JComboBox? - java

I have a few JComboBoxes in my programm. I want to change the size of the scrollbar and the arrow button in the way that they are much wider. I need that because I want to use the programm on a Windows tablet and it is too small for a finger to work with.
Is there any possibility to do that?
JComboBox comboBox;
comboBox = new JComboBox(list_apple_device.toArray());
comboBox.setSelectedItem(null);
comboBox.setFont(schrift);
comboBox.setBounds(1568, 329, 306, 43);
comboBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
// TODO Auto-generated method stub
textField.setText(""+e.getItem());
}
});
getContentPane().add(comboBox);
That's my code.

You can use the UIManger to control the width of the scrollbar:
UIManager.put("ScrollBar.width", new Integer(50));
You would execute that code BEFORE you create the combo box.

it's not so easy, but there is a solution, you have to subclass jcombobox...
You have to subclass JComboBox to get access to the ComboBoxUI. To do so you set your own custom ComboBoxUI during object instanciation (we make changes in the all constructors, see init() in CustomComboBox.
The ComboBoxUI is required to get access to the ComboboxPopup. We replace simply the default ComboboxPopup with our custom ComboboxPopup. You have to know that the ComboboxPopup is responsible for the creation of the drop-down-menu, that pops up when you click on the button.
then we finally can adjust the JScrollPane from the Popup, we grab the vertical JScrollBarand alter its appearance (setting a custom width).
public class CustomComboBox<T> extends JComboBox<T> {
public CustomComboBox() {
super();
init();
}
public CustomComboBox(ComboBoxModel<T> aModel) {
super(aModel);
init();
}
public CustomComboBox(T[] items) {
super(items);
init();
}
public CustomComboBox(Vector<T> items) {
super(items);
init();
}
public void init(){
CustomComboBoxUI ccbui = new CustomComboBoxUI();
setUI(ccbui);
}
}
this is the custom ComboboxUI that grants you acces to the ComboboxPopup (quite simple):
public class CustomComboBoxUI extends BasicComboBoxUI{
protected ComboPopup createPopup() {
return new CustomComboBoxPopup( comboBox );
}
}
thankgod the custom ComboboxPopup needs just the basic constructor overriden and only one method changed (sets the size of the scrollpan to 40px):
public class CustomComboBoxPopup extends BasicComboPopup{
public CustomComboBoxPopup(JComboBox combo) {
super(combo);
}
#Override
protected void configureScroller() {
super.configureScroller();
scroller.getVerticalScrollBar().setPreferredSize(new Dimension(40, 0));
}
}
to set the size of the combobox you simply need to adjust its size
String[] data = new String[]{"a","b","c","d","e","f","g","h","i"};
CustomComboBox<String> comboBox = new CustomComboBox(data);
comboBox.setPreferredSize(new Dimension(50,50)); //set the size you wish
see also setting size of scroller and setting size of combobox for further help...

Related

How do I return an object to a previous frame that is still open?

I have a main frame which has an array list containing a list of items for an order. I then have a button which creates a new window that has a form allowing the user to pick multiple options for an item, this information is then put into an object.
I want to return this object back to the original frame so that I can add it to the order array list. However I'm not sure how to go about this as my frames have their code auto generated as I'm using netbeans.
You should use a listener (interface) system. Create an interface and implement it in your main frame, when you create your second frame you pass the first one as parameter. By this way you will be able to call a method, let's say, onItemSelected in the second frame whenever you want in an elegant way.
Using interfaces is more convenient, you can have multiple listener.
There is an example:
class MyFrame extends JFrame implements ItemSelectedListener {
void onButtonClick() {
new SecondFrame(this);
}
#Override
public void onItemSelected(List<String> items) {
// do your stuff with the selected items here
}
}
interface ItemSelectedListener {
void onItemSelected(List<String> items);
}
class SecondFrame extends JFrame {
private ItemSelectedListener itemSelectedListener;
private JTextField name;
private JButton buttonOk;
SecondFrame(ItemSelectedListener listener) {
itemSelectedListener = listener;
name = new JTextField();
buttonOk = new JButton("OK");
getContentPane().add(name);
getContentPane().add(buttonOk);
buttonOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<String> myFormItems = new ArrayList<>();
// fulfill your list with all informations that you need
myFormItems.add(name.getText());
// notify your main frame that the user finished to complete the form
itemSelectedListener.onItemSelected(myFormItems);
}
});
}
}

How to call an Action from a different class in Java

How would I call an Action from another class in Java? I got a CloseTabButton class online that allows a simple close tab button on each JTabbedPane, but when the tab is closed, I would like a dialog to pop up based on information (if file is not saved, ask to save it, etc.). This is the file:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class CloseTabButton extends JPanel implements ActionListener {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
close.addActionListener(this);
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
#Override
public void actionPerformed(ActionEvent e) {
int i = pane.indexOfTabComponent(this);
String fileName = pane.getToolTipTextAt(i);
// Where I want to ask if user wants to save, etc.
if (fileName == "Untitled") {
// Do stuff
}
pane.remove(i); // Removes the tab
// If tab count < 1, then disable the save and save as buttons on menu
if (pane.getTabCount() < 1) {
JFrame frame = (JFrame) pane.getParent().getParent().getParent().getParent().getParent(); // Yes, there is that many in my code to get the parent JFrame
int menuCount = frame.getJMenuBar().getMenuCount();
for (int a = 0; a < menuCount; a++) {
int itemCount = frame.getJMenuBar().getMenu(a).getItemCount();
for (int b = 0; b < itemCount; b++) {
Component component = frame.getJMenuBar().getMenu(a).getMenuComponent(b);
if (!(component instanceof JSeparator)) {
// Not a seperator
String itemName = frame.getJMenuBar().getMenu(a).getItem(b).getAccessibleContext().getAccessibleName();
if (itemName == "Save As..") {
frame.getJMenuBar().getMenu(a).getItem(b).setEnabled(false);
}
}
}
}
}
}
}
In my main class I have actions listed like this:
static Action Close = new AbstractAction("Close") {
public void actionPerformed(ActionEvent e) {
closeCurrentWindow(); // function that will close tab
}
}
The other menu items are Actions as well, and as you can see, what I'm currently doing in the CloseTabButton class is quite frustrating, and most likely the wrong way to code it. Is there a much simpler way to do what I'm doing?
The first thing I might do is provide ActionListener support to the CloseTabButton, for example...
public class CloseTabButton extends JPanel {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
close.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
fireActionPerformed();
}
});
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
protected void fireActionPerformed() {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "You could provide you own action command for each tab here");
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
Basically, this now allows you to register your own ActionListeners to the CloseTabButton
Next, this, fileName == "Untitled", is not how you compare Strings in Java, you should be using something more like "Untitled".equals(fileName)
If you're menus are based on actual Actions, then you can simply disable the Actions themselves. This would require a little bit of work, but a lot less of "guess" work then you're doing now.
Basically, you would monitor the JTabbedPane itself, monitoring for changes to the selected tab and updating the states of the individual Actions themselves
There a number of ways you could do this, like passing a reference of the JTabbedPane to the Actions so they can perform there own monitoring (but I'd use some kind of management interface which could more easily provide information to the Actions and decouple the code and the reliance on JTabbedPane directly, then you could be free to use JInternalFrames instead).
You could have a "menu manager" which did a similar job, monitoring changes to the document container and changing the state of the menu Actions based on the current state, as an example
Updated
If you're making use of the Action API (which I would recommend), then you could simply do something like...
public class CloseTabButton extends JPanel {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, Action action, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(action);
close.setIcon(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
}
Passing in the Action for the close operation, then use the same action for both the JMenuItem and JTabbedPane.
The "core" issue would be how you would identify the "current" tab and document in a uniform manner

How to place tabs over JInternalFrame title bar in Java Swing?

I want to have a JInternalFrame that will be able to handle JTabbedPane much like the Eclipse IDE. I want the tabs to sit on top of the title bar. Each tab should have its own close button. The InternalFrame should also have a close button so that a user can close all the tabs in one go.
This is what I have:
This is what I want to have (screenshot taken from Eclipse IDE):
I don't know how I can achieve this. Can anyone please point me in the right direction?
EDIT:
Based on a comment to look into UI Delegate, I created a UI delegate subclass that is able to remove the menu, but there are some problems with this:
It looks kind of funny in comparison to a normal JInternalFrame, even though I haven't done anything to it but comment out the "createActionMap" and "add(menuBar)" lines.
I can't find anywhere in the library code to indicate how the title bar and contentPane positions are set - obviously I want to move the position of the contentPane to overlap the title bar.
Here are the codes:
public class MyInternalFrameUI extends BasicInternalFrameUI {
public MyInternalFrameUI(JInternalFrame b) {
super(b);
// TODO Auto-generated constructor stub
}
public static ComponentUI createUI(JComponent b) {
return new MyInternalFrameUI((JInternalFrame)b);
}
protected JComponent createNorthPane(JInternalFrame w) {
titlePane = new MyBasicInternalFrameTitlePane(w);
return titlePane;
}
}
public class MyBasicInternalFrameTitlePane extends BasicInternalFrameTitlePane {
public MyBasicInternalFrameTitlePane(JInternalFrame f) {
super(f);
}
protected void installTitlePane() {
installDefaults();
installListeners();
createActions();
enableActions();
//createActionMap(); // This method is package protected and not visible
setLayout(createLayout());
assembleSystemMenu();
createButtons();
addSubComponents();
}
protected void addSubComponents() {
//add(menuBar); // Remove this to disable the menu
add(iconButton);
add(maxButton);
add(closeButton);
}
}
To answer one part with the close button. A solution is to add the close button yourself (there is no option for that built in Swing).
You have to implement the closeTab(…) method or a better solution would be a callback handler
protected class CloseTabButton extends JPanel {
private JLabel titleLabel;
protected CloseTabButton(JTabbedPane aTabbedPane,
final AbstractObservableObjectJPanel<M> aDetailPanel,
String aTitle, Icon anIcon) {
setOpaque(false);
titleLabel = new JLabel(aTitle, anIcon, JLabel.LEFT);
add(titleLabel);
ImageIcon closeImage = new ImageIcon(
CloseTabButton.class.getResource("/images/icon_normal.png"));
Image img = closeImage.getImage();
Image newimg = img.getScaledInstance(16, 16,
java.awt.Image.SCALE_SMOOTH);
ImageIcon closeIcon = new ImageIcon(newimg);
ImageIcon closeImageRollover = new ImageIcon(
CloseTabButton.class.getResource("/images/icon_roll.png"));
Image imgRoll = closeImageRollover.getImage();
Image newimgRoll = imgRoll.getScaledInstance(16, 16,
java.awt.Image.SCALE_SMOOTH);
ImageIcon closeIconRoll = new ImageIcon(newimgRoll);
JButton btClose = new JButton(closeIcon);
btClose.setPreferredSize(new Dimension(15, 15));
add(btClose);
btClose.setOpaque(false);
btClose.setContentAreaFilled(false);
btClose.setBorderPainted(false);
btClose.setRolloverIcon(closeIconRoll);
btClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent aE) {
closeTab(aDetailPanel);
}
});
aTabbedPane.setTabComponentAt(
aTabbedPane.indexOfComponent(aDetailPanel), this);
}
public JLabel getTitleLabel() {
return titleLabel;
}
}
To add keyboard shortcuts you can add them to the input map via
KeyStroke ctrlW = KeyStroke.getKeyStroke(KeyEvent.VK_W,
InputEvent.CTRL_DOWN_MASK);
getRootPane()
.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(ctrlW, disposeAction.getValue(Action.NAME));
DisposeAction is just an Action that also calls closeTab(…)

How do you remove the JComboBox 'click and see dropdown' functionality?

I have a JComboBox which uses GlazedLists to add type-ahead functionality. I want the user to type in a string and see type-ahead (this is working thanks to Glazedlists). However, I don't want users to be able to click the down arrow of the combobox and inspect the dropdown list. I've made the down arrow invisible and made the combobox editable so that it resembles a JTextField. However, you are still able to hover the mouse over the area where the down arrow used to be and click it. This results in the dropdown appearing. What do I change or which methods do I override in order to remove the 'click and get dropdown' functionality.
ComboBox<String> box = new ComboBox<String>();
box.setEditable(true);
box.setUI(new BasicComboBoxUI(){ // make the down arrow invisible
protected JButton createArrowButton() {
return new JButton() {
public int getWidth() {
return 0;
}
};
}
});
SwingUtilities.invokeLater(new Runnable(){
public void run(){
Object[] elements = new Object[] {"java", "perl", "python", "haskell", "erlang", "groovy"};
AutoCompleteSupport.install(box, GlazedLists.eventListOf(elements));
}
});
Override JButton#addMouseListener:
JComboBox<String> box = new JComboBox<>();
box.setEditable(true);
box.setUI(new BasicComboBoxUI() { // make the down arrow invisible
protected JButton createArrowButton() {
return new JButton() {
public int getWidth() {
return 0;
}
#Override
public synchronized void addMouseListener(MouseListener l) {
}
};
}
});

Remove Arrows from Swing Scrollbar in JScrollPane

I would like to remove the scrollbar arrow buttons from a scrollbar in a JScrollPane. How would I do this?
class NoArrowScrollBarUI extends BasicScrollBarUI {
protected JButton createZeroButton() {
JButton button = new JButton("zero button");
Dimension zeroDim = new Dimension(0,0);
button.setPreferredSize(zeroDim);
button.setMinimumSize(zeroDim);
button.setMaximumSize(zeroDim);
return button;
}
#Override
protected JButton createDecreaseButton(int orientation) {
return createZeroButton();
}
#Override
protected JButton createIncreaseButton(int orientation) {
return createZeroButton();
}
#Override
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
//own painting if needed
}
#Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
//own painting if needed
}
}
Removing buttons let space for then. I found make buttons zero as the simplest way.
If you are using the basic version of JScrollBar, then it is probably rendering using the BasicScrollBarUI. I would suggest that you extend BasicScrollBarUI to create a custom UI class (like MyBasicScrollBarUI) . The buttons are protected variables in the superclass. So you need to override the installComponents() methods in the subclass and make sure that you do not add the buttons. See the below code snippet and hide the lines as suggested there.
protected void installComponents(){
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
incrButton = createIncreaseButton(SOUTH);
decrButton = createDecreaseButton(NORTH);
break;
case JScrollBar.HORIZONTAL:
if (scrollbar.getComponentOrientation().isLeftToRight()) {
incrButton = createIncreaseButton(EAST);
decrButton = createDecreaseButton(WEST);
} else {
incrButton = createIncreaseButton(WEST);
decrButton = createDecreaseButton(EAST);
}
break;
}
scrollbar.add(incrButton); // Comment out this line to hide arrow
scrollbar.add(decrButton); // Comment out this line to hide arrow
// Force the children's enabled state to be updated.
scrollbar.setEnabled(scrollbar.isEnabled());
}
Then, in your code after you initialize a JScrollBar, you can call setUI() and pass in an instance of MyBasicScrollBarUI class.
Note: I havent tried this myself, but from the code it looks like it could work.
It is not the most elegant way... but works for me
JScrollBar jsb = getHorizontalScrollBar();
for(Component c : jsb.getComponents()) {
jsb.remove(c);
}
This is the way i went.
Set the scrollbar policy of the scrollbar you want to hide as never
Mimic this behavior with a MouseWheelListener
This method:
Is fast to implement with very few lines of code.
Retains the benefits of the L&F.
Will remove both the buttons and the bar.
Below is a sample code for removing the verticall scroll bar.
JScrollPane myScrollPane = new JScrollPane();
//remove the scroll bar you don't want
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
JTextPane myJTextArea = new JTextPane();
//myScrollPane.setViewportView(myJTextArea);
myScrollPane.addMouseWheelListener(new MouseWheelListener() {
//this will mimick the behavior of scrolling
public void mouseWheelMoved(MouseWheelEvent e) {
JScrollBar scrollBar = myScrollPane.getVerticalScrollBar();
//capturing previous value
int previousValue = scrollBar.getValue();
int addAmount;
//decide where the wheel scrolled
//depending on how fast you want to scroll
//you can chane the addAmount to something greater or lesser
if(e.getWheelRotation()>0) {
addAmount = 2;
}else {
addAmount = -2;
}
//set the new value
scrollBar.setValue(previousValue + addAmount);
}
});

Categories

Resources