Change JLabel text from another class - java

I have the following class that draws a Label. (I have only given part of the code here). Everyhting works fine, the label gets displayed.
Now, i have another class called Caller Class. I have a method in that where i will use to change the value of this label. how can i do that
public class MyClass{
private JLabel label;
MyClass(){
run();
}
public void editTheLabelsValue (String text) {
label.setText(text);
frame.repaint();
}
run(){
.... // there were more code here, i removed it as it's not relevant to the problem
label = new JLabel("Whooo");
label.setBounds(0, 0, 50, 100);
frame.getContentPane().add(label);
.....
}
later on, i will be using the following class to change the text of the above label. How can i do this.
public class Caller {
void methodA(){
MyClass mc = new MyClass();
mc.editTheLabelsValue("Hello");
}
}
1.) When the methodA() is executed, the text Hello is not getting displayed on the Label field. it still remains as Whooo. How can i correct this. I want the label text to be Hello once that method has been executed.

The immeditate problem I can see is to appears that you are either using a null layout or your don't understand how layout managers work.
The following code updates the label from the main class in a sub class via a setText method call. This method is called every second
public class PaintMyLabel {
private int counter = 0;
public static void main(String[] args) {
new PaintMyLabel();
}
public PaintMyLabel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final MasterPane master = new MasterPane();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(master);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter++;
master.setText("Now updated " + counter + " times");
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
});
}
public class MasterPane extends JPanel {
private JLabel label;
public MasterPane() {
label = new JLabel("Original text");
setLayout(new GridBagLayout());
add(label);
}
public void setText(String text) {
label.setText(text);
}
}
}
If you're using a null layout, then stop it. Just don't. There are only a very small number of times you would ever use a null layout and I suspect this isn't one of them.

Related

split GUI in few classes

