When does a Java Swing JScrollBar update its size? - java

I have a JTextArea in a JScrollPane, to which I append messages with display.append(). I am trying to make it scroll automatically by setting the value of the scroll bar to the maximum after appending the text. However, the value of getVerticalScrollBar().getMaximum()doesn't get updated immediately after a line is appended. I have tried to force an update with revalidate(), repaint() and updateUI(), but seem unable to find the right function.
MWE:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class MessageDisplayPane extends JScrollPane {
private static final long serialVersionUID = 2025745714938834689L;
public static final int NUM_LINES = 5;
private JTextArea display;
private JScrollBar vertical = getVerticalScrollBar();
public MessageDisplayPane() {
display = createTextArea();
setViewportView(display);
}
private JTextArea createTextArea() {
JTextArea ta = new JTextArea(NUM_LINES, 0);
ta.setEditable(false);
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setFont(new Font("Arial", Font.PLAIN, 12));
ta.setBorder(BorderFactory.createEtchedBorder());
return ta;
}
class EventListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
new Thread() {
#Override
public void run() {
System.out.println(vertical.getMaximum());
display.append("test\r\n");
revalidate();
repaint();
updateUI();
System.out.println(vertical.getMaximum());
System.out.println();
//vertical.setValue(vertical.getMaximum());
}
}.start();
}
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
MessageDisplayPane messagePane = new MessageDisplayPane();
JButton button = new JButton("Display another line");
frame.setSize(800, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.getContentPane().add(messagePane, BorderLayout.SOUTH);
button.addActionListener(messagePane.new EventListener());
frame.setVisible(true);
}
});
}
}

A possible solution could be to set the caret position to the end (or the beginning) of your text, something like :
textArea.setCaretPosition (textArea.getText ().length ()); // to scroll to the bottom
textArea.setCaretPosition (0); // to scroll to the top
I used a similar instruction to set caret position to 0, and the scrollbar did automatically scroll to the top, so it should work for you.

Related

Java - how to zoom in/zoom out text in JTextArea

I am writing in a notepad. And I want to implement text scaling in my notepad. But I don't know how to do it. I'm trying to find it but everyone is suggesting to change the font size. But I need another solution.
I am create new project and add buttons and JTextArea.
package zoomtest;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JTextArea;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class zoom {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
zoom window = new zoom();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public zoom() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.NORTH);
JButton ZoomIn = new JButton("Zoom in");
ZoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Code here...
}
});
panel.add(ZoomIn);
JButton Zoomout = new JButton("Zoom out");
Zoomout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Code here...
}
});
panel.add(Zoomout);
JTextArea jta = new JTextArea();
frame.getContentPane().add(jta, BorderLayout.CENTER);
}
}
Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Laying Out Components Within a Container section.
I reworked your GUI. Here's how it looks when the application starts. I typed some text so you can see the font change.
Here's how it looks after we zoom out.
Here's how it looks after we zoom in.
Stack Overflow scales the images, so it's not as obvious that the text is zooming.
Explanation
Swing was designed to be used with layout managers. I created two JPanels, one for the JButtons and one for the JTextArea. I put the JTextArea in a JScrollPane so you could type more than 10 lines.
I keep track of the font size in an int field. This is a simple application model. Your Swing application should always have an application model made up of one or more plain Java getter/setter classes.
Code
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ZoomTextExample {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
new ZoomTextExample();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private int pointSize;
private Font textFont;
private JFrame frame;
private JTextArea jta;
private JTextField pointSizeField;
public ZoomTextExample() {
this.pointSize = 16;
this.textFont = new Font(Font.DIALOG, Font.PLAIN, pointSize);
initialize();
}
private void initialize() {
frame = new JFrame("Text Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButtonPanel(), BorderLayout.NORTH);
frame.add(createTextAreaPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JButton zoomIn = new JButton("Zoom in");
zoomIn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
incrementPointSize(+2);
updatePanels();
}
});
panel.add(zoomIn);
panel.add(Box.createHorizontalStrut(20));
JLabel label = new JLabel("Current font size:");
panel.add(label);
pointSizeField = new JTextField(3);
pointSizeField.setEditable(false);
pointSizeField.setText(Integer.toString(pointSize));
panel.add(pointSizeField);
panel.add(Box.createHorizontalStrut(20));
JButton zoomOut = new JButton("Zoom out");
zoomOut.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
incrementPointSize(-2);
updatePanels();
}
});
panel.add(zoomOut);
return panel;
}
private JPanel createTextAreaPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
jta = new JTextArea(10, 40);
jta.setFont(textFont);
JScrollPane scrollPane = new JScrollPane(jta);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private void updatePanels() {
pointSizeField.setText(Integer.toString(pointSize));
textFont = textFont.deriveFont((float) pointSize);
jta.setFont(textFont);
frame.pack();
}
private void incrementPointSize(int increment) {
pointSize += increment;
}
}

