I've looked at other JLabel threads and though similar, a few just don't seem to apply to what I'm experiencing. First, I want to say I am a novice when it comes to Java. Next, I am trying to follow tutorials and demos at the docs.oracle.com site. Now, I can update the label when I type something into a JTextField and there is an ActionListener on that...
But I also have a Menu, and when I select a Menu Item, that Action does not want to update the label.
Questions -
How do I have action listeners on both JTextFields and JMenuItems? Are there two ActionEvent methods or do I use one method and somehow identify each type of action?
If I use the same basic code in the JTextField ActionEvent and JMenuItem ActionEvent, the JLabel updates correctly with the JTextField event but not JMenuItem event. They both use the messageField.setText property. Could the JMenuItem action be doing something to block the setText?
I can easily copy code in here, but it's pretty spaghetti-like at the moment, so if you want to see anything, let me know specifically and I'll post it.
I would appreciate any assistance that anyone would be able to provide.
---edit---
Wow!! Thanks for all of the comments and suggestions.
1 - I know it has to be my code. As I mentioned, I am really just cobbling stuff together from demos and tutorials, and trying to learn Java along the way. I've just never gotten the hang of object oriented....
2 - I do know the individual Listeners are working. I'm using System.out.println to validate, as well as inspecting those labels in debug mode to see they have indeed changed.
3 - I will look at the various links and code posted here and see if I can figure out what's wrong with my code.
Really, thanks again!
---edit---
Here is what I originally had in my createAndShowGUI method....
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Create XML for Photo Gallery");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(new CreateGalleryXML());
frame.pack();
frame.setVisible(true);
}
Seems like you yourself are doing something wrong, in your code. Without a proper SSCCE it's hard to say what thing you doing wrong, since it works perfectly, using same ActionListener for both JMenuItem and JTextField.
Here is a sample program to match with yours :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class UpdateLabel
{
private JLabel label;
private String labelText;
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
setLabelText((String) ae.getActionCommand());
label.setText(getLabelText());
}
};
private void setLabelText(String text)
{
labelText = text;
}
private String getLabelText()
{
return labelText;
}
private void createAndDisplayGUI()
{
final JFrame frame = new JFrame("Update Label");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(true);
JMenuBar menuBar = new JMenuBar();
JMenu programMenu = new JMenu("Program");
JMenuItem exitMenuItem = new JMenuItem("Exit");
exitMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
frame.dispose();
}
});
JMenu labelMenu = new JMenu("Label");
JMenuItem updateMenuItem = new JMenuItem("Update Label");
updateMenuItem.setActionCommand("Updated by JMenuItem");
updateMenuItem.addActionListener(action);
programMenu.add(exitMenuItem);
labelMenu.add(updateMenuItem);
menuBar.add(programMenu);
menuBar.add(labelMenu);
frame.setJMenuBar(menuBar);
JPanel contentPane = new JPanel();
label = new JLabel("I am the LABEL which will be updated!!");
contentPane.add(label);
JTextField tfield = new JTextField(10);
tfield.setActionCommand("Updated by JTextField");
tfield.addActionListener(action);
frame.add(contentPane, BorderLayout.CENTER);
frame.add(tfield, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new UpdateLabel().createAndDisplayGUI();
}
});
}
}
And here is the output in both the cases :
and
Do check out the main method, might be you had failed to put your code inside EDT - Event Dispatcher Thread, that can lead to such issues too. All updates on the Swing GUI, must be done on the Event Dispatcher Thread.
LATEST EDIT
It seems to me that CreateGalleryXML extends JPanel by the look of it. See at Line 3 of this below code taken from your update, here you are initializing a new Object of CreateGalleryXML inside, when you already had one Object window created at Line 1:
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(new CreateGalleryXML());
So try to change the above thingy to this
CreateGalleryXML window = new CreateGalleryXML();
frame.setJMenuBar(window.createMenuBar());
frame.add(window);
and see what happens and Please do revert back again :-)
Use Action to encapsulate common functionality that must be shared by menus and related components. See this example that extends AbstractAction.
Pretty much everything you could need to know is in the Java tutorials. Down the bottom they have demo's on how to do both menu's and text fields. They include source code to look at as well.
There's not much more I can say that they don't say better, but in answer to your questions:
Both, you can have separate listener's on each component, or one that figures out what component is responsible for causing the action event. I would suggest you use separate ones for each thing.
Can't really say with out seeing the code, are you sure that the action on the JMenu is even firing? Does it print something to the console etc if you use System.out.println somewhere?
Related
"This method creates an object but does not assign this object to any variable or field. This implies that the class operates through side effects in the constructor, which is a bad pattern to use, as it adds unnecessary coupling. Consider pulling the side effect out of the constructor, into a separate method, or into the calling method."
This short test program runs as I expected, but I don't know how to address this checkstyle error. Most of the examples of using javax.swing seem to have this structure.
There is also a error causes by EXIT_ON_CLOSE, but without it the process lingers after I close the window and must be force quit.
public class GUI implements ActionListener {
private int clicks = 0;
private JLabel label = new JLabel("Clicks= " + clicks);
private JFrame frame = new JFrame();
public GUI() {
// make a Jbutton named button
JButton button = new JButton("Click Me");
button.addActionListener(this);
// arrange the button and label
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
// put the panel in a frame
frame.add(panel, BorderLayout.CENTER);
// EXIT_ON_CLOSE has a style error too.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Graphical User Interface");
frame.pack();
frame.setVisible(true);
}
// update label and number of clicks when button is clicked
public void actionPerformed(ActionEvent e) {
clicks++;
label.setText("Clicks= " + clicks);
}
// This is the code that InteliJ says has bad form.
public static void main(String[] args) {
new GUI();
} }
One bad pattern here is that you are not creating your GUI on Event Dispatch Thread. Not sure if this is related to your problem.. but you should always use EDT to create the GUI in Swing.
EDIT: take a look here. In the main method you just have "new GUI()" without a reference variable. Writing your app like this example you are not going to use the constructor to create all :)
I am trying to open a GUI from my main GUI by pressing a button. When the button is pressed, this is executed:
WorkloadFactor wf = new WorkloadFactor();
wf.setVisible(true);
This doesn't open the WorkloadFactor GUI. I am confused by this because I have other GUIs that open this way without issue.
WorkloadFactor class works fine when I run it by itself but won't open when it is called by my main GUI. Below is my class without imports and stuff:
public class WorkloadFactor extends JPanel {
public WorkloadFactor() {
setLayout(new BorderLayout());
JTabbedPane tabbedPane = new JTabbedPane();
String[] tabnames = { "Zero", "One", "Two", "Three", "Four" };
for (int i = 0; i < tabnames.length; i++) {
tabbedPane.addTab(tabnames[i], createPane(tabnames[i]));
}
tabbedPane.setSelectedIndex(0);
JButton submit = new JButton("Submit All");
submit.setForeground(Color.RED);
add(tabbedPane, BorderLayout.CENTER);
add(submit, BorderLayout.SOUTH);
}
public JPanel createPane(final String t) {
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
//setContentPane(contentPane); I think this might be it?
contentPane.setLayout(null);
setBounds(100, 100, 531, 347);
//***** all the components I am including then add them like so
//******contentPane.add(checkbox1);
//****** contentpane.add(label1);
return contentPane;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Set Workload Factor Information");
frame.getContentPane().add(new WorkloadFactor());
frame.setBounds(100, 100, 531, 347);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}
I have tried arranging things in so many ways, putting everything in the constructor and other changes but can't seem to find a reason why instantiating this WorkloadFactor class elsewhere and setting it visible won't work.
Does it have something to do with setContentPane(contentPane) vs contentPane.add(xxxx) and returning it?
Thank you for reading!
WorkloadFactor wf = new WorkloadFactor();
wf.setVisible(true);
To be blunt, this won't display anything. Please understand that WorkloadFactor extends JPanel and like all non-top level components must be placed into a container that is ultimately held by a top-level window in order to be displayed. Look at how you display it in your main method -- you first put it into a JFrame, and then display that JFrame. You must do the same thing if you want to display it on button press -- you need to put it into a JPanel or other container that is held by a JFrame or JDialog, or JOptionPane.
Make sure that you have properly registered the button on your main GUI which opens WorkLoadFactor GUI to an action listener.
Since you have not included code from your main GUI I can't confirm this is the issue. However it is a commonly overlooked issue.
Heres some suggestions from the Java documentation tutorials:
"Problem: I'm trying to handle certain events from a component, but the component isn't generating the events it should.
First, make sure you registered the right kind of listener to detect the events. See whether another kind of listener might detect the kind of events you need.
Make sure you registered the listener on the right object.
Did you implement the event handler correctly? For example, if you extended an adapter class, then make sure you used the right method signature. Make sure each event-handling method is public void, that the name spelled right and that the argument is of the right type."
source: Solving Common Event-Handling Problems
Make a JFrame and add a JButton in it than add action listener in button and add this code in it like this:
This code makes a frame with a button and when button is pressed new window is opened.
public class Example extends JFrame {
public Example() {
super("Title");
setLayout(new FlowLayout());
JButton b = new JButton("Open new Frame");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
newWindow nw = new newWindow();
}
});
add(b);
}
}
newWindow Code:
public class newWindow extends JFrame {
newWindow() {
super("title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setVisible(true);
}
}
I am trying to make a refresh button that will essentially restart the program when ever I click the button. I don't know how I should go about doing this.
I've place the Graphical User Interface i decided to use do complete this action. Any and all help would be greatly appreciated.
package pdfView;
import javax.swing.*;
import java.awt.*;
public class View extends JFrame {
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
JButton ReFresh = new JButton("ReFresh");
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.squing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc){
}
}
public static void main(String[] args) {
View pdf = new View();
}
}
What do you mean by refresh or restart?
Do you mean:
Let the application be as it is, just update what it's showing?
Really restart the application?
Updating what the application is showing
You first need to decide what actually should cause your application to refresh. You already talked about a Button. The mechanism for activating something like a button is called Action. You can do that stuff manually, using an ActionListener, or you could extend AbstractAction, which is what I recommend. Extending AbstractAction allows you to use the same logical action something in more than one location on the UI. Look at typical applications, they offer Cut/Copy/Paste through menu, toolbar, popupmenu and keyboard shortcuts. The simplest way to achieve this in Java is using Action by extending AbstractAction.
The methods you need to call to update your application are invalidate(), validate() or repaint().
Restarting an application
So you want to run through main() again? That should actually not be required, unless you have an application that supports updating itself. Even then it can sometimes be avoided by smart usage of a ClassLoader.
Some more notes on your code
Usage by extension anti-pattern
I wouldn't extend JFrame just to display a window on the screen. Usage by extension is an anti-pattern. You don't need to extend JFrame to get a JFrame displayed on the screen and do what you want.
Referring static members
I would refer to constants via their original declaration. I.e. I'd refer to EXIT_ON_CLOSE via WindowConstants.EXIT_ON_CLOSE, not JFrame.EXIT_ON_CLOSE.
Typo
You have a typo in your UIManager.setLookAndFeel() code. Search for swing and you will see the typo.
Exception information
You might actually want to print the exception to stderr using exc.printStackTrace() instead of ignoring it completely, because when you have a typo in the LaF class name, as you do, and you don't print the exception, you might actually not come to know what's going wrong.
Sequence of widget construction and UIManager.setLookAndFeel()
The sequence of UIManager.setLookAndFeel() and the effective new JFrame() via super(...) does not guarantee you that the whole UI will be in Nimbus, parts of it might still be in Metal. I recommend to set the LaF before even constructing the first widget, to be on the safe side. As far as I remember, it's not guaranteed that changing the LaF after component construction has an effect, unless you tell the UIManager to update the LaF. See also this quote from the documentation of UIManager:
Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
setSize() vs. pack() with a little help of Insets and Border
Instead of setting the size manually, you might want to play with Insets or Border and JFrame.pack() in order to get a decent layout of your window. Setting the size manually assumes that you know a lot about the screen resolution and the font size of the user.
The pack() method performs automatic size calculation based on the contents. Insets and Border allow you to create some space and borders, even with some designs or labels, around components so they wouldn't be cramped tightly in a window but be nicely spaced.
First you have to assign an actionListener to the ReFresh Jbutton.
You can either implement the interface ActionListener to the class, and override the actionPerformed() method like this
public class View extends JFrame implements ActionListener{
private JButton ReFresh;
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
ReFresh = new JButton("ReFresh");
ReFresh.addActionListener(this);
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() { //right way for nimbus: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.equals(ReFresh))
{
super.repaint();
}
}}
public static void main(String[] args) {
View pdf = new View();
}
Or you can do inline assignment to addActionListener, like this
ReFresh.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
super.repaint();
}
});
You can try these methods to refresh/reload the JFrame,
invalidate();
validate();
repaint();
you can also use dispose(); and then new View(); to create the new JFrame, but in this sequence it will close the window and create new one.
or you can even try setVisible(false); then setVisible(true);
I recommend the first 3.
What I'm trying to do is create a very basic button click game much like "AdVenture Capitalist" and several other casual games like it. Nothing quite as fancy. I'm using FlashDevelop (AS3) and I'm trying to figure out how to create a button then every time that button is pressed it adds +1 to my main value represented on screen.
I'd also like to figure out how to make a button that would automate the clicking process.
If anyone could show me how, or direct me to a specific page that would help me out I would be very thankful.
I'm also not sure if Actionscript is the best language to write this in. If you have a recommendation that I can use FlashDevelop with I would appreciate the tip!
Thank you!
I have idea about the how this operation will be performed in java. For example creating buttons and labels. As long as you need to combine java and flash this link is useful for starters. If you need only java the following snippet will be useful. Also learn java swing from JavaDocs for GUI purpose
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonClick
{
int counter = 0;
public ButtonClick()
{
JFrame frame = new JFrame("Title");
JButton btn = new JButton("Click me");
JLabel clicks = new JLabel("");
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
counter++;
clicks.setText("Number of clicks till now :"+Integer.toString(counter));
frame.repaint();
}
});
frame.add(btn);
frame.add(clicks);
frame.setVisible(true);
}
public static void main(String []args)
{
ButtonClick c = new ButtonClick();
}
}
I'm trying to get my first UndoManager work, but I got a problem with the prototype. I don't understand why the following code provides only one single undo.
When I change the text, click undo and change the text again, another undo won't do anything. Where is the catch?
import java.awt.*;
import javax.swing.*;
public class IComeUndone
{
public static void main(String[] args)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextArea textArea = new JTextArea(20, 40);
textArea.setText("Back here");
f.add(textArea);
final UndoManager undoManager = new UndoManager();
textArea.getDocument().addUndoableEditListener(undoManager);
undoManager.setLimit(1000);
JButton undoB = new JButton("Undo");
undoB.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
undoManager.end();
if(undoManager.canUndo())
{
undoManager.undo();
}
textArea.requestFocus();
}
});
f.add(undoB, BorderLayout.PAGE_END);
f.pack();
f.setVisible(true);
}
}
Update:
When I comment out the undoManager.end(); line, it works fine, but each click on undo does only undo one single edit, like one typed letter. I wanted to undo a group of single edits, so that the undoManager.end(); makes sense at this point. But I can't restart the tracking of single edits after undo has been clicked the first time. (Hope you can understand)
Interesting one, it seems that once you call end() it converts the UndoManager into a CompoundEdit and then there is more work that you have to do. The following link has as example: http://tips4java.wordpress.com/2008/10/27/compound-undo-manager/