I'm writting a program and the GUi Class (main class) is overloaded.
I want to know if it's possible to split the class in several classes.
for example I made a class of constaints.
The main question is if I can keep all interface code in one class(where I'll addd and initialize JTetxFields,JButtons and other Jobjects) and then use them in another class.
for example:
in interface class there will be:
JTextField field = new JTextField(12);
JButton button = new JButton("Click");
and in main class I do smthng like this:
add(field);
add(button);
button.addActionListener(this);
public void actionPerformed(ActionEvent e) {
if(e.getSource==button){
field.setVisible(false);
}
if it's possible with creating new JFrame,then please tell me how to create new Frame and use it in main class.
Your main question -- can you create a class that is a repository of your GUI components and use them elsewhere, and the answer is yes you can, but I don't think that you should, at least not for simple components. You should keep your JTextFields, JButtons in the GUI classes that use them, but any major subsection of your GUI, such as a JPanel that contains components and that has a unique functionality, that can go in its own class.
More important is to separate out different functional parts of your program, especially you should try to separate out the logical or "model" part of your program from the GUI or "view" part. The details of how you do this will depend on the details of your program and overall problem.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SeparateClasses {
private static void createAndShowGui() {
SeparateClassView mainPanel = new SeparateClassView();
new SeparateClassControl(mainPanel);
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
public class SeparateClassView extends JPanel {
private JTextField field1 = new JTextField(12);
private JTextField field2 = new JTextField(12);
private JTextField resultField = new JTextField("false", 5);
private JButton button = new JButton("Click");
public SeparateClassView() {
resultField.setEditable(false);
resultField.setFocusable(false);
add(new JLabel("Field 1:"));
add(field1);
add(new JLabel("Field 2:"));
add(field2);
add(button);
add(new JLabel("Two texts equivalent?:"));
add(resultField);
}
public void addButtonListener(ActionListener listener) {
button.addActionListener(listener);
field1.addActionListener(listener);
field2.addActionListener(listener);
}
public String getField1Text() {
return field1.getText();
}
public String getField2Text() {
return field2.getText();
}
public void setField1Text(String text) {
field1.setText(text);
}
public void setField2Text(String text) {
field2.setText(text);
}
public void setResult(boolean result) {
resultField.setText(String.valueOf(result));
}
}
public class SeparateClassControl implements ActionListener {
private SeparateClassView view;
public SeparateClassControl(SeparateClassView view) {
this.view = view;
view.addButtonListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
String text1 = view.getField1Text();
String text2 = view.getField2Text();
boolean result = SeparateClassModel.stringsEquivalent(text1, text2);
view.setResult(result);
}
}
public class SeparateClassModel {
public static boolean stringsEquivalent(String text1, String text2) {
return text1.equalsIgnoreCase(text2);
}
}

Pass a String to another class

I'm writing an application where I need to get two String objects from the GUI to the nullObject class.
I'm relatively new to programming, and am trying my best to learn. If you have any tips on how to make this better, I'd be really thankful!
My GUI class:
package com.giuly.jsoncreate;
public class GUI {
private JFrame startFrame;
private JFrame chkFrame;
private JFrame osFrame;
private JFrame appVFrame;
private JPanel controlPanel;
private JButton nextPage;
private JButton cancel;
private JButton save;
public GUI() {
generateGUI();
}
public static void main(String[]args) {
GUI gui = new GUI();
}
public void generateGUI() {
//Creation of the First Frame
startFrame = new JFrame("JSCON Creator");
startFrame.setSize(1000, 700);
startFrame.setLayout(new FlowLayout());
startFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Panel Creation
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
//Button Creation
cancel = new JButton("Cancel");
cancel.setSize(100, 100);
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
nextPage = new JButton("Next");
nextPage.setSize(100, 100);
nextPage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
startFrame.setVisible(false);
showText();
}
});
startFrame.add(controlPanel);
startFrame.add(cancel);
startFrame.add(nextPage);
startFrame.setVisible(true);
startFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public void showText() {
JFrame textFrame = new JFrame();
textFrame.setSize(1000, 700);
textFrame.setTitle("Text");
textFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JPanel textPanel = new JPanel();
JLabel titleLabel = new JLabel("Title");
textPanel.add(titleLabel);
JLabel descrLabel = new JLabel("Description");
JTextField tfTitle = new JTextField("",15);
tfTitle.setForeground(Color.BLACK);
tfTitle.setBackground(Color.WHITE);
JTextField tfDescr = new JTextField("",30);
tfDescr.setForeground(Color.BLACK);
tfDescr.setBackground(Color.WHITE);
textPanel.add(tfTitle);
textPanel.add(descrLabel);
textPanel.add(tfDescr);
JButton buttonOK = new JButton("OK");
textPanel.add(buttonOK);
buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String jsonTitle = tfTitle.getText();
String jsonDescr = tfDescr.getText();
System.exit(0);
}
});
textFrame.add(textPanel);
textFrame.setVisible(true);
}
I want to get the Strings jsonTitle and jsonDescr into another class, so I can store them. In the end I will have some Strings and I need to save them in a JSON file. I need a way to get those two Strings, what advice do you guys have?
Erick is correct with his answer. Just thought I should add additional info. If you declare jstonTitle and jsonDescr like your other fields using private you still will not be able to access these fields from another class. Coding up a getter for the fields along with declaring them at the top of GUI should solve your problem. Then just create an instance of GUI in your other class and call the method.
public String getJsonTitle(){
return this.jsonTitle;
}
You're declaring jstonTitle and jsonDescr inside the actionPerformed() method. That means that as soon as actionPerformed() exits you'll lose those variables. You need to declare them in an enclosing context. For example, you could make them fields on the GUI class. Still assign them in actionPerformed(), but declare them up at the top of GUI where you're declaring startFrame, chkFrame, etc.
That will give you the ability to access those values from anywhere within GUI.
Oh, BTW, get rid of System.exit(0);. (Have you actually tried to run your program?)

JLabel that changes text from one thing to another

I'm working on this program and I ran into another issue. I have a Jframe with a JLabel that I wish for it to change text from one thing to another. However, when I try to do that it doesnt show me the text changing, rather the last text I set it to.
How do I get my JLabel to cycle through text SLOWLY?
I'm trying a wait method to make the program go slowly so I can see if I can make it cycle through, but that doesnt seem to be working.
it would be helpful if someone could edit my code or make their own example of how to do this, THANKS!
public class CreditGraphics {
public String cardNum;
public JFrame frame;
public JPanel panel;
public JLabel label;
public JTextField text;
public CreditGraphics() {
synchronized(this){
try {
frame = new JFrame("HI");
panel = new JPanel();
label = new JLabel();
text = new JTextField(16);
panel.add(label);
panel.add(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
wait(4000);
label.setText("Hi");
wait(4000);
frame.revalidate();
frame.repaint();
label.setText("Hello");
frame.revalidate();
frame.repaint();
text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardNum = text.getText();
}
});
}
catch(InterruptedException e) {
e.printStackTrace();
}}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CreditGraphics();
}
});
}
public void checkCard(){
}
}
As suggested by #trashgod use Swing Timer that is more suitable for swing application to perform a task once, after a delay or to perform a task repeatedly.
sample code:
private Timer timer;
...
label.setText("Hi");
// delay of 4 seconds
timer=new Timer(4000,new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("Hello");
// timer.stop(); // stop the timer if repeated mode is on
}
});
timer.setRepeats(false); // you can turn-on it if needed
timer.start();
Note:
There is no need to call frame.repaint() and frame.revalidate() in this case.
Override getPreferredSize() to set the preferred size of the JPanel in case of custom painting.
sample code:
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
};
read more...
Do not use Thread.sleep() or wait() as it will freeze your Swing application.
Instead you should use a javax.swing.Timer
See the Java tutorial How to Use Swing Timers and Lesson: Concurrency in Swing for more information and examples.

