Here is a simple version of my code:
JTextArea textareaA = new JTextArea(...);
JTextArea textareaB = new JTextArea(...);
textareaA.addModificationListener(new Modification Listener()
{
public void modified(Modifiable arg0){
if (textareaA.getValue().contains("\t"))
{
textareaA.setValue(textareaA.getValue().trim());
textareaB.getTextComponent().requestFocusInWindow();
}
}
});
The problem is, when I try different ways to change the value of A, B never gets the focus. If I turn off the focusable of A, I can't turn it back on. I need to remove the tab from A, then give focus to B, allowing the user to click back to A if needed, and the tab be gone. The above code causes the focus to stay in A, even though I had B request it. Is this a timing issue maybe?
Thank you!
As far as I understood your question, you want a user to be able to type "Tab" and switch to the next textarea. You also want to trim the last "Tab" entered.
Besides the fact that if you type a "Tab" in the middle of the text, it will not get removed, the next code (based and elaborated from your own) seems to do what you want:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Test {
protected void initUI() {
final JFrame frame = new JFrame();
frame.setTitle("Test dialog synch");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
final JTextArea textareaA = new JTextArea(24, 80);
final JTextArea textareaB = new JTextArea(24, 80);
textareaA.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
textareaB.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
textareaA.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
modified();
}
#Override
public void insertUpdate(DocumentEvent e) {
modified();
}
#Override
public void removeUpdate(DocumentEvent e) {
modified();
}
public void modified() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (textareaA.getText().contains("\t")) {
textareaA.setText(textareaA.getText().trim());
textareaB.requestFocusInWindow();
}
}
});
}
});
panel.add(textareaA, BorderLayout.NORTH);
panel.add(textareaB, BorderLayout.SOUTH);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().initUI();
}
});
}
}
Related
In a JTabbedPane, I associated a custom-made Data object to each added tab. I also have a corresponding Metadata object that shows up in another panel when the tab is selected. The problem I have now is when a tab is closed, the metadata panel shows the metadata of the Data object in the tab that just gets closed. Ideally, I want the panel to show the metadata for the in-focus tab that the user sees. However, the act of closing a tab means the “selected tab” is the tab being closed, so tabpane.getSelectedIndex() would not work. How can I get the tab that is in focus after closing a tab? Thank you in advance!
Devil is in the detail, which you provided none.
I did a quick test and discovered that, ChangeListener is called before ContainerListener, which is a real pain, but, it was always reporting the correct index.
So, what you need to do is marry the two together, so that, both will update the meta data pane when they are called.
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("One", new TabPane(tabbedPane));
tabbedPane.addTab("Two", new TabPane(tabbedPane));
tabbedPane.addTab("Three", new TabPane(tabbedPane));
tabbedPane.addTab("Four", new TabPane(tabbedPane));
tabbedPane.addContainerListener(new ContainerListener() {
#Override
public void componentAdded(ContainerEvent e) {
}
#Override
public void componentRemoved(ContainerEvent e) {
System.out.println("Removed " + e.getChild());
}
});
tabbedPane.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
System.out.println(tabbedPane.getSelectedIndex());
}
});
JFrame frame = new JFrame();
frame.add(tabbedPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TabPane extends JPanel {
private JTabbedPane parent;
public TabPane(JTabbedPane parent) {
this.parent = parent;
setLayout(new GridBagLayout());
JButton btn = new JButton("Close");
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
parent.remove(TabPane.this);
}
});
}
}
}
For some reason my jFrame no longer pops up after I add the menu. Is there something I am missing? I'm trying to make a menu that pops up before the beginning of the game and has buttons "play" as well as a text box that allows the user to input a username.
Any suggestions for how I could fix my code? Thank you!
this is my Menu class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Menu extends JPanel{
private static final long serialVersionUID = 1L;
public Menu() {
JPanel buttonPanel = new JPanel(new GridLayout());
JButton play = new JButton();
JButton help = new JButton();
buttonPanel.add(play);
buttonPanel.add(help);
setFocusable(true);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Game.started = true;
}
});
}
public void paint (Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.fillRect(400, 400, Game.WIDTH, Game.HEIGHT);
}
}
and this is my Main class from which I run my program:
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Main implements Runnable{
public void run() {
final JFrame frame = new JFrame();
frame.setTitle("Flying Square");
frame.setSize(Game.WIDTH, Game.HEIGHT);
//The menu
final Menu menu = new Menu();
final Game game = new Game();
frame.add(menu, BorderLayout.CENTER);
menu.setVisible(true);
try {while (Game.started == false) {
Thread.sleep(10);
}} catch (InterruptedException e){
e.printStackTrace();
}
frame.remove(menu);
//Main playing area
frame.add(game, BorderLayout.CENTER);
game.setVisible(true);
frame.revalidate();
// Put the frame on the screen
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// add listeners
frame.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
flyingObject.jump();
}
});
frame.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE)
{
flyingObject.jump();
}
}
});
// Start game
Game.reset();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Main());
}
}
So, this...
try {while (Game.started == false) {
Thread.sleep(10);
}} catch (InterruptedException e){
e.printStackTrace();
}
Is blocking the Event Dispatching Thread, preventing it from processing any events and basically causing your program to hang.
This is not how you want to process responses from the user. Your Menu should be monitoring for input from the user, probably through one or more ActionListeners, when an action is triggered, it should be notifying some kind of controller, the controller can then make decisions about what it needs to do, like switch the panels for example
You're going to want to break your code down into at least three chunks, the "game" the "menu" and the "controller", this way it will be easier to manage, rather than trying to retrofit the functionality into an existing code
It would recommend having a look at
How to Use CardLayout to help you facilite the switching of the view
How to Use Key Bindings instead of KeyListener
Model-View-Controller
Observer Pattern
So i'm writing a program that saves mouse button (currently just mousePressed, but will add mouseReleased once this will work) status to log file. How do i do that?
Current code:
import static com.sun.java.accessibility.util.AWTEventMonitor.addMouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class mouse {
public static void main(String[] args) throws InterruptedException{
mouse();
}
public static void mouse() throws InterruptedException{
for(int i=0;i<10000;i++){
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
writeToFile(me); //writeToFile saves the me value to txt
}
});
TimeUnit.MILLISECONDS.sleep(1); // time delay, so it saves every 1ms
}
}
public static void writeToFile(MouseEvent me){
try{
String data =" "+me+" ";
File file =new File("log.txt");
//if log.txt doesn't exist, it makes it
if(!file.exists()){
file.createNewFile();
}
//true = write
FileWriter fileWritter = new FileWriter(file.getName(),true);
BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
bufferWritter.write(data);
bufferWritter.close();
}catch(IOException e){
}
}
}
The program compiles and runs, but it doesn't do anything.
I thank you all in advance.
If you're not trying to create a GUI and instead want to log general Mouse position, then adding a MouseListener to your class will do nothing of use. Instead understand that Java is not optimized for this type of program, and you would likely have to use JNA or JNI to trap the OS's mouse handling code. If on the other hand you wish to trap the mouse usage of a Swing GUI, then you first need to create a Swing GUI and then add your MouseListener to it. I'd advise your reading the MouseListener Tutorial for more on this.
Edit
You state:
Ultimately, it will be a part of GUI application, i'm just trying to make a concept of it.
Please understand that a MouseListener will not be functional without adding it to a Component that accepts one, that extends ultimately from the Component type, and that is displayed in a GUI. So in order to test your concept, you will again need to create a Swing GUI and add a MouseListener to one of the visualized components of your GUI. Again, please read the MouseListener tutorials.
About overwriting the file, it doesn't, i took it from my previous program, and it works properly.
Sorry, my bad -- I misread your code.
Edit 2
And as noted in comment, the listener should not have loops, but rather should respond to mouse EVENTS. For example, the following code listens for mouse press, release, and drag and displays the information in a JTextArea. It would be trivial to change this to write to file:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleMouseListenerEg extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private JPanel listenedToPanel = new JPanel();
private JTextArea textArea = new JTextArea(10, 25);
public SimpleMouseListenerEg() {
listenedToPanel.setBorder(BorderFactory.createTitledBorder("Listened To Panel"));
MouseAdapter myMouseAdapter = new MyMouseAdapter();
listenedToPanel.addMouseListener(myMouseAdapter);
listenedToPanel.addMouseMotionListener(myMouseAdapter);
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setLayout(new BorderLayout());
add(listenedToPanel, BorderLayout.CENTER);
add(scrollPane, BorderLayout.EAST);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
// a combination MouseListener and MouseMotionListener
private class MyMouseAdapter extends MouseAdapter {
private String template = "%-10s [%03d, %03d]%n";
#Override
public void mousePressed(MouseEvent mEvt) {
String text = String.format(template, "Pressed", mEvt.getX(), mEvt.getY());
textArea.append(text);
}
#Override
public void mouseReleased(MouseEvent mEvt) {
String text = String.format(template, "Released", mEvt.getX(), mEvt.getY());
textArea.append(text);
}
#Override
public void mouseDragged(MouseEvent mEvt) {
String text = String.format(template, "Dragged", mEvt.getX(), mEvt.getY());
textArea.append(text);
}
}
private static void createAndShowGui() {
SimpleMouseListenerEg mainPanel = new SimpleMouseListenerEg();
JFrame frame = new JFrame("SimpleMouseListenerEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I want to set setDissmissDelay() method multiple times, but I could not set it for a specific value again and again. I also tried to use an infinite loop, and tried to override (ToolTipManager Constructor is on default modifier).
I know for sure the code is working properly as I can see it's printing the e.getsource() in console. I was trying to solve this issue asked by someone (This Question) and while solving that I became stumped at this point. What is the reason behind that? And if I can set the value how can it be? Is there any other way to achieve this?
Here is my code snippet:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class Hello {
static JButton button;
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("Hello World");
button.setToolTipText("Its a tool tip Experiment!");
frame.getContentPane().add(button);
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() == button) {
ActionListener tt = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ToolTipManager.sharedInstance().setDismissDelay(
1000);
System.out.println(e.getSource());
}
};
new Timer(100, tt).start();
}
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Please guide me through this.
Calling setDismissDelay() is a global setting to indicate how long should a Tooltip remain on the display before it is removed. It does not reset the time until when the current tooltip is removed. As suggested in your linked question setting the dismiss delay, once and for all, to Integer.MAX_VALUE should do the trick.
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.