JTextPane: KeyBindings are not working on StyledEditorKit - java

Please have a look at the following code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.text.*;
public class Form1 extends JFrame
{
private JTextPane textPane;
private JPanel south;
private JScrollPane scroll;
private String content;
public String documentType;
private DefaultStyledDocument document;
int start, end, offset1,length1;
private JButton button;
JFrame frame;
public Form1()
{
//Declaring the instance variables
textPane = new JTextPane();
textPane.setMinimumSize(new Dimension(100,100));
button = new JButton("Bold");
button.addActionListener(new StyledEditorKit.BoldAction());
button.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_B,KeyEvent.CTRL_MASK),"key");
button.getActionMap().put("key", new StyledEditorKit.BoldAction());
document = (DefaultStyledDocument) textPane.getDocument();
//Creating the main window
south = new JPanel();
south.setLayout(new FlowLayout());
south.add(button);
scroll = new JScrollPane(textPane);
getContentPane().add(scroll,"Center");
getContentPane().add(south,"South");
setSize(800,600);
validate();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class Action extends AbstractAction
{
public void actionPerformed(ActionEvent ae)
{
new StyledEditorKit.BoldAction();
}
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run() {
Form1 f = new Form1();
f.setVisible(true);
}
});
}
}
In here, user can enter any text, and when he select a text and click on "Bold" button, the text will be bold. However, I need to do it using CTRL+B also. As you can see, my attempt is not giving any response to that key event. I even tried adding it to a seperate class which extends AbstractAction, but still no good. How can I implement the CTRL+B here? Please help...

When key bindings don't work for me, the first place I look is the InputMap -- am I sure that I'm using the right one? Well, are you sure? The default one uses JComponent.WHEN_FOCUSED and thus only works if your component has the focus.
If you want it to work at other times, say when the bound component is visible and in a focused window but doesn't necessarily have the focus itself, perhaps you should try different condition parameters. Try using JComponent.WHEN_IN_FOCUSED_WINDOW to start with.
i.e.,
InputMap inputMap = myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

Related

How to bind action with any gui interface in java

I am new to java.
Can someone tell me how to add ActionListener with my code?
Do I need to make a different function for it? I want to retrieve value from textfield which is entered by user. I am getting error.
Please explain me the background logic behind when to make function of methods that already exists in java or can we use them directly? My code is:
Also tell me how by pressing ENTER I can get value attached with text field in string?
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.*;
import javax.swing.JList;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Clientgui
{
public static void main(String[] args)
{
JFrame guiFrame=new JFrame();
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("Client GUI");
guiFrame.setSize(30,30);
guiFrame.setLocationRelativeTo(null);
final JPanel comboPanel = new JPanel();
JLabel Msg = new JLabel("Type Message");
JTextField textbox=new JTextField(10);
comboPanel.add(Msg);
comboPanel.add(textbox);
textbox.addActionListener(this);
String text = textbox.getText();
//textArea.append(text + newline);
//textbox.selectAll();
textbox.setText("Enter message here");
//final JPanel comboPanel1 = new JPanel();
//JLabel listLb2 = new JLabel("Connect");
//comboPanel.add(listLb2 );
JButton connect=new JButton("Connect");
guiFrame.add(comboPanel,BorderLayout.NORTH);
guiFrame.add(connect,BorderLayout.SOUTH);
guiFrame.setVisible(true);
}
}
You need an instance of something that implements ActionListener, you are getting a compilation error here -
textbox.addActionListener(this); // <-- no instance "this".
// You may have new Clientgui(), but
// Clientgui does not implement ActionListener.
As mentioned by Elliott Frisch You can add the Action to the instance of something that implements ActionListener which you can achieve in two way
textbox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Write your action here.
}
});
OR
public class Clientgui implements ActionListener{
// content of class goes here
textbox.addActionListener(this);
// content of class goes here
}
In order to bind the enter key with your text box you should implements KeyListener
textbo.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
System.out.println("ENTER key pressed");
}
}
});

java, apple default look and feel: How to set color of a button

