-1

I have a JCheckBoxMenuItem, I tried to make it so that when you click it, a JScrollPane is removed from a JPanel and then a JTextArea is added with a word-wrap and vice versa, but when I used it, the code didn't work

I'm adding the scrollpane/textArea directly to the JFrame

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Builder extends JFrame implements KeyListener{
    private static final long serialVersionUID = 1156397512984837248L;

    JTextArea ta = new JTextArea(30,50);
    JScrollPane scroll = new JScrollPane(ta);
    boolean s = false;

    public test(){
        setTitle("Builder");
        setSize(600,600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setResizable(false);
        setVisible(true);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_CONTROL){
            if(s == false){
                s = true;
                remove(scroll);
                ta.setLineWrap(true);
                add(ta);
                repaint();
            }else{
                s = false;
                ta.setLineWrap(false);
                remove(ta);
                add(scroll);
                repaint();
            }
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }
}
Sigma 7
  • 27
  • 6
  • 2
    Why don't you use a [`CardLayout`](https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html)? Having 1 panel with your `JScrollPane` and then another with your `JTextArea` and change card when clicked? See [here](http://stackoverflow.com/questions/30078997/how-to-use-cardlayout-with-menu-as-action-listener) and [here](http://www.dreamincode.net/forums/topic/48386-cardlayout-with-jmenu/) for examples – Frakcool Jan 11 '16 at 15:10
  • 1
    Welcome to SO. Please post [mcve] so we can help with this issue – Leet-Falcon Jan 11 '16 at 15:11
  • If you're going to edit the question, make it a useful edit like the MCVE suggested by @Leet-Falcon, as opposed to replacing an illogical `}`. – Andrew Thompson Jan 11 '16 at 15:25
  • I have a lot of code that wouldn't work without other parts, and those parts wouldn't matter to this situation so it's kind of hard to decide what pieces of code are necessary and what aren't. all I know is that i'm using a boolean and a button to decide whether I should add a text field with word-wrap and remove a scroll pane, or to add the scroll pane and remove the text field – Sigma 7 Jan 11 '16 at 15:27
  • 2
    *I have a lot of code that wouldn't work without other parts* try making a new simple project, a Runnable Example (See the link provided by @Leet-Falcon) – Frakcool Jan 11 '16 at 15:33
  • 1
    *"and those parts wouldn't matter to this situation.."* Those are exactly the parts to remove from the MCVE. Note that there is a close reason that boils down to 'lack of MCVE', If you want people to look into the problem more carefully, post an MCVE. But do it soon, only three more votes needed before this is closed, and it's harder to re-open questions then. – Andrew Thompson Jan 11 '16 at 16:10
  • `CardLayout` is the way to go, you might also consider using the key bindings API instead of `KeyListener` which is likely a symptom of the overall problem. See [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) for more details – MadProgrammer Jan 11 '16 at 22:33

1 Answers1

1

I'm not sure I understand the entire problem or what it is you ultimately want to achieve, but, lets have a look at some of the issues you are having to start with...

First, you create a JScrollPane which wraps a JTextArea...

JScrollPane scroll = new JScrollPane(ta);

Okay, this is good.

Next, using a KeyListener (which is never registered in you code snippet), you either add the JScrollPane OR the JTextArea to the screen

if(e.getKeyCode() == KeyEvent.VK_CONTROL){
    if(s == false){
        s = true;
        remove(scroll);
        ta.setLineWrap(true);
        add(ta);
        repaint();
    }else{
        s = false;
        ta.setLineWrap(false);
        remove(ta);
        add(scroll);
        repaint();
    }
}

There are actually three problems with this...

  1. When adding a component to a container, it is first removed from it's previous parent, in this case, when you add your JTextArea to the frame, you remove it from the JScrollPane, but you never reapply it, so your JScrollPane will be empty the next time you add it
  2. When updating a UI dynamically like this, you need to call revalidate followed by repaint to ensure that the layout is update
  3. KeyListener is notorious for not working, this is due to the fact that the component that it is registered to must be focusable AND have focus before it will trigger, a better solution would be to use the Key Bindings API

But how to fix it? Normally, when switching between components/views, I'd recommend a CardLayout, but to be honest, I'm not sure why you want to remove the JScrollPane, so instead, I've just set it up to change the lineWrap state via the Control key instead

Switch

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Switcher {

    public static void main(String[] args) {
        new Switcher();
    }

    public Switcher() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new BorderLayout());
            ta = new JTextArea(10, 20);
            ta.setLineWrap(true);
            add(new JScrollPane(ta));

            try (Reader r = new FileReader(new File("Labyrinth.txt"))) {
                ta.read(r, "Labyrinth");
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK), "pressed.control");
            actionMap.put("pressed.control", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ta.setLineWrap(!ta.getLineWrap());
                }
            });
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366