How can I get access to the JTextPane content from a JMenuItem? - java

I'm working on a text editor using Java (Swing). So far I have made the body. I'm having problem with this feature:
New (JMenuItem) (empties the content of the JTextArea).
When the user clicks on the button, the JTextArea content should be replaced with an empty string.
This is my code (I'm ommiting code that's not relevant to the problem, such as menu creation, menu items addition, only adding the classes.)
This is the TextArea class:
class MyTextArea extends JTextArea implements ActionListener {
JTextArea myTextArea;
public MyTextArea() {
init();
}
public void init(){
setLineWrap(true);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
(Empty, as you can see.)
This is the MenuBar class:
class MyMenuBar extends JMenuBar implements ActionListener {
private JMenu mArchivo;
private JMenuItem mNuevo;
public MyMenuBar(){
init();
add(mArchivo);
}
private void init() {
mArchivo = settingUpMenus("Archivo", "Archivo", 'A');
mNuevo = settingUpMenuItems("Nuevo", "Nuevo", 'N');
mArchivo.add(mNuevo);
}
private JMenu settingUpMenus(String mTitle, String mDescription,
char mMnemonic) {
JMenu mMenu;
mMenu = new JMenu(mTitle);
mMenu.setMnemonic(mMnemonic);
mMenu.getAccessibleContext().setAccessibleDescription(mDescription);
mMenu.setActionCommand(mTitle);
mMenu.addActionListener(this::actionPerformed);
return mMenu;
}
private JMenuItem settingUpMenuItems(String mTitle, String
mDescription, char mMnemonic) {
JMenuItem mMenuItem;
mMenuItem = new JMenuItem(mTitle);
mMenuItem.setMnemonic(mMnemonic);
mMenuItem.getAccessibleContext().
setAccessibleDescription(mDescription);
mMenuItem.setActionCommand(mTitle);
mMenuItem.addActionListener(this::actionPerformed);
return mMenuItem;
}
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case "Nuevo":
onNew();
break;
}
}
private void onNew() {
}
}
And this is the class constructor where I add the JTextArea and the JMenu with it's items and all.
public Editor() {
JScrollPane myScrollPane = new JScrollPane(new MyTextArea(),
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
systemLook();
setTitle("Text editor");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(new Dimension(800, 700));
setVisible(true);
setJMenuBar(new MyMenuBar());
add(myScrollPane);
}
However, I have tried many ways for my new button to get access to the current instance of JTextArea and to modify it, such as getting the parent classes with the ActionEvent object in the actionPerformed method inside the JMenu class. But none of the intents I have done can access to the JTextArea. Any ideas? Should I implement it another way?

Just pass it as a parameter in the constructor of the menu bar like
...
private JTextArea myTextArea;
public MyMenuBar(MyTextArea myTextArea){
init();
add(mArchivo);
this.myTextArea = myTextArea;
}
...
and in the main would look like
MyTextArea myTextArea = new MyTextArea();
JScrollPane myScrollPane = new JScrollPane(myTextArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
systemLook();
setTitle("Text editor");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(new Dimension(800, 700));
setVisible(true);
setJMenuBar(new MyMenuBar(myTextArea));

Related

How to make button in one class affect text area in another?

Please help me to understand how this works. I'm having difficulties to understand how, for example, JButton in one class can alter text in JTextArea that is in another class of a same package. I've made a simple app just to ask a question here, I need this for a bigger school project where I need to implement this to work with multiple classes.
When I put everything in the same class it works but I need it in separate classes.
Here is the simple code.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Button extends JPanel {
private JButton button;
private Panel panel;
public Button() {
button = new JButton("BUTTON");
panel = new Panel();
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
String input = clicked.getText();
panel.setTextArea(input);
//System.out.println(input);
}
});
}
}
class Panel extends JPanel {
private JTextArea textArea;
public Panel() {
setLayout(new BorderLayout());
textArea = new JTextArea();
add(textArea, BorderLayout.CENTER);
}
public JTextArea getTextArea() {
return textArea;
}
void setTextArea(String text) {
this.textArea.setText(text);
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java() {
frame = new JFrame();
dugme = new Button();
panel = new Panel();
//super("test");
frame.setLayout(new BorderLayout());
frame.setTitle("test");
frame.setSize(300, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(dugme, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
Java app = new Java();
}
}
I want action listener to alter the text in the panel, sys-out works so the listener listens the button but I can't make it to alter the text in text area.
As already mentioned by #XtremeBaumer you have two different instances of Panel class. You need to remove the secode one.
public class Button extends JPanel {
private JButton button;
private Panel panel;
public Button(Panel panel) { // we need already created instance of panel here.
this.panel = panel;
button = new JButton("BUTTON");
// panel = new Panel(); <-- this line must be deleted.
// ...
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java(){
frame = new JFrame();
panel = new Panel();
dugme = new Button(panel);
// ...
}
}
Please also replace the line
add(textArea, BorderLayout.CENTER);
by
add(new JScrollPane(textArea), BorderLayout.CENTER);
This allows you to get the scrool bars when text goes larger than the text ara size.
Here is your reworked example
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Button extends JPanel {
private JButton button;
private Panel panel;
public Button(Panel panel) {
this.panel = panel;
button = new JButton("BUTTON");
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
String input = clicked.getText();
panel.setTextArea(input);
//System.out.println(input);
}
});
}
}
class Panel extends JPanel {
private JTextArea textArea;
public Panel() {
setLayout(new BorderLayout());
textArea = new JTextArea();
add(new JScrollPane(textArea), BorderLayout.CENTER);
}
public JTextArea getTextArea() {
return textArea;
}
void setTextArea(String text) {
this.textArea.setText(text);
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java() {
frame = new JFrame();
panel = new Panel();
dugme = new Button(panel);
//super("test");
frame.setLayout(new BorderLayout());
frame.setTitle("test");
frame.setSize(300, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(dugme, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
Java app = new Java();
}
}

How can I display multiple JPanel's from different classes onto my JFrame?

I will have a menu bar in which I can select multiple choices, in which will display a different JPanel for me onto my JFrame. Whenever I choose another option from my menu bar, a different JPanel will occupy the JFrame's space.
However, with this code, every time I issue the following code frame.getJPanelOne();, it creates a new JFrame, which I don't want. I only want the panel to be displayed on my existing JFrame.
Keep in mind, when my program starts, a JFrame is created from the JFrameTest class and also displays my menu bar at the top so I can select between Panel one and Panel two.
How can I successfully do this with the following code?
public class MenuActionListener implements ActionListener {
private MyFrame frame;
public MenuActionListener (MyFrame frame) {
this.frame = frame;
}
public void displayPanelOne() {
JFrameTest frame = new JFrameTest();
frame.getJPanelOne();
}
public void displayPanelTwo() {
JFrameTest frame = new JFrameTest();
frame.getJPanelTwo();
}
#Override
public void actionPerformed(final ActionEvent e) {
String command = e.getActionCommand();
switch (command) {
//Display panel one when I select the option on the menu bar
case "Panel One":
displayPanelOne();
break;
//Display panel two when I select the option on the menu bar
case "Panel Two":
displayPanelTwo();
break;
default:
}
}
}
Here is my JFrameTest class:
public class JFrameTest extends JFrame {
private JPanel panelMain;
private JPanelOne panel1;
private JPanelTwo panel2;
private JMenuBar menuBar;
public JFrameTest() {
MenuBar menuBarInstance = new MenuBar();
frame = new JFrame();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setPreferredSize(new Dimension(720, 480));
setJMenuBar(menuBarInstance.getMenuBar());
menuBar.getMenu(0).getItem(0).addActionListener(new MenuActionListener(this));
menuBar.getMenu(0).getItem(1).addActionListener(new MenuActionListener(this));
pack();
setLocationRelativeTo(null);
setVisible(true);
panelMain = new JPanel();
panelMain.setBounds(0, 0, 420, 90);
panelMain.setPreferredSize(new Dimension(200, 40));
add(panelMain);
}
public JPanel getJPanelOne() {
panel1 = new JPanelOne();
panelMain.add(panel1);
return panelMain;
}
public JPanel getJPanelTwo() {
panel2 = new JPanelTwo();
panelMain.add(panel2);
return panelMain;
}
}
Here is both my JPanel classes in which will be added whenever I select the appropriate item from the menu bar:
public class JPanelOne extends JPanel
{
public JPanelOne()
{
// setting up black JPanel
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(220, 40));
panel.setBackground(Color.BLACK);
JLabel label = new JLabel("Panel One");
// adding button to the black JPanel
panel.add(label);
// adding blackJPanel
add(panel);
}
}
And a separate class for my other panel.
public class JPanelTwo extends JPanel
{
public JPanelTwo()
{
// setting up black JPanel
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(220, 40));
panel.setBackground(Color.RED);
JLabel label = new JLabel("Panel One");
// adding button to the black JPanel
panel.add(label);
// adding blackJPanel
add(panel);
}
}
Create menu action listener and add it to my GUI:
public class MenuBar {
private JMenuBar menuBar;
private MyFrame frame;
public MenuBar() {
System.out.println("menuBar");
//Creates a menubar for a JFrame
menuBar = new JMenuBar();
//Define addMenu items
JMenuItem addPanelOneItem = new JMenuItem("Panel One");
addPanelOneItem.setActionCommand("Panel One");
//Define addMenu items
JMenuItem addPanelTwoItem = new JMenuItem("Panel Two");
addPanelTwoItem.setActionCommand("Panel Two");
JMenu menu = new JMenu("Test");
menuBar.add(menu);
menu.add(addPanelOneItem);
menu.add(addPanelOneItem);
public JMenuBar getMenuBar()
{
return menuBar;
}
}
My question is, how can I successfully display multiple JPanel's from different classes onto my main JFrame without creating new instances of said JFrame?
Thank you in advance.
Your use case, seems perfect for CardLayout.
In card layout you can add multiple panels in the same place, but then show or hide, one panel at a time.
It's creating a new JFrame each time because you are telling it to (new JFrameTest();). Instead, do something like:-
JFrameTest frame = new JFrameTest();
public void displayPanelOne() {
// todo - remove existing panel if required?
frame.getJPanelOne();
}
your MenuActionListener class should look like this:
public class MenuActionListener implements ActionListener {
private JFrameTest frame;
public MenuActionListener(JFrameTest frame){
this.frame=frame;
}
public void displayPanelOne() {
frame.getJPanelOne();
}
public void displayPanelTwo() {
frame.getJPanelTwo();
}
#Override
public void actionPerformed(final ActionEvent e) {
String command = e.getActionCommand();
switch (command) {
//Display panel one when I select the option on the menu bar
case "Panel One":
displayPanelOne();
break;
//Display panel two when I select the option on the menu bar
case "Panel Two":
displayPanelTwo();
break;
default:
}
}
}
and again we are missing the crucial part of the code, on which you create the MenuActionListener and add it to your GUI. if you post that code, we can solve your question. And also don't make a new question to the exact same problem as before
Copy the following code of your MenuBar
public class MenuBar {
private JMenuBar menuBar;
private MyFrame frame;
public MenuBar() {
System.out.println("menuBar");
//Creates a menubar for a JFrame
menuBar = new JMenuBar();
//Define addMenu items
JMenuItem addPanelOneItem = new JMenuItem("Panel One");
addPanelOneItem.setActionCommand("Panel One");
//Define addMenu items
JMenuItem addPanelTwoItem = new JMenuItem("Panel Two");
addPanelTwoItem.setActionCommand("Panel Two");
JMenu menu = new JMenu("Test");
menuBar.add(menu);
menu.add(addPanelOneItem);
menu.add(addPanelOneItem);
}
public JMenuBar getMenuBar()
{
return menuBar;
}
}
and in your JFrameTest class you then after
setJMenuBar(menuBarInstance.getMenuBar());
add these lines of code:
menuBar.getMenu(0).getItem(0).addActionListener(new MenuActionListener(this));
menuBar.getMenu(0).getItem(1).addActionListener(new MenuActionListener(this));
public JFrameTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setPreferredSize(new Dimension(720, 480));
menuBar=new MenuBar().getMenuBar();
menuBar.getMenu(0).getItem(0).addActionListener(new MenuActionListener(this));
menuBar.getMenu(0).getItem(1).addActionListener(new MenuActionListener(this));
pack();
setLocationRelativeTo(null);
setVisible(true);
panelMain = new JPanel();
panelMain.setBounds(0, 0, 420, 90);
panelMain.setPreferredSize(new Dimension(200, 40));
add(panelMain);
setJMenuBar(menuBar);
}

JTextField and button is not updated while switching between panel using cardlayout

I have been struggling with updating Jtextfield and Jbutton data in cardlayout from couple of days. I have created small demo to explain my problem.. When I click on "start" button it should show another panel and thats is working but when I return back to main page I want my Jtextfield and jbutton to be updated from "world" to "hello" but that is not working. Any help and suggestions would be appreciated.(Sorry about the indentation of code, I do not know why copy-paste did not work properly).
public class CardlayoutDemo {
public static String data = "world";
private static final String INTRO = "intro";
private static final String GAME = "game";
private CardLayout cardlayout = new CardLayout();
private JPanel mainPanel = new JPanel(cardlayout);
private IntroPanel introPanel = new IntroPanel();
private GamePanel gamePanel = new GamePanel();
public CardlayoutDemo() {
mainPanel.add(introPanel.getMainComponent(), INTRO);
mainPanel.add(gamePanel.getMainComponent(), GAME);
introPanel.addBazBtnActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardlayoutDemo.data = "hello";
mainPanel.repaint();
mainPanel.revalidate();
CardLayout cl = (CardLayout)mainPanel.getLayout();
cl.show(mainPanel, GAME);
}
});
gamePanel.addBackBtnActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout)mainPanel.getLayout();
cl.show(mainPanel, INTRO);
}
});
}
private JComponent getMainComponent() {
return mainPanel;
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CardlayoutDemo().getMainComponent());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class IntroPanel {
private JPanel mainPanel = new JPanel();
public JButton start;
private JButton exit;
private JTextField lblData;
public IntroPanel() {
mainPanel.setLayout(new BorderLayout());
JPanel content = new JPanel();
start = new JButton("Start");
exit = new JButton(CardlayoutDemo.data);
lblData = new JTextField(CardlayoutDemo.data);
content.add(lblData);
content.add(start);
content.add(exit);
mainPanel.add(content, BorderLayout.CENTER);
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window win = SwingUtilities.getWindowAncestor(mainPanel);
win.dispose();
}
});
}
public void addBazBtnActionListener(ActionListener listener) {
start.addActionListener(listener);
}
public JComponent getMainComponent() {
return mainPanel;
}
}
class GamePanel {
private static final Dimension MAIN_SIZE = new Dimension(400, 200);
private JPanel mainPanel = new JPanel();
private JButton back;
public GamePanel() {
back = new JButton("return to main menu");
mainPanel.add(back);
mainPanel.setPreferredSize(MAIN_SIZE);
}
public JComponent getMainComponent() {
return mainPanel;
}
public void addBackBtnActionListener(ActionListener listener) {
back.addActionListener(listener);
}
}
when this line gets executed inside your listener:
CardlayoutDemo.data = "hello";
You´re creating a new java.lang.String object and setting the field data to reference the new String you have just created. This has no effect over the internal state of the JTextField or the String object which was previously referenced by the variable.
To change the text of the JTextField you should call the setText(String) method of JTextField .
No, don't override the show method. Instead give your classes methods that allow other classes the ability to change their state. For instance, you could add this method to the IntroPanel class:
class IntroPanel {
// .....
// !! added!
public void lblDataSetText(String text) {
lblData.setText(text);
}
}
and then call it when you want to change the state of its lblData field:
introPanel.addBazBtnActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// !! CardlayoutDemo.data = "hello";
mainPanel.repaint();
mainPanel.revalidate();
CardLayout cl = (CardLayout) mainPanel.getLayout();
cl.show(mainPanel, GAME);
introPanel.lblDataSetText("Hello!"); // !!
}
});
Note that this is a quick and dirty solution. If you want a more robust solution that scales better in larger programs, then re-structure your program along an M-V-C design pattern, and have your view change the displayed text in response to a change in the state of a String in the model. This would require more work, and in a small "toy" program wouldn't be worth the effort, but in a large complex program is well worth the effort since it would help reduce coupling and thereby reduce complexity and risk of bugs.