i want to know how to set the color of a button (in example, but i will need to set every component color) with the apple look and feel.
I found an answer in stackoverflow that suggest to change to the standard look and feel, that works for me, but i prefer not to change because I like apple's one.
Is there any solution?
I know there is because I saw many apps written in java that have colored buttons and also that use particular styles or images as background.
Can you tell me a solution?
Extend the Jbutton class and in that override the repaint() method and call setBackground(COLOR.ORANGE), to change the button color.
Now use this class to create all your buttons. If you wish to change color of a specific button, call the setBackground(COLOR.ORANGE) method on that specific button. Hope this helps. Have a look at the code below
package solutions;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class VerifierTest extends JFrame {
private static final long serialVersionUID = 1L;
public VerifierTest() {
final JTextField tf = new JTextField("TextField1");
getContentPane().add(tf, BorderLayout.NORTH);
tf.setInputVerifier(new PassVerifier());
final JTextField tf2 = new JTextField("TextField2");
getContentPane().add(tf2, BorderLayout.SOUTH);
tf2.setInputVerifier(new PassVerifier());
final JButton b = new JButton("Button");
b.setBackground(Color.ORANGE);
b.setVerifyInputWhenFocusTarget(true);
getContentPane().add(b, BorderLayout.EAST);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!tf.getInputVerifier().verify(tf)) {
JOptionPane.showMessageDialog(tf.getParent(), "illegal value: " + tf.getText(), "Illegal Value",
JOptionPane.ERROR_MESSAGE);
}
if (b.isFocusOwner()) {
System.out.println("Button clicked");
}
}
});
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Frame frame = new VerifierTest();
frame.setSize(400, 200);
frame.setVisible(true);
}
class PassVerifier extends InputVerifier {
#Override
public boolean verify(JComponent input) {
final JTextField tf = (JTextField) input;
String pass = tf.getText();
if (pass.equals("Manish")) {
return true;
} else {
return false;
}
}
}
}
Comment the line "b.setBackground(Color.ORANGE);" and see the difference.

How to display different components in a JFrame?

