I'm having troubles with this program. Everything works, but the program keeps opening the JFrame over and over again (and obviously, I only want just one JFrame to be opened). What is wrong with my code?
Thank you in advance,
Stefan
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ColoredWords {
JFrame frame;
JPanel controlPanel, wordsPanel;
JButton match, nomatch;
ColoredWords() {
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
frame = new JFrame("Colored Words Experiment");
wordsPanel = new JPanel();
controlPanel = new JPanel();
frame.setLayout(new BorderLayout());
frame.add(wordsPanel, BorderLayout.NORTH);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.setSize(1000, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
match = new JButton("Matching");
nomatch = new JButton("Non-Matching");
controlPanel.add(match, BorderLayout.WEST);
controlPanel.add(nomatch, BorderLayout.CENTER);
ClicksReporter clicksreporter;
clicksreporter = new ClicksReporter();
match.addActionListener(clicksreporter);
nomatch.addActionListener(clicksreporter);
}
} );
}
class ClicksReporter extends ColoredWords implements ActionListener {
Labeling labeling = new Labeling();
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Matching")) {
wordsPanel.add(labeling);
} else if (e.getActionCommand().equals("Non-Matching")) {
wordsPanel.add(labeling);
}
}
}
public static void main(String[] arg) {
new ColoredWords();
}
}
class Labeling extends JPanel {
JLabel[] labelsList = new JLabel[20];
int i = 0;
public Labeling() {
while (i < 5) {
labelsList[i] = new JLabel("black");
setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
labelsList[i].setOpaque(true);
labelsList[i].setBackground(Color.white);
add(labelsList[i]);
i++;
}
}
}
The problem is when you instantiate ClicksReporter inside main(). This is because it inherits the constructor of ColoredWords, calling it when instantiated. To avoid this, you can take the program code out of the constructor and into another method, say, execute() or run(). You can then adjust your program accordingly to call this method in main().
Your ColoredWords constructor calls clicksreporter = new ClicksReporter(); but ClicksReporter inherits ColoredWords, so the constructor of ColoredWords gets called, wich will again execute clicksreporter = new ClicksReporter(); and so on... You get stuck in an infinite loop. Try to remove inheritance.
You create a new JFrame in your ColoredWords constructor.
You create a new ClicksReporter in your ColoredWords constructor.
ClicksReporter extends ColoredWords.
That means every ColoredWords construction leads to another ColoredWords construction, which also creates a JFrame.
Related
First I am a beginner in java. I'm making a window with small button and a label (with 0 in default position), when I click on the button the label will change to 1 and when I tap another click the button will be 2. But, I have an error in calling the method.
my code:
package prototype;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Prototype {
public static int count;
public static JLabel l;
public void Proto()
{
JFrame f = new JFrame();
JButton b = new JButton("click");
JLabel lo = new JLabel("0");
JPanel p = new JPanel();
f.setBounds(120,120,500,500);
b.addActionListener(new MyAction());
p.add(lo);
p.add(b);
f.getContentPane().add(p,BorderLayout.CENTER);
f.show();}
public class MyAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
count++;
l.setText(Integer.toString(count));}
public static void main(String[] args) {
//I want to call the proto method but it give me an eror
new proto();
}}}
public class Prototype extends JFrame{
private static int count;
private JLabel l;
public Prototype() {
super();
JButton b = new JButton("click");
l = new JLabel("0");
JPanel p = new JPanel();
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
count++;
l.setText(Integer.toString(count));
}
});
p.add(l);
p.add(b);
this.getContentPane().add(p, BorderLayout.CENTER);
this.pack();
this.setVisible(true);
}
public static void main(String...args){
Prototype p=new Prototype();
}
}
I changed the method to a constructor, to have the possibility of creating a object of type Prototype and directly create a frame with it. Also I extended the class with JFrame to not need to create an extra JFrame. Next step was to remove the ActionListener class and creating a new ActionListener while adding it to the button. In my eyes this is useful if you have several buttons with different functionalities, so you can see the function of the button directly just by looking at the code of the button. and the last step was to create a new Object of type Prototype in the main method
If I we're you use a SwingWorker instead of manually setting the text of JLabel. Because this is not a proper way updating your GUI. This should be done using SwingWorker. Please read about publish and processmethod.
Hello I would like to ask how can I call my Main menu screen from MainScreen? and kindly explain a little more details about Listener.
below is my prepared code:
public class MainScreen {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
placeComponents(panel);
frame.setVisible(true);
}
private static void placeComponents(JPanel panel) {
JLabel WelcomeNote = new JLabel("Welcome");
panel.add(WelcomeNote);
JButton Start = new JButton("Start");
panel.add(Start);
//Insert action for Start button here
}
}
public class MainMenu {
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
placeComponents(panel);
frame.setVisible(true);
}
private static void placeComponents(JPanel panel) {
JLabel menuLbl = new JLabel("Main Menu");
panel.add(menuLbl);
}
}
What is wrong?
You cannot have two main methods in a single file in Java.
Program
Here is a demo program to change windows.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
class First extends JFrame
{
JLabel jlb = new JLabel("Label in First Window");
JButton jb = new JButton("Next Window");
First()
{
super("First Windows");
//Set this frame
this.setSize(350,250);
this.setLayout(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Setting size of components
jlb.setBounds(10,10,200,40);
jb.setBounds(10,120,150,40);
add(jlb);
add(jb);
jb.addActionListener((e)->{
this.setVisible(false);
new Second();
});
setVisible(true);
}
}
class Second extends JFrame implements ActionListener
{
JLabel jlb = new JLabel("Label in Second Window");
JButton jb = new JButton("Prev. Window");
Second()
{
super("Second Window");
this.setSize(350,250);
this.setLayout(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Setting size of components
jlb.setBounds(10,10,200,40);
jb.setBounds(10,120,150,40);
add(jlb);
add(jb);
jb.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
this.setVisible(false);
new First();
}
}
class StartHere
{
public static void main(String[] args) {
Runnable r = ()->{
new First();
};
r.run();
}
}
Understanding the above program.
The StartHere class has a main method. It is just used for calling the first window you like. I could even call Second using new Second().
First and Second are similar codes.
Both of them have buttons. On each button (or JButton) I have added a method named addActionListner(this). This method fires up an ActionEvent which as you can see in Second class is captured by actionPerformed method. This method is declared in Functional Interface, ActionListener. The 'this' passed in Second class is you telling where the actionPerformed method is present in your code. The parameter is an ActionListener. Hence, you have to implement ActionListener for the class where you define actionPerformed.
Bonus
The First class doesn't seem to follow the norms described above. I passed a strange syntax. It is a new feature included in Java 8.
See this Oracle tutorial about Lambda Expressions.
I have 2 classes. Both implements runnable to create the GUI. The first one is the main, and the second one is the secondary class.
I want within the actionlistener of the main class to startup the secondary class.
Here is the code (the two classes are separated files):
public class Main implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
private class SListener implements ActionListener
{
public void actionPerformed(ActionEvent a)
{
Secondary s = new Secondary();
}
}
public static void main (String[] args)
{
Main gui = new Main();
SwingUtilities.invokeLater(gui);
}
}
public class Secondary implements Runnable
{
private JTextField txt1, txt2;
private JLabel lbl1, lbl2;
public Secondary()
{
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
public void run()
{
JFrame frame = new JFrame("Secondary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = frame.getContentPane();
JPanel background = new JPanel();
background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));
.........
// Horizontally adding the textbox and button in a Box
Box box = new Box(BoxLayout.Y_AXIS);
......
background.add(box);
pane.add(background);
frame.pack();
frame.setVisible(true);
}
}
I want to keep the code in two files, I don't want to mixed the two classes in one file.
As you can see from the code, in the Secondary class, in it's constructor I create an Instance of the Secondary class and I run the gui so that when the Instance of this class is created in the Main class, to run the gui.
Unfortunately this technique is not working.
Any ideas?
Thanks
The following line are complety wrong:
public Secondary(){
Secondary gui = new Secondary();
SwingUtilities.invokeLater(gui);
}
Each time you call new Secondary() somewhere in your code, the above code will be triggered, which in turn calls new Secondary() again, and again, and again, ... and your program is blocked.
You probably want to replace it either by
public Secondary(){
SwingUtilities.invokeLater(this);
}
which will avoid the loop, but this is weird behaviour for a constructor.
It makes much more sense to switch to an empty constructor (or delete it all together)
public Secondary(){
}
and rewrite your listener to
public void actionPerformed(ActionEvent a){
Secondary s = new Secondary();
SwingUtilities.invokeLater( s );
}
I would recommend that you completely re-design your program. I find that it is most helpful to gear my GUI's towards creation of JPanels, not top level windows such as JFrame, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. I find that this greatly increase the flexibility of my GUI coding, and is exactly what I suggest that you do. So...
Your first class creates a JPanel that is then placed into a JFrame.
In the first class's ActionListener, create an instance of the 2nd class, place it into a JDialog (not a JFrame), and then display it.
For example,
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class TwoWindowEg {
public TwoWindowEg() {
// TODO Auto-generated constructor stub
}
private static void createAndShowGui() {
GuiPanel1 mainPanel = new GuiPanel1();
JFrame frame = new JFrame("Main GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_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();
}
});
}
}
class GuiPanel1 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private GuiPanel2 guiPanel2 = new GuiPanel2(); // our second class!
private JDialog dialog = null; // our JDialog
public GuiPanel1() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JButton(new LaunchNewWindowAction("Launch New Window")));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class LaunchNewWindowAction extends AbstractAction {
public LaunchNewWindowAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
// get the Window that holds this JPanel
Window win = SwingUtilities.getWindowAncestor(GuiPanel1.this);
dialog = new JDialog(win, "Second Window", ModalityType.APPLICATION_MODAL);
dialog.add(guiPanel2);
dialog.pack();
}
dialog.setVisible(true);
}
}
}
class GuiPanel2 extends JPanel {
public GuiPanel2() {
setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
add(new JLabel("The second JPanel/Class"));
add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
}
}
class DisposeAction extends AbstractAction {
public DisposeAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose();
}
}
Alternatively, you could swap JPanel "views" using a CardLayout, but either way, you will want to avoid showing two JFrames. Please have a look at The Use of Multiple JFrames, Good/Bad Practice?.
I created two classes in netbeans;One of them is a JPanel form and another is a JFrame form;
How can i add the JPanel class into JFrame form class?
I wrote this code in constructor of JFrame form Class but ,it didnt work.
public JFrameClass() {
initComponents();
this.getContentPane().add(jpc = new JPanelClass());
jpc.setVisible(true);
this.pack();
this.setVisible(true);
}
You need to make sure the JPanelClass is visible from where your JFrameClass is.
Then do the following:
JPanelClass jpc = new JPanelClass()
this.getContentPane().add(jpc);
Also, there is no need to call jpc.setVisible(true);
The resulting code should be:
public JFrameClass() {
initComponents();
JPanelClass jpc = new JPanelClass()
getContentPane().add(jpc);
pack();
setVisible(true);
}
How can i add the JPanel class into JFrame form class in netbeans?
In your JFrame class just set your JPanel and add its to Container.
JPanel panel = new JPanelClass();
controls.add(panel);
Note: You should have some private void method named for example createAndAddCompontents() and call it in your constructor.
public JFrameClass() {
...
createAndAddCompontents();
}
Then when you want to execute your Application so in main() method you should call it similar like this:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
YouJFrameClass initAndShowComponents = new YouJFrameClass();
initAndShowComponents.setVisible(true);
}
});
set the bounds of the JPanel so that the container knows where to draw it
public void run() {
NewJFrame frame = new NewJFrame();
NewJPanel panel = new NewJPanel();
panel.setBounds(0, 0, 200, 200);
frame.add(panel);
frame.setVisible(true);
}
I've got one class called WindowTemplate that is the base for other (more complex) windows. It is an abstract class and then I'm trying to use the "extend" trick to add more stuff to the new window, keeping the original "skeleton". That is my problem though, because if I run WindowTemplate.createWindow(); or a_Welcome.createWindow(); (they should be point to the same thing), I get my "base" window. But when I run a_Welcome window = new a_Welcome(); (what should be the base + new stuff) I get only the extra bits that I added without the original features. Here is my code:
package windows;
import java.awt.*;
import javax.swing.*;
public abstract class WindowTemplate extends JFrame {
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
public static void createWindow() {
JFrame myFrame = new JFrame("My first window");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myFrame.setSize(550, 450);
myFrame.setLocationRelativeTo(null);
// JLabel emptyLabel = new JLabel("");
// emptyLabel.setPreferredSize(new Dimension(550, 450));
// myFrame.getContentPane().setLayout(new CardLayout());
// myFrame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
// myFrame.pack();
}
}
the class with new window and some extra stuff (ignore a_):
package windows;
import java.awt.*;
import javax.swing.*;
public class a_Welcome extends WindowTemplate {
public a_Welcome() {
JPanel area = new JPanel();
JLabel text = new JLabel("One line another line and another line"); // , JLabel.CENTER);
// text.setBounds(80, 400, 400, 50);
add(area);
// area.setLayout(null);
area.add(text, new CardLayout());
// area.add(text); // , BorderLayout.CENTER);
Font font = new Font("SansSerif", Font.BOLD, 30);
text.setFont(font);
text.setForeground(Color.green);
area.setBackground(Color.darkGray);
area.setSize(550, 450);
}
}
// timer-after 5 seconds-go to the next window (countdown in the bottom right corner)
and the main:
package windows;
public class Launcher {
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
// WindowTemplate.createWindow();
// a_Welcome.createWindow();
a_Welcome window = new a_Welcome();
window.setVisible(true);
}
});
}
}
Thanks for your help!
Static method createWindow() always creates a new JFrame which is not a superclass of the WindowTemplate. Constructor of the a_Window is adding components to the WindowTemplate which hasn't been initialized since the static createWindow() creates an independent frame.
I would suggest you to change the static createWindow() into WindowTemplate constructor and try running main once again.
package windows;
import java.awt.*;
import javax.swing.*;
public abstract class WindowTemplate extends JFrame {
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
public WindowTemplate () {
JFrame myFrame = new JFrame("My first window");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myFrame.setSize(550, 450);
myFrame.setLocationRelativeTo(null);
// JLabel emptyLabel = new JLabel("");
// emptyLabel.setPreferredSize(new Dimension(550, 450));
// myFrame.getContentPane().setLayout(new CardLayout());
// myFrame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
// myFrame.pack();
}
}
You have another JFrame defined in the static createWindow() method. This means that you are adding the components to this frame that is scoped to the createWindow() method only and in the constructor you are adding to the a_Welcome instance.
You should do something like this
public class BaseWindow() {
//Constructor
public BaseWindow() {
init();
}
public void init() {
//add basic components
}
}
public class SubClassWindow() {
public SubClassWindow() {
super();
}
#Override
public void init() {
super.init(); //important so you get the base stuff
//add other components
}
}
Code not tested.
Another approach you might consider would be to have a JFrame that is just a wrapper and compose the window by adding a panel. Let's say you want a toolbar at the top of every window you're creating. Each window would have different buttons on the toolbar and a different set of components at the bottom. This way you are doing composition instead of inheritance, because inheritance can get ugly later on. (For discussions on that point, see this, this, and this for starters)
That would look something like:
public interface AppPanel {
List<JButton> getToolbarButtons();
boolean okToClose();
JPanel getGui();
}
public MyPanel extends JPanel implements AppPanel {
//standard swing components stuff set up here
public List<JButton> getToolbarButtons() {
//set up buttons and their actions
return buttonList;
}
public boolean okToClose() {
//ask user if they want to save, etc.
return true;
}
public JPanel getGui() {
return this;
}
}
public AppFrame extends JFrame {
private AppPanel panel;
public static AppFrame createFrame(AppPanel panel) {
AppFrame frame = new AppFrame(panel);
return frame;
}
public AppFrame(AppPanel panel) {
super();
this.panel = panel;
add(panel.getGui(), someLayoutConstraints);
panel.getToolbarButtons(); //do stuff with the buttons
//...
this.addWindowListener(new WindowAdapter() {
public void WindowClosing(WindowEvent e) {
if (panel.isOkToClose()) {
setVisible(false);
}
}
});
}
}