Changing JScrollPane height in Swing

I failed to change the height of JPanel or JScrollPane to make more lines to appear, I used GridLayout. It seems that, every component in it should have the same size even when I use setSize(). Should I use another layout?
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Main {
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
private imagePanel image;
JTextField textField = new JTextField(20);
public Main() throws IOException{
prepareGUI();
}
class imagePanel extends JPanel {
private static final long serialVersionUID = 1L;
public void paint(Graphics g) {
try {
BufferedImage image = ImageIO.read(new File("file.jpg"));
g.drawImage(image, 170, 0, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException{
Main swingControlDemo = new Main();
swingControlDemo.showEventDemo();
}
private void prepareGUI(){
mainFrame = new JFrame("Java SWING Examples");
mainFrame.setSize(400,500);
GridLayout gridlayout = new GridLayout(4, 1);
gridlayout.setVgap(1);
mainFrame.setLayout(gridlayout);
headerLabel = new JLabel("",JLabel.CENTER );
statusLabel = new JLabel("",JLabel.CENTER);
JScrollPane scroller = new JScrollPane(statusLabel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
image = new imagePanel();
image.setLayout(new FlowLayout());
// mainFrame.add(headerLabel);
mainFrame.add(image);
mainFrame.add(controlPanel);
mainFrame.add(scroller);
mainFrame.setVisible(true);
}
private void showEventDemo(){
headerLabel.setText("Control in action: Button");
JButton okButton = new JButton("reload");
JButton submitButton = new JButton("Submit");
JButton cancelButton = new JButton("Cancel");
okButton.setActionCommand("reload");
submitButton.setActionCommand("Submit");
cancelButton.setActionCommand("Cancel");
okButton.addActionListener(new ButtonClickListener());
submitButton.addActionListener(new ButtonClickListener());
cancelButton.addActionListener(new ButtonClickListener());
controlPanel.add(okButton);
controlPanel.add(submitButton);
//controlPanel.add(cancelButton);
controlPanel.add(textField);
System.out.println("---------------------");
mainFrame.setVisible(true);
}
private class ButtonClickListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if( command.equals( "reload" )) {
statusLabel.setText(convertToMultiline("Line1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8\nLine9\nLine2\nLine3\nLine\nLine2\nLine3\nLine\nLine2\nLine3\nLine\nLine2\nLine3\nLine\nLine2\nLine3\nLine\nLine2\nLine3\nLine\nLine2\nLine3\nLine"));
}
else {
statusLabel.setText("Submit Button clicked.");
}
}
}
public static String convertToMultiline(String orig)
{
return "<html>" + orig.replaceAll("\n", "<br>");
}
}
The GUI need to look like this
I want to remove the large vertical gaps between the componets, and the jLabel should use that space
Well in your comment you say you want the label to use the space. But in your picture you show the text area with all the space. How can we answer a question when you give us conflicting requirements? Be specific and accurate when describing a problem.
In any case, the default layout of a JFrame is a BorderLayout so you would probably start with that.
Then the component that you want to grow/shrink as the frame is resized should be added to the CENTER of the frame.
Then you create a second panel to contain your other components. This panel would then be added to either the PAGE_START or PAGE_NORTH of the frame depending on your exact requirement.
The layout manager of this panel can then be whatever your want. Maybe a GridLayout, or a GridBagLayout or a vertical BoxLayout.
Read the section from the Swing tutorial on Layout Managers for more information and working examples. The key point is you create nest panels each with a different layout manager to achieve your layout.

How to implement JScrollPane child behavior?

It is said in manual, that if child does not implement Scrollable, then JScrollPane rely on preferredSize properties of it's content.
Apparently this is not true for me. I am increasing preferred height, but JScrollPane does not feel or react on it.
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Try01_JScrollPane extends JFrame {
private static final long serialVersionUID = 4123186105171813186L;
private static final Logger log = LoggerFactory.getLogger(Try01_JScrollPane.class);
JPanel yellowPanel = new JPanel();
{
yellowPanel.setPreferredSize(new Dimension(200,50));
yellowPanel.setSize(new Dimension(200,50));
yellowPanel.setBackground(Color.yellow);
}
JScrollPane scrollPane = new JScrollPane(yellowPanel);
{
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
}
AbstractAction increaseAction = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
yellowPanel.setPreferredSize(new Dimension(yellowPanel.getPreferredSize().width, yellowPanel.getPreferredSize().height+100));
log.debug("preferred height is now {}", yellowPanel.getPreferredSize().height);
}
};
Timer increaseTimer = new Timer(1000, increaseAction);
{
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 400);
setTitle("Try01_JScrollPane");
increaseTimer.start();
setVisible(true);
}
public static void main(String[] args) {
new Try01_JScrollPane();
}
}
JPanel is container and JComponent too, for any changes to JViewport you have to notify the JScrollPane:-)
.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Try01_JScrollPane extends JFrame {
private static final long serialVersionUID = 4123186105171813186L;
private JFrame frame = new JFrame("Try01_JScrollPane");
private JPanel yellowPanel = new JPanel();
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
{
yellowPanel.setBackground(Color.yellow);
}
private JScrollPane scrollPane = new JScrollPane(yellowPanel);
{
scrollPane.setPreferredSize(new Dimension(400, 300));
}
private AbstractAction increaseAction = new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
yellowPanel.setPreferredSize(
new Dimension(yellowPanel.getPreferredSize().width + 100,
yellowPanel.getPreferredSize().height + 100));
yellowPanel.revalidate();
yellowPanel.repaint();
}
};
private Timer increaseTimer = new Timer(1000, increaseAction);
public Try01_JScrollPane() {
frame.add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
increaseTimer.start();
increaseTimer.setRepeats(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Try01_JScrollPane();
}
});
}
}
The JScrollPane cuts a view port out of a backing content have a scroll pane layout. The part on getPreferredSize refers to this layout. It simply says that the JScrollPane / view port rectangle is not influenced by the backing content and vice versa: content is layed out with respect to their preferred size.
So a change of preferred size need a new layouting. More sence would be to:
initialize with a setPreferredSize.
afterwards call setSize to resize.