Adding JPanel to JMenuItem

I have added buttons and text fields to a panel, but when I try to add the panel to the MenuItem nothing happens. I have defined an ActionListener for the MenuItem in which I am adding the JPanel. No error is detected by the compiler, but nothing happens when I click the MenuItem. How can I resolve this issue?
public class MenuFrame extends JFrame {
private JMenu customers;
private JMenu purchase;
private JPanel panel1 = new JPanel();
public MenuFrame() {
JButton button = new JButton();
panel1.add(button);
customers = new JMenu("Customers");
JMenuItem createInvoice = new JMenuItem("Create");
JMenuItem updateInvoice = new JMenuItem("Update");
JMenuItem deleteInvoice = new JMenuItem("Delete");
sales.add(createInvoice);
PanelHandler p = new PanelHandler(panel1);
createInvoice.addActionListener(p);
}
private class PanelHandler implements ActionListener {
private JPanel panel;
public PanelHandler(JPanel p) {
this.panel = p;
}
public void actionPerformed(ActionEvent e) {
// getContentPane().removeAll();
// getContentPane().setVisible(true);
// JButton b=new JButton("Enter");
// panel.add(b);
panel.setVisible(true);
add(panel, BorderLayout.SOUTH);
getContentPane().doLayout();
// update(getGraphics());
}
}
}
Don't invoke doLayout() directly.
When add (or remove) components from a visible GUI the basic code is:
panel.add(...);
panel.realidate(); // to invoke the layout manager
panel.repaint(); to repaint components

