Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need to change the default language into Hebrew in all the text areas in the app. I tried to use Set Local, but it didn't work.
Any idea?
The below code demonstrates the only way I know of to configure a JTextComponent (which JTextArea is a subclass of) so that when it gains input focus it displays Hebrew characters. In other words no need for the user to explicitly change the language after the JTextComponent has gained focus and before the user starts entering text.
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.im.InputContext;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
public class DfltHbrw implements ActionListener, FocusListener, Runnable {
private static final Locale HEBREW = new Locale("iw", "IL");
private static final String EXIT = "\u05E1\u05D2\u05D5\u05E8";
private JFrame frame;
private JTextArea textArea;
#Override // java.awt.event.ActionEvent
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
if (EXIT.equals(actionCommand)) {
System.exit(0);
}
}
#Override // java.awt.event.FocusListener
public void focusGained(FocusEvent event) {
InputContext ic = textArea.getInputContext();
ic.selectInputMethod(HEBREW);
}
#Override // java.awt.event.FocusListener
public void focusLost(FocusEvent event) {
// Do nothing.
}
#Override // java.lang.Runnable
public void run() {
showGui();
}
private JPanel createButtons() {
JPanel buttonsPanel = new JPanel();
JButton button = new JButton(EXIT);
button.addActionListener(this);
buttonsPanel.add(button);
return buttonsPanel;
}
private JScrollPane createTextArea() {
textArea = new JTextArea(20, 60);
textArea.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
textArea.addFocusListener(this);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
return scrollPane;
}
private void showGui() {
frame = new JFrame("Hebrew");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createTextArea(), BorderLayout.CENTER);
frame.add(createButtons(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new DfltHbrw());
}
}
I only added the JButton so that there would be more than one [GUI] component so as to allow transferring focus from one component to another.
The relevant part of the above code is the focusGained() method. I added a focus listener to the JTextArea which calls that method when the JTextArea gains focus. In fact the focusGained() method does the actual work of configuring the JTextArea for displaying Hebrew when the user starts to enter text into it.
Note that the same focusGained() method can be used to configure the JTextArea to display any [supported] language. All you need to change is the Locale argument that is passed to the selectInputMethod() method.
Also note that I only set the ComponentOrientation so that the Hebrew text in the JTextArea would look "natural". It is not required in order to configure the JTextArea for displaying Hebrew.
Related
I have a problem where I have to use two JFrames, so we can forget about good/bad practice.
Now that when we are past this point.
My Two JFrames are
LoginFrame
MainFrame
I want to sign out of MainFrame to LoginFrame and vice versa. In doing so, I want both the frames to open fresh.
Just like how we instantiate them, i.e.
MainFrame.class
//on signout button event
new LoginFrame().setVisible(true);
dispose(); //it will dispose this frame and destroy its UI components and free resources etc etc.
Similarly,
LoginFrame.class
//on signin button event
new MainFrame().setVisible(true);
dispose(); //it will dispose this frame and destroy its UI components and free resources etc etc.
Now, this is working well but the problem is that I have a keyDispatchEvent in MainFrame which is executing a number of times I login after signout (without closing the application).
I believe that even after disposing, the JFrame it isn't actually disposed. So when I type any shortkey, previously disposed frame objects and new object of MainFrame are all dispatching their event. How can I lose ( I mean really dispose) all previous objects so that this event is only fired for current object?
MainFrame.class
final static KeyboardFocusManager keyManager=KeyboardFocusManager.getCurrentKeyboardFocusManager();
keyManager.addKeyEventDispatcher(new KeyEventDispatcher()
{
#Override
public boolean dispatchKeyEvent(KeyEvent e)
{
// if key is alt+r
{
signout(); // getting called repeatedly on single key release
}
}
});
What I don't want is using same objects because they will have previous state/information/changes. Just want to get rid of disposed objects.
Also, I have to work with KeyboardManager to DispatchKeyEvent in this case.
I hope the below code does what you want. Since you didn't post a minimal, reproducible example I can only guess what you want from your [poor] problem description and your insistence on [your] way or the highway.
the problem is that I have a keyDispatchEvent in MainFrame which is executing a number of times I login after signout
My guess is that you keep adding the same KeyEventDispatcher to the KeyboardFocusManager and each one that gets added will execute. So if you add the same KeyEventDispatcher three times, it will execute three times. I assume you only want to add it once and therefore you need to remove it when it is no longer required.
I also assume that when you launch your application, you want the LoginFrame to be displayed first. Hence I added a main method to class LoginFrame, below.
Class LoginFrame
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class LoginFrame extends JFrame implements ActionListener {
public LoginFrame() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(MainFrame.ked);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
JButton signin = new JButton("sign in");
signin.addActionListener(this);
JPanel panel = new JPanel();
panel.add(signin);
add(panel, BorderLayout.PAGE_END);
pack();
setLocationByPlatform(true);
}
#Override
public void actionPerformed(ActionEvent event) {
new MainFrame().setVisible(true);
dispose();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new LoginFrame().setVisible(true));
}
}
Class MainFrame
import java.awt.BorderLayout;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame implements ActionListener {
final static KeyboardFocusManager keyManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
private static boolean done;
static KeyEventDispatcher ked;
public MainFrame() {
keyManager.removeKeyEventDispatcher(ked);
ked = new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent ke) {
int key = ke.getKeyCode();
int modifiers = ke.getModifiersEx();
if (key == KeyEvent.VK_R && (modifiers & KeyEvent.ALT_DOWN_MASK) == KeyEvent.ALT_DOWN_MASK) {
if (done) {
done = false;
}
else {
done = true;
actionPerformed(null);
}
}
return false;
}
};
keyManager.addKeyEventDispatcher(ked);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
JButton signout = new JButton("sign out");
signout.addActionListener(this);
JPanel panel = new JPanel();
panel.add(signout);
add(panel, BorderLayout.PAGE_END);
pack();
setLocationByPlatform(true);
}
#Override
public void actionPerformed(ActionEvent event) {
new LoginFrame().setVisible(true);
dispose();
}
}
NOTES:
I don't know why, but each time I hit Alt+R on the keyboard, the event dispatcher fires twice. Hence the done flag.
In my program a JPanel component which is operated by listener using KeyBindings (changed that from KeyListeners already after reading about issues with focusing) is added to a JFrame. Task of this app is to simply move drawn figure around using arrow keys.
This works perfectly until i add another component before drawing board (JPanel with three buttons).
I tested both Keybindings and KeyListener and both methods have the same issue.
If I add components after drawing board keybindings starts to work again.
Here is my UI class where i add components.
EDIT: removed uncleaned code
I would like to understand Java a bit more so any answer is very appreciated.
Edit: I cleaned my code and created "minimal" example of the problem.
Thank you Andrew for heads up.
Program should print "movingup" in console after pressing arrow up.
The problem occurs here:
container.add(buttons); //after adding this Key Bindings stops working
container.add(board);
And the question is: Why order of adding components makes Key Bindings to stop working? If i add buttons after board Key Binding is working.
Class with the problem (used for creating frame and adding components)
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.WindowConstants;
public class UserInterface implements Runnable {
private static final String MOVE_UP = "moveUP";
private JFrame frame;
public UserInterface() {
}
#Override
public void run() {
frame = new JFrame("Board");
frame.setPreferredSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout());
createComponents(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createComponents(Container container) {
DrawingBoard board = new DrawingBoard();
container.add(new JButton()); //after adding this figure stops moving - arrow keys doesn't work
container.add(board);
MovingUpwards up = new MovingUpwards(board);
board.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
board.getInputMap().put(KeyStroke.getKeyStroke("UP"), MOVE_UP);
board.getActionMap().put(MOVE_UP, up);
}
public JFrame getFrame() {
return frame;
}
}
Rest of the used classes for testing purposes:
import javax.swing.SwingUtilities;
public class Main {
public static void main (String[] args) {
UserInterface ui = new UserInterface();
SwingUtilities.invokeLater(ui);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawingBoard extends JPanel {
public DrawingBoard() {
super.setBackground(Color.WHITE);
}
#Override
protected void paintComponent (Graphics graphics) {
super.paintComponent(graphics);
}
}
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class MovingUpwards extends AbstractAction {
private Component component;
public MovingUpwards(Component component) {
this.component = component;
}
#Override
public void actionPerformed(ActionEvent a) {
System.out.println("movingup");
}
}
The key bindings work fine for me. Check out the Motion Using Key Bindings example found in Motion Using the Keyboard.
I changed the code:
frame.add( content );
frame.add(left, BorderLayout.NORTH);
to:
frame.setLayout(new GridLayout());
frame.add(left);
frame.add( content );
to better simulate your logic.
If you need more help then read Andrew's comment above. Simplify your code to demonstrate the problem so we can "easily" test it by copying and compiling a single source file, the way you can test the code found in the link above.
I am trying to make a game in Java where pressing spacebar moves the box in the window. I am using Key Binding to accomplish this task. The problem is that I can't figure out how to use an ActionListener on the box itself, which is a JLabel. Here is the code below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Game {
private static JFrame frame = new JFrame();
private static JPanel gamePanel = new JPanel();
private static Action playerAction = new PlayerListener();
private static JLabel box = new JLabel();
private static int x = 250;
private static int y = 250;
public static void main(String[] args) {
frame.add(boxPanel());
frame.setTitle("Block Game");
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setFocusable(true);
box.addActionListener(playerAction);
frame.setVisible(true);
}
static JPanel boxPanel() {
ImageIcon boxIcon = new ImageIcon("box.png");
box.setIcon(boxIcon);
box.setSize(30,30);
box.setLocation(x,y);
box.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doPlayerAction");
box.getActionMap().put("doPlayerAction", playerAction);
gamePanel.setLayout(null);
gamePanel.add(box);
frame.add(gamePanel);
return gamePanel;
}
static class PlayerListener extends AbstractAction {
public void actionPerformed(ActionEvent e) {
System.out.println("SPACEBAR");
}
}
}
I tried changing the box to a JButton and working with that instead, but I have found that "SPACEBAR" only prints out when I click on the box itself. Any help is greatly appreciated. Thanks!
Your "core" problem revolves around box.getInputMap(), change it to something more like box.getInputMap(WHEN_IN_FOCUSED_WINDOW) which will mean that the API will respond to key events whenever the window has focus, regardless what other components might have focus.
I'd also suggestsomething more like box.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "doPlayerAction"), as the mechanism which KeyStroke uses to parse String to a KeyStroke is more complicated then it might seem, normally requiring additional information like pressed, released or typed, it's just easier to use the virtual keys
I would also bind the keys to the gamePanel as a general preference, as it should be the container making decisions about what to do, but that's just me.
Have a look at How to Use Key Bindings for more details
I'm currently working on a project that requires the state of a JRadioButton to change when the record being viewed is updated.
We've had a few clients complain to us that when the record changes, if the JRadioButton is off-screen, it won't be updated until the screen is shown. This behavior seems to be a result of using the Windows Look and Feel, as it doesn't seem to happen when it is not set.
The code example below demonstrates this.
The default selected JRadioButton is 'Cat', so by selecting the 'Dog' JButton and then changing tab to 'Question', you can see the JRadioButton transition occur.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* Example of JRadioButton not updating until it's parent panel becomes visible.
*/
public class RadioButtonExample extends JPanel implements ActionListener {
public static final String CAT = "Cat";
public static final String DOG = "Dog";
private final JRadioButton radCat;
private final JRadioButton radDog;
private final ButtonGroup grpAnimal;
public RadioButtonExample() {
super(new BorderLayout());
JLabel lblQuestion = new JLabel("Are you a cat or dog person?");
radCat = new JRadioButton(CAT);
radCat.setActionCommand(CAT);
radCat.setSelected(true);
radDog = new JRadioButton(DOG);
radDog.setActionCommand(DOG);
grpAnimal = new ButtonGroup();
grpAnimal.add(radCat);
grpAnimal.add(radDog);
JPanel pnlQuestion = new JPanel(new GridLayout(0, 1));
pnlQuestion.add(lblQuestion);
pnlQuestion.add(radCat);
pnlQuestion.add(radDog);
JButton btnSetCat = new JButton(CAT);
btnSetCat.setActionCommand(CAT);
btnSetCat.addActionListener(this);
JButton btnSetDog = new JButton(DOG);
btnSetDog.setActionCommand(DOG);
btnSetDog.addActionListener(this);
JPanel pnlButtons = new JPanel(new GridLayout(0, 1));
pnlButtons.add(new JLabel("Update your choice of animal"));
pnlButtons.add(btnSetCat);
pnlButtons.add(btnSetDog);
JTabbedPane tabPane = new JTabbedPane();
tabPane.addTab("Buttons", pnlButtons);
tabPane.addTab("Question", pnlQuestion);
add(tabPane, BorderLayout.LINE_START);
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
public void actionPerformed(ActionEvent evt) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
grpAnimal.clearSelection();
if (CAT.equals(evt.getActionCommand())) {
grpAnimal.setSelected(radCat.getModel(), true);
}
else if (DOG.equals(evt.getActionCommand())) {
grpAnimal.setSelected(radDog.getModel(), true);
}
}
});
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("RadioButtonExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new RadioButtonExample();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Comment out the line below to run using standard L&F
setLookAndFeel();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void setLookAndFeel() {
try {
// Set Windows L&F
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch (Exception e) {
// handle exception
}
}
}
Is there a way to prevent this behavior or even speed it up to make it less noticeable for our users?
You might be able to disable the animation by specifying the swing.disablevistaanimation Java system property:
java -Dswing.disablevistaanimation="true" your-cool-application.jar
In the com.sun.java.swing.plaf.windows.AnimationController class, there is a VISTA_ANIMATION_DISABLED field that is initialized to the swing.disablevistaanimation property. This field determines whether the paintSkin method calls the skin.paintSkinRaw method if animations are disabled or else starts to get into the animations.
It works on my Windows 8.1 laptop with Java 8 (jdk1.8.0_65), so its effect does not seem to be limited to Windows Vista only.
I want to add a mouselistener to mt JFrame frame but when i do frame.addMouseListener(this) i get an error that i cannot use this in a static method
I am making an application that detects a click of the mouse then displays it in int clicks
code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class numberOfClicks implements MouseListener{
static int clicks = 0;
#Override
public void mouseClicked(MouseEvent e) {
clicks++;
}
static JTextField text = new JTextField();
static String string = clicks+" Clicks";
static JFrame frame = new JFrame("Click Counter");
public static void frame(){
Font f = new Font("Engravers MT", Font.BOLD, 23);
text.setEditable(false);
text.setBackground(Color.BLUE);
text.setFont(f);
text.setForeground(Color.GREEN);
text.setBorder(BorderFactory.createLineBorder(Color.BLUE));
text.setText(string);
frame.add(text, BorderLayout.SOUTH);
frame.setResizable(false);
frame.setSize(300, 300);
frame.getContentPane().setBackground(Color.BLUE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.addMouseListener(this);
}
public static void main(String[] args){
frame();
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
}
this doesn't exist in a static method since a static method is a method of the class, not of the object (the owner of this). Solution: get rid of all statics from your code above. None of your fields or methods above should be static other than the main method.
Edit
And as Andrew Thompson correctly states, add the MouseListener to a JPanel that is added to the JFrame's contentPane.
Edit 2
You will want to learn and use Java naming conventions. Class names (i.e., NumberOfClicks) should start with an upper case letter. Method and variable names with a lower-case letter.
You are better off using the mousePressed(...) method rather than the mouseClicked(...) since the former is less persnickety about accepting presses.
You will also want to set your JTextField's text in your mousePressed(...) method since just changing the clicks value isn't enough to change the display.
I try to avoid having my GUI (or "view") classes implement my listeners. I prefer to use anonymous inner classes or stand-alone classes where possible.
e.g.,
JPanel mainPanel = new JPanel();
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
clicks++;
text.setText(clicks + " Clicks");
}
});
// add mainPanel to the JFrame...