I am very new to Java AWT. My question header must seem ridiculous to you, sorry about that. In my application I have three buttons which display different threads when clicked on. Now I want to add maybe a button or checkboxes or choicelist, etc when clicked on a particular button. For eg, if I click on yes button, it should display a choice list, something like that. How do I achieve something like that? Here is my code so far:
import java.awt.Button;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class AppWindow extends Frame implements ActionListener{
String keymsg = "Test message";
String mousemsg = "Nothing";
int mouseX=30, mouseY=30;
String msg;
public AppWindow(){
//addKeyListener(new MyKeyAdapter(this));
//addMouseListener(new MyMouseAdapter(this));
addWindowListener(new MyWindowAdapter());
}
public void paint(Graphics g){
g.drawString(msg, 150, 100);
}
//Here the window is created:
public static void main(String args[]){
AppWindow appwin = new AppWindow();
appwin.setSize(new Dimension(300,200));
appwin.setTitle("My first AWT Application");
appwin.setLayout(new FlowLayout(FlowLayout.LEFT));
appwin.setVisible(true);
Button yes,no,maybe;
yes = new Button("yes");
no = new Button("no");
maybe = new Button("maybe");
appwin.add(yes);
appwin.add(no);
appwin.add(maybe);
yes.addActionListener(appwin);
no.addActionListener(appwin);
maybe.addActionListener(appwin);
}
#Override
public void actionPerformed(ActionEvent ae) {
// TODO Auto-generated method stub
String str = ae.getActionCommand();
if(str.equals("yes")){
msg = "You pressed Yes";
}
if(str.equals("no")){
msg = "You pressed No";
}
if(str.equals("maybe")){
msg = "You pressed Maybe";
}
repaint();
}
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent we){
System.exit(0);
}
}
Points describing what you should be doing :
As already mentioned by others, better to use Swing over AWT, since Swing is more advanced.
As much as possible, always try to Paint on top of a JPanel or a
JComponent, instead of Painting right on top of your JFrame, by
overriding the paintComponent(Graphics g) method of the said
JComponent/JPanel
Never call setVisible(true) on the JFrame until and unless it's
size has been established. So in general terms, this has to be the
last call, once you are done adding components to the JFrame and
the size of the JFrame has been realized by the LayoutManager.
Inside your actionPerformed(...), instead of writing all if
statement blocks, you should adhere to the if-else if statement
blocks. The benefit of this, over the former is that, at any given
time, only one event will be fired, hence once the said condition is
satisfied, you don't want your code to keep checking other
conditions, which in general is really not a good programming
practice, IMHO.
MOST IMPORTANT THING : Never make calls like pack()/setVisible(...) from within the main method, such calls belong
to the Event Dispatch Thread, and must be done on the same. Please
read Concurrency in Swing for more detail.
Have a look at the example program, for better understanding.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ComponentExample
{
private CustomPanel drawingBoard;
private JPanel contentPane;
private JButton yesButton;
private JButton noButton;
private JButton maybeButton;
private JComboBox cbox;
private ActionListener buttonAction = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (cbox.isShowing())
contentPane.remove(cbox);
if (button == yesButton)
{
drawingBoard.setText("You Pressed YES.");
contentPane.add(cbox, BorderLayout.PAGE_END);
}
else if (button == noButton)
drawingBoard.setText("You Pressed NO.");
else if (button == maybeButton)
drawingBoard.setText("You Pressed MAYBE.");
/*
* revalidate()/repaint() is needed
* when the JComponent is added or
* removed from the already
* visible Container.
*/
contentPane.revalidate();
contentPane.repaint();
}
};
public ComponentExample()
{
cbox = new JComboBox(
new String[]{"I GOT IT"
, "I STILL HAD DOUBT"});
}
private void displayGUI()
{
JFrame frame = new JFrame("Component Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBackground(Color.DARK_GRAY);
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(5, 5));
JPanel buttonPanel = new JPanel();
buttonPanel.setOpaque(true);
buttonPanel.setBackground(Color.WHITE);
yesButton = new JButton("YES");
yesButton.addActionListener(buttonAction);
noButton = new JButton("NO");
noButton.addActionListener(buttonAction);
maybeButton = new JButton("MAY BE");
maybeButton.addActionListener(buttonAction);
buttonPanel.add(yesButton);
buttonPanel.add(noButton);
buttonPanel.add(maybeButton);
contentPane.add(buttonPanel, BorderLayout.PAGE_START);
drawingBoard = new CustomPanel();
contentPane.add(drawingBoard, BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ComponentExample().displayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
private String msg;
public CustomPanel()
{
msg = "";
setOpaque(true);
setBackground(Color.WHITE);
}
public void setText(String msg)
{
this.msg = msg;
repaint();
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString(msg, getWidth() / 3, getHeight() / 3);
}
}
I don't know if I have understood the question well but... couldn't you create those elements and call their setVisible(boolean) methods to make them not visible at first, and them make them visible when user pushes buttons?

processing text in jTextArea

I am trying to implement a Document Listener in my program. So far every time the user types in a new word, I am getting the whole text and saving it. What I want to do is to get only the new word/words typed in and process them. Can you give me suggestions how I can do that?
How about document at http://docs.oracle.com/javase/tutorial/uiswing/events/documentlistener.html ?
Basically, the parameter DocumentEvent from insertUpdate event contains the text. You will have to retrieve the texts from the object e.
My suggestion is to try out some code and we'll see how much you know about DocumentListener, ok?
Below is proposed code similar to yours above:
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
//public class DocumentListener { // Fix: not a good name for the class since it is part of JVM
public class DocumentEventDemo extends JFrame { // easier than extends JPanel
JPanel txtPanel, centerPanel;
GridLayout grid;
JTextField txtField;
JTextArea txtArea;
JFrame frame;
JComponent newContentPane;
FlowLayout flow;
public DocumentEventDemo() {
txtArea = new JTextArea();
txtArea.getDocument().addDocumentListener(new MyDocumentListener());
txtArea.getDocument().putProperty("txtArea", "MyDocumentListener");
// txtField = new JTextField(10); // 10 chars max
// txtField.setText("12345");
centerPanel = new JPanel();
grid = new GridLayout(2,1,1,1);
txtPanel = new JPanel();
flow = new FlowLayout(FlowLayout.CENTER);
txtPanel.setLayout(flow);
//Adding control GUI fields to the only panel
// txtPanel.add(txtArea);
// txtPanel.add(txtField);
// Forming the center view with GUI controls
centerPanel.setLayout(grid);
// centerPanel.add(txtPanel);
centerPanel.add(txtArea);
// Add Panels to the Frame
getContentPane().add(centerPanel,"Center");
this.setSize(500,200);
this.validate();
this.setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// newContentPane = getRootPane();
// newContentPane.setOpaque(true);
// frame.setContentPane(newContentPane);
}
//MyEditor editor = new MyEditor(); // what is MyEditor?
//javax.swing.event.DocumentListener mydocumentListener = new javax.swing.event.DocumentListener()
// Make a class to define the inherited abstract methods, which are also events.
class MyDocumentListener implements DocumentListener {
String[] word=new String[50];
String text;
int i=0;
int y;
int l;
int len;
public void changedUpdate(DocumentEvent documentEvent) {
System.out.println("The text has been changed.");
}
public void insertUpdate(DocumentEvent documentEvent) {
try {
GetWord(documentEvent);
} catch (BadLocationException ex) {
Logger.getLogger(DocumentListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void removeUpdate(DocumentEvent documentEvent) {
System.out.println("A character has been removed!");
}
private void GetWord(DocumentEvent documentEvent) throws BadLocationException {
//get the type of event
DocumentEvent.EventType type = documentEvent.getType();
//check what is the event, hence what is the user doing
if (type.equals(DocumentEvent.EventType.INSERT)) {
Document source = documentEvent.getDocument();
y=documentEvent.getOffset();
l=documentEvent.getLength();
len=source.getLength();
text = source.getText(y,l);
if(text.equals(" "))
{
for (int z=0;z<len;z++)
{
System.out.print(word[z]);
}
System.out.println("\n");
Arrays.fill(word,null);
i=0;
}
word[i]=text;
i++;
} else {
System.out.println("A character has been removed!");
}
}
}; // DocumentListener class instantiation
// editor. editArea.getDocument().addDocumentListener(mydocumentListener);
public static void main(String args[]){
new DocumentEventDemo();
}
} // TOP class
Notes:
My most outer class extends JFrame, which creates the window & listeners the easy way, I think.
DocumentEventDemo is a constructor that creates the UI controls and looks.
I created a class that implements DocumentListener. This way I can override the abstract events.
My main function is on the bottom inside the class DocumentEventDemo, like yours actually.
I do not see the code for class MyEditor. Therefore I replaced that with JTextArea, behaves like an editor.
Your code GetWord seems to be working well. Congratulations!
Your technique of using System.out.println is not working since the app is windows GUI application instead of console, which works well with System.out.
Obviously, you still have work to do with the Listener functions for changed and remove.
Have fun!
Tommy Kwee

How to set the orientation of JTextArea from right to left (inside JOptionPane)

I have JScrollPane with JTextArea inside it and I am trying to set the JTextArea's orientation from right to left so the text inside it will start from the right and the scrollbar will be on the left
I've tried the following but they didn't affect the direction of the orientation:
txt.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
txt.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
txt.setAlignmentX(JTextArea.RIGHT_ALIGNMENT);
EDIT:
the two answers camickr & trashgod provided work fine but not in my program where I use my JTextArea as an object Message and pass it to OptionPane.
EDIT2:
I figured out that setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); doesn't work if I apply it on the JOptionPane contents .. is there an alternative solution to this issue?
Similar to my code:
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class TextArea extends JPanel
{
private JTextArea txt = new JTextArea();
public TextArea()
{
setLayout(new GridLayout());
txt.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
JScrollPane scroll = new JScrollPane(txt);
scroll.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
setPreferredSize(new Dimension(200,200));
this.add(scroll);
}
private void display()
{
Object[] options = {this};
JOptionPane pane = new JOptionPane();
int option = pane.showOptionDialog(null, null, "Title", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
}
public static void main(String[] args)
{
new TextArea().display();
}
}
and the scrollbar will be on the left
scrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
so the text inside it will start from the right
textArea.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
The text starts on the right side, but still gets append to the end as you type instead of being inserted at the beginning of the line.
Update:
I don't know why it doesn't work in an option pane. Here is a simple solution:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test
{
public static void main(String args[]) throws Exception
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JTextArea textArea = new JTextArea(4, 20);
JScrollPane scrollPane = new JScrollPane( textArea );
JPanel panel = new JPanel();
panel.add( scrollPane );
scrollPane.addAncestorListener( new AncestorListener()
{
public void ancestorAdded(AncestorEvent e)
{
JScrollPane scrollPane = (JScrollPane)e.getComponent();
scrollPane.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}
public void ancestorMoved(AncestorEvent e) {}
public void ancestorRemoved(AncestorEvent e) {}
});
JOptionPane.showMessageDialog(null, panel);
}
});
}
}
This seems to work.
import java.awt.ComponentOrientation;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/** #see http://stackoverflow.com/questions/6475320 */
public class RTLTextArea extends JPanel {
private static final String s = "مرحبا العالم";
private JTextArea jta = new JTextArea(7, 5);
private Locale arabic = new Locale("ar", "KW");
private ComponentOrientation arabicOrientation =
ComponentOrientation.getOrientation(arabic);
public RTLTextArea() {
this.setLayout(new GridLayout());
this.add(new JScrollPane(jta));
this.applyComponentOrientation(arabicOrientation);
for (int i = 0; i < 8; i++) {
jta.append(s + "\n");
}
}
private void display() {
JFrame f = new JFrame("RTLTextAre");
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 RTLTextArea().display();
}
});
}
}
this line
setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT)
change the correct order of the words.
i have this result
KBytes 80.78
The following lines solved my problem:
jTextArea1.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
jTextArea1.setText(<text>);
They serve to:
setComponentOrientation() changes the orientation of the TextArea; and,
setText() refreshes TextArea immediately so it displays properly
Simply setting ComponentOrientation to RIGHT_TO_LEFT is not sufficient by itself. repaint() doesn't force the text to realign itself. A quick solution for me was to update the contents of the TextArea. That forced the text to realign itself.

Categories