How to replace current JPanel with another JPanel?

I am trying to transit from a UserAdminPanel to AdminLogin within the same JPanel when I press the Admin button.
UserAdmin Panel
transit to AdminLogin Panel
The problem I have now is that I am opening up a new panel instead of changing the current panel to the new panel.
This is my code for the UserAdminPanel
public class SelectAdminUserPanel extends JPanel
{
public SelectAdminUserPanel()
{
setLayout(new GridLayout(3,1));
JButton b1 = new JButton("User Login");
JButton b2 = new JButton("Admin Login");
JButton b3 = new JButton("Exit");
b1.addActionListener(new SelectUserButtonListener() );
b2.addActionListener(new SelectAdminButtonListener());
b3.addActionListener(new SelectExitButtonListener() );
add(b1);
add(b2);
add(b3);
}
private class SelectAdminButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
AdminModule am = new AdminModule();
am.run();
}
}
private class SelectUserButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
GameModule gm = new GameModule();
gm.run();
}
}
private class SelectExitButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
}
}
}
This is the code for the AdminLogin Panel
public class AdminLoginPanel extends JPanel
{
AdminLoginPanel()
{
JLabel pwlabel = new JLabel("Password");
JPasswordField pwfield = new JPasswordField(20);
JButton loginbutton = new JButton("Login");
add(pwlabel);
add(pwfield);
add(loginbutton);
}
}
I have looked at the following example and this example but it's not very applicable because it talks about CardLayout instead of like rewriting the current JPanel.
I think that you should have a reference to your main frame and just remove the components from it based on the button pressed and add only the required components. From what you say, UserAdminPanel is your main panel. I think it's added to a frame for which you can obtain a reference. When you click a button, you want to remove all the content shown on it and display only what the button clicked should show. I think it should look something like this:
private class SelectAdminButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.getContentPane().removeAll();
AdminModule am = new AdminModule();
frame.add(am.getNewPanel());
frame.pack();
// am.run(); //it's not clear what does for you
}
}
Where the method getNewPanel() would return the underlying JPanel. I'm assuming that AdminModule has a reference to the AdminLoginPanel.

Categories