Java, menuBar, JMenuitems Focus

I have created JMenuItems with Key Accelerators, then i have added them to the menubar directly without the need to be added to the JMenu so they look like JButtons, every thing work just fine, but i noticed that JMenuItem never get focus when clicked or key pressed, that make some problems to me for example:
One of the JMenuItems is for save, also i have one JTextField which do some validation when losing focus, but that not working since when pressing the Save, the focus kept there on the JTextField.
Any Ideas ?!
I'd suggest using a JToolBar and taking advantage of the Action API
Here's a really short example of how you might be able to achieve accelerator support for toolbar (or any) button.
public class MenuTest {
public static void main(String[] args) {
new MenuTest();
}
public MenuTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JToolBar tb = new JToolBar();
tb.add(new FastButton(new OpenAction()));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(tb, BorderLayout.NORTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class FastButton extends JButton {
private FastButton(Action action) {
super(action);
setHideActionText(true);
}
#Override
protected void configurePropertiesFromAction(Action a) {
super.configurePropertiesFromAction(a);
if (a != null) {
KeyStroke ks = (KeyStroke) a.getValue(Action.ACCELERATOR_KEY);
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(ks, "Action.accelerator");
actionMap.put("Action.accelerator", a);
}
}
}
public class OpenAction extends AbstractAction {
public OpenAction() {
putValue(NAME, "Open");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
putValue(SMALL_ICON, new ImageIcon(getClass().getResource("/folder_document.png")));
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Open");
}
}
}

User-Interface question

i'm kinda new to manipulating UI in java, so pls forgive me for this question i cant find the answer anywhere.
Description
| i'm trying to do a card game and i have an engine class that manipulates all the cards and plays made, and i want the engine to tell the UI to update the score, card position or card image.
this is an example of how i start the UI, problem here is i don't have any instance to manipulate the JLabels using the instance methods i made inside Board class, and i can't create a instance outside of the EventQueue because i would be violating "never manipulate/create UI outside UI thread"
public class Engine {
public StartUp(){
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (UnsupportedLookAndFeelException e) {
}
new Board().setVisible(true);
}
});
}
}
the Board class extends JPanel and adds some JLabels to the ui in the constructor , and has several methods to change text and imgs.
My question is how to properly call these methods(the ones i created to alter text and img), i'm also open o any other suggestions on how to approach this problem.
*edited:
here's simple example of my Board Class:
public class Board extends JFrame{
public JLabel img1;
public Board(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 265);
JPanel body = new JPanel(new GridBagLayout());
getContentPane().add(body);
img1 = new JLabel();
body.add(img1);
}
public void setImg1(String s){
img1.setIcon(new ImageIcon(s));
}
}
i want to be able from Engine to access setImg1(String s) method that is inside the Board to be able to change the current image during runtime
sorry if i expressed my question wrong
final edit:
solved it merging the Engine into the Board.
ty to everyone that helped and for your time
public class MainFrame extends JFrame {
public MainFrame() {
super("Demo frame");
// set layout
// add any components
add(new Board()); // adding your board component class
frameOptions();
}
private void frameOptions() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); // or setSize()
setVisible(true);
}
public static void main(String[] a) {
JFrame.setDefaultLookAndFeelDecorated(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
new MainFrame();
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
}
The basic idiom for getting a GUI up is:
SwingUtilities.invokeLater(new Runnable() {
JFrame frame = new JFrame("My Window Title");
frame.setSize(...);
frame.add(new Board()); // BorderLayout.CENTER by default
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null); // center on main screen
frame.setVisible(true);
});

Categories