Scrolling to the top JPanel inside a JScrollPane

I know a lot of people asked this question, but i still can't resolve this problem.
I have a JPanel inside a JScrollPane. JPanel contains six panels that are loaded dynamically.
After the panels are loaded the system makes a vertical autoscroll to the middle of the panel.
I have to avoid this, so I tried with this:
panel.scrollRectToVisible(scrollPane.getBounds());
But it doesn't work.
My scrollPane has been created in this way
JScrollPane scrollPane= new JScrollPane();
scrollPane.setBounds(panel.getBounds());
scrollPane.setViewportView(panel);
Can you help me?
panel.scrollRectToVisible(scrollPane.getBounds()); should be panel.scrollRectToVisible(JPanelAddedOnRuntime.getBounds());
rest of code (posted here) coudn't be works,
for better help sooner post an SSCCE, short, runnable, compilable
EDIT
works, again you would need to re_read my above 3rd. point
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class ScrollTesting {
private JPanel panel = new JPanel();
private JScrollPane scrollPane = new JScrollPane(panel);
private Vector<JTextField> fieldsVector = new Vector<JTextField>();
private Dimension preferredSize = new Dimension(400, 40);
private Font font = new Font("Tahoma", 1, 28);
public ScrollTesting() {
panel.setLayout(new GridLayout(100, 1));
for (int i = 0; i < 100; i++) {
fieldsVector.addElement(new JTextField());
fieldsVector.lastElement().setPreferredSize(preferredSize);
fieldsVector.lastElement().setFont(font);
panel.add(fieldsVector.lastElement());
}
JFrame frame = new JFrame();
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JTextField tf = (JTextField) fieldsVector.lastElement();
panel.scrollRectToVisible(tf.getBounds());
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ScrollTesting scrollTesting = new ScrollTesting();
}
});
}
}

How to configure JComboBox not to select FIRST element when created?

Problem:
Update:
From the Java SE 6 API:
public JComboBox() Creates a JComboBox
with a default data model. The default
data model is an empty list of
objects. Use addItem to add items. By
default the first item in the data
model becomes selected.
So I changed to JComboBox(model) as the API says:
public JComboBox(ComboBoxModel aModel)
Creates a JComboBox that takes its
items from an existing ComboBoxModel.
Since the ComboBoxModel is provided, a
combo box created using this
constructor does not create a default
combo box model and may impact how the
insert, remove and add methods behave.
I tried the following:
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.setSelectedItem(null);
suggestionComboBox = new JComboBox(model);
suggestionComboBox.setModel(model);
But could not get it to work, the first item is still being selected.
Anyone that can come up with a working example would be very much appreciated.
Old part of the post:
I am using JComboBox, and tried using setSelectionIndex(-1) in my code (this code is placed in caretInvoke())
suggestionComboBox.removeAllItems();
for (int i = 0; i < suggestions.length; i++) {
suggestionComboBox.addItem(suggestions[i]);
}
suggestionComboBox.setSelectedIndex(-1);
suggestionComboBox.setEnabled(true);
This is the initial setting when it was added to a pane:
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
suggestionComboBox.addActionListener(new SuggestionComboBoxListener());
When the caretInvoke triggers the ComboBox initialisation, even before the user selects an element, the actionPerformed is already triggered (I tried a JOptionPane here):
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo1.png
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo2.png
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo3.png
The problem is: My program autoinserts the selected text when the user selects an element from the ComboBox. So without the user selecting anything, it is automatically inserted already.
How can I overcome the problem in this situation? Thanks.
Here is my SSCCE: (finally)
package components;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
public class Temp extends JFrame {
JTextPane textPane;
AbstractDocument doc;
JTextArea changeLog;
String newline = "\n";
private JComboBox suggestionComboBox;
private JPanel suggestionPanel;
private JLabel suggestionLabel;
private JButton openButton, saveButton, aboutButton;
public Temp() {
super("Snort Ruleset IDE");
//Create the text pane and configure it.
textPane = new JTextPane();
textPane.setCaretPosition(0);
textPane.setMargin(new Insets(5, 5, 5, 5));
StyledDocument styledDoc = textPane.getStyledDocument();
if (styledDoc instanceof AbstractDocument) {
doc = (AbstractDocument) styledDoc;
//doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));
} else {
System.err.println("Text pane's document isn't an AbstractDocument!");
System.exit(-1);
}
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(700, 350));
//Create the text area for the status log and configure it.
//changeLog = new JTextArea(10, 30);
//changeLog.setEditable(false);
//JScrollPane scrollPaneForLog = new JScrollPane(changeLog);
//Create a JPanel for the suggestion area
suggestionPanel = new JPanel(new BorderLayout());
suggestionPanel.setVisible(true);
suggestionLabel = new JLabel("Suggestion is not active at the moment.");
suggestionLabel.setPreferredSize(new Dimension(100, 50));
suggestionLabel.setMaximumSize(new Dimension(100, 50));
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
//suggestionComboBox.addActionListener(new SuggestionComboBoxListener());
suggestionComboBox.addItemListener(new SuggestionComboBoxListener());
//suggestionComboBox.setSelectedIndex(-1);
//add the suggestionLabel and suggestionComboBox to pane
suggestionPanel.add(suggestionLabel, BorderLayout.CENTER);
suggestionPanel.add(suggestionComboBox, BorderLayout.PAGE_END);
JScrollPane sp = new JScrollPane(suggestionPanel);
JScrollPane scrollPaneForSuggestion = new JScrollPane(suggestionPanel);
//Create a split pane for the change log and the text area.
JSplitPane splitPane = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
scrollPane, scrollPaneForSuggestion);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(1.0);
//Disables the moving of divider
splitPane.setEnabled(false);
//splitPane.setDividerLocation(splitPane.getHeight());
//splitPane.setPreferredSize(new Dimension(640,400));
//Create the status area.
JPanel statusPane = new JPanel(new GridLayout(1, 1));
CaretListenerLabel caretListenerLabel =
new CaretListenerLabel("Status: Ready");
statusPane.add(caretListenerLabel);
//Create the toolbar
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.setRollover(true);
openButton = new JButton("Open Snort Ruleset");
toolBar.add(openButton);
saveButton = new JButton("Save Ruleset");
toolBar.add(saveButton);
toolBar.addSeparator();
aboutButton = new JButton("About");
toolBar.add(aboutButton);
//Add the components.
getContentPane().add(toolBar, BorderLayout.PAGE_START);
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPane, BorderLayout.PAGE_END);
JMenu editMenu = createEditMenu();
JMenu styleMenu = createStyleMenu();
JMenuBar mb = new JMenuBar();
mb.add(editMenu);
mb.add(styleMenu);
setJMenuBar(mb);
//Put the initial text into the text pane.
//initDocument();
textPane.setCaretPosition(0);
//Start watching for undoable edits and caret changes.
textPane.addCaretListener(caretListenerLabel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textPane.requestFocusInWindow();
}
});
}
//This listens for and reports caret movements.
protected class CaretListenerLabel extends JLabel
implements CaretListener {
public CaretListenerLabel(String label) {
super(label);
}
//Might not be invoked from the event dispatch thread.
public void caretUpdate(CaretEvent e) {
caretInvoke(e.getDot(), e.getMark());
}
protected void caretInvoke(final int dot, final int mark) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
Rectangle caretCoords = textPane.modelToView(dot);
//Find suggestion
suggestionComboBox.removeAllItems();
for (int i = 0; i < 5; i++) {
suggestionComboBox.addItem(Integer.toString(i));
}
//suggestionComboBox.setSelectedItem(null);
suggestionComboBox.setEnabled(true);
suggestionLabel.setText("The following keywords are normally used as well. Click to use keyword(s). ");
//changeLog.setText("The following keywords are suggested to be used together: " + str);
} catch (BadLocationException ble) {
setText("caret: text position: " + dot + newline);
System.out.println("Bad Location Exception");
}
}
});
}
}
public class SuggestionComboBoxListener implements ItemListener {
//public void actionPerformed(ActionEvent e) {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
JComboBox cb = (JComboBox)e.getSource();
String selection = (String) cb.getSelectedItem();
JOptionPane.showMessageDialog(null, "Item is selected", "Information", JOptionPane.INFORMATION_MESSAGE);
}
}
}
/*
* Menu Creation
*/
//Create the edit menu.
protected JMenu createEditMenu() {
JMenu menu = new JMenu("Edit");
return menu;
}
protected JMenu createStyleMenu() {
JMenu menu = new JMenu("Style");
return menu;
}
private static void createAndShowGUI() {
//Create and set up the window.
final Temp frame = new Temp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//The standard main method.
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
You need to remove the ItemListener before you make any changes to the combo-box and add it back when you are done.
Something like this:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class Suggestions {
private JFrame frame;
private JTextPane textPane;
private JComboBox suggestionComboBox;
private SuggestionComboBoxListener selectionListener;
public Suggestions() {
frame = new JFrame("Snort Ruleset IDE");
textPane = new JTextPane();
textPane.setCaretPosition(0);
textPane.setMargin(new Insets(5, 5, 5, 5));
textPane.addCaretListener(new SuggestionCaretListener());
JScrollPane textEntryScrollPane = new JScrollPane(textPane);
textEntryScrollPane.setPreferredSize(new Dimension(300, 400));
selectionListener = new SuggestionComboBoxListener(frame);
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
suggestionComboBox.addItemListener(selectionListener);
JPanel suggestionPanel = new JPanel(new BorderLayout());
suggestionPanel.add(suggestionComboBox, BorderLayout.PAGE_END);
frame.getContentPane().add(textEntryScrollPane, BorderLayout.NORTH);
frame.getContentPane().add(suggestionPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private final class SuggestionCaretListener implements CaretListener {
#Override
public void caretUpdate(CaretEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
generateSuggestions();
}
});
}
}
public static final class SuggestionComboBoxListener implements ItemListener {
Component parent;
public SuggestionComboBoxListener(Component parent) {
this.parent = parent;
}
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
JComboBox cb = (JComboBox) e.getSource();
String selection = (String) cb.getSelectedItem();
JOptionPane.showMessageDialog(parent, "The selected item is: " + selection, "Information",
JOptionPane.INFORMATION_MESSAGE);
}
}
}
void generateSuggestions() {
suggestionComboBox.removeItemListener(selectionListener);
suggestionComboBox.removeAllItems();
for (int i = 0; i < 5; i++) {
suggestionComboBox.addItem(Integer.toString(i));
}
suggestionComboBox.setEnabled(true);
suggestionComboBox.addItemListener(selectionListener);
}
public static void main(String[] args) {
new Suggestions();
}
}
BTW, what you posted is not an SSCCE it is a dump of your code. An SSCCE should only have enough code to reproduce the issue you are experiencing.
use
setSelectedItem(null);
Please try with ItemListener instead of ActionListener.
if You want that after 1st entry you made and immediately you combox is empty then just write down the under mentioned code which is:
jComboBox1.setSelectedIndex(0);
and your combox will reset Automatically

Categories

Resources