If I want to make a class that can be run as both an JApplet and JFrame I thought that all the class had to do was extend the JApplet. I had asked this question in a post earlier but I am not sure how to extends this question to that question. I have the life cycle of an applet included in this code and along with the main method.
import java.awt.*;
import java.applet.Applet;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class LifeCycle extends Applet
{
private static final long serialVersionUID = 1L;
String output = "test";
String event;
public void init()
{
gui(); //I am not certain if this needs to be there.
event = "\nInitializing...";
printOutput();
}
public void start()
{
event = "\nStarting...";
printOutput();
}
public void stop()
{
event = "\nStopping...";
printOutput();
}
public void destroy()
{
event = "\nDestroying...";
printOutput();
}
private void printOutput()
{
System.out.println(event);
output += event;
repaint();
}
private void gui() {
JFrame f = new JFrame("Not resizable");
JPanel d = new JPanel();
d.setBackground(Color.BLACK);
f.add(d);
f.setSize(745,440);
f.setResizable(false);
f.setLocationRelativeTo(null);
f.setTitle("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g)
{
System.out.println("Graphics Paint Method!");
g.drawString(output, 100, 100);
}
public static void main(String[] args) {
LifeCycle l = new LifeCycle();
l.gui();
}
}
If you need something that can be run in a JFrame or a JApplet, put all the logic and things into a JPanel and depending on which you want make either a JFrame or a JApplet and add the JPanel to either.
Edit for all those lifecycle things, you can have either the applet or frame call them as necessary on your panel.
Edit: example
public class MyPanel extends JPanel {
public MyPanel()
{
setBackground(Color.BLACK);
setForeground(Color.WHITE);
}
String output = "test";
String event;
public void init()
{
event = "\nInitializing...";
printOutput();
}
// Put all the other methods in here too
private void printOutput()
{
System.out.println(event);
output += event;
repaint();
}
#Override
public void paintComponent(Graphics g)
{
System.out.println("Graphics Paint Method!");
g.setColor(this.getBackground());
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(this.getForeground());
g.drawString(output, 100, 100);
}
}
public class MyFrame extends JFrame {
MyPanel myPanel;
public MyFrame()
{
super("Test frame");
setSize(745,440);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myPanel=new MyPanel();
add(myPanel,BorderLayout.CENTER);
}
public static void main(String[] args)
{
MyFrame f = new MyFrame();
f.setVisible(true);
}
}
public class MyApplet extends JApplet {
private static final long serialVersionUID = 1L;
MyPanel myPanel;
#Override
public void init()
{
myPanel = new MyPanel();
getContentPane().add(myPanel,BorderLayout.CENTER);
}
}
Then add methods to JFrame and JApplet to call the relevant methods on myPanel
For JFrame I recommend WindowListener and whatnot. For JApplet you can just have the init, start, destroy and stop methods to call those methods on the panel.
For WindowListener or perhaps more conveniently WindowAdapter, this link seems to be a good reference: http://way2java.com/awt-components/java-frame-closing-windowadapter/
Simply add() the applet to a JFrame and then call the applet's life cycle methods on the appropriate events (init() after you construct it, destroy() when the frame is closing etc)
Edit: yes the call to gui() should be there and not in main
Related
So I'm not sure what the problem is with the repaint method. It won't fill in a new background colour. It doesn't seem to print out a text within that method whenever I tried to debug it. I have 3 classes: GameInterface, Renderer, and RepaintConfiguration. The RepaintConfiguration extends from the GameInterface class and implements ActionListener.
public class GameInterface {
public static GameInterface gameInterface;
public static JFrame jframe;
private String title;
private Container container;
public GameInterface() {
gameInterface = this;
jframe = new JFrame();
jframe.setSize(1500, 800);
jframe.setResizable(false);
jframe.setTitle("Jetpack");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setVisible(true);
}
}
public class Renderer extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
RepaintConfiguration.repaintConfiguration.repaint(g);
}
}
public class RepaintConfiguration extends GameInterface implements ActionListener
{
public static RepaintConfiguration repaintConfiguration;
public static Renderer renderer;
public static GameInterface gameInterface;
public RepaintConfiguration() {
super();
repaintConfiguration = this;
renderer = new Renderer();
super.jframe.add(renderer);
}
#Override
public void actionPerformed(ActionEvent e) {
renderer.repaint();
}
public void repaint(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, 1500, 800);
}
}
I managed to get your code to compile and run. Public classes have to be inner classes.
I added a main method. I added a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I reordered the JFrame method calls. The JFrame methods must be called in a specific order. This is the order I use for all my Swing applications.
You don't size the JFrame. You size the drawing JPanel. The JFrame includes decorations that take up some space.
I left your convoluted drawing code. You're going to have great difficulties extending this code to actually create a game.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GameInterface {
private JFrame jframe;
private Renderer renderer;
private RepaintConfiguration repaintConfiguration;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GameInterface();
}
});
}
public GameInterface() {
this.repaintConfiguration = new RepaintConfiguration(this);
jframe = new JFrame();
jframe.setTitle("Jetpack");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);
this.renderer = new Renderer(repaintConfiguration);
jframe.add(renderer, BorderLayout.CENTER);
jframe.pack();
jframe.setLocationByPlatform(true);
jframe.setVisible(true);
}
public Renderer getRenderer() {
return renderer;
}
public class Renderer extends JPanel {
private static final long serialVersionUID = 1L;
private RepaintConfiguration repaintConfiguration;
public Renderer(RepaintConfiguration repaintConfiguration) {
this.repaintConfiguration = repaintConfiguration;
this.setPreferredSize(new Dimension(1500, 800));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
repaintConfiguration.repaint(g);
}
}
public class RepaintConfiguration implements ActionListener {
private GameInterface gameInterface;
public RepaintConfiguration(GameInterface gameInterface) {
this.gameInterface = gameInterface;
}
#Override
public void actionPerformed(ActionEvent event) {
gameInterface.getRenderer().repaint();
}
public void repaint(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, 1500, 800);
}
}
}
Hi, I'm new to Java and I have the following problem:
I created a JFrame and I want the JPanel to change when clicking a JButton. That does almost work.The only problem is that the program creates a new window and then there are two windows. One with the first JPanel and one with the second JPanel.
Here is my current code:
first class:
public class Program {
public static void main (String [] args) {
new window(new panel1());
}
}
second class:
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame {
private static final long serialVersionUID = 1L;
Window(JPanel panel) {
setLocation((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 200,
(int) Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 100);
setSize(400, 200);
setTitle("test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setContentPane(panel);
setVisible(true);
}
}
third class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Panel1 extends JPanel {
private final long serialVersionUID = 1L;
Panel1() {
JButton nextPanelButton = new JButton("click here");
add(nextPanelButton);
ActionListener changePanel = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
new window(new panel2());
}
};
nextPanelButton.addActionListener(changePanel);
}
}
fourth class:
public class Panel2 extends JPanel {
private static final long serialVersionUID = 1L;
Panel2() {
JLabel text = new JLabel("You pressed the Button!");
add(text);
}
}
But I just want to change the JPanel without opening a new window. Is there a way to do that?
Thanks in advance!
This is a demo
import javax.swing.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainFrame("Title").setVisible(true);
});
}
}
MainFrame.java
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame {
private JPanel viewPanel;
public MainFrame(String title) {
super(title);
createGUI();
}
private void createGUI() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
setMinimumSize(new Dimension(600, 480));
viewPanel = new JPanel(new BorderLayout());
add(viewPanel, BorderLayout.CENTER);
showView(new View1(this));
pack();
}
public void showView(JPanel panel) {
viewPanel.removeAll();
viewPanel.add(panel, BorderLayout.CENTER);
viewPanel.revalidate();
viewPanel.repaint();
}
}
View1.java
import javax.swing.*;
import java.awt.*;
public class View1 extends JPanel {
final private MainFrame owner;
public View1(MainFrame owner) {
super();
this.owner = owner;
createGUI();
}
private void createGUI() {
setLayout(new FlowLayout());
add(new JLabel("View 1"));
JButton button = new JButton("Show View 2");
button.addActionListener(event -> {
SwingUtilities.invokeLater(() -> owner.showView(new View2(owner)));
});
add(button);
}
}
View2.java
import javax.swing.*;
import java.awt.*;
public class View2 extends JPanel {
final private MainFrame owner;
public View2(MainFrame owner) {
super();
this.owner = owner;
createGUI();
}
private void createGUI() {
setLayout(new FlowLayout());
add(new JLabel("View 2"));
JButton button = new JButton("Show View 1");
button.addActionListener(event -> {
SwingUtilities.invokeLater(() -> owner.showView(new View1(owner)));
});
add(button);
}
}
First of all, take a look at Java naming conventions, in particular your class names should start with a capitalized letter.
If you want to avoid to open a new window every time you click the button, you could pass your frame object to Panel1 constructor, and setting a new Panel2 instance as the frame content pane when you click the button. There is also no need to pass Panel1 to Window constructor (please note that Window class is already defined in java.awt package, it would be better to avoid a possible name clash renaming your class ApplicationWindow, MyWindow or something else).
You could change your code like this (only relevant parts):
public class Program
{
public static void main (String [] args) {
SwingUtilities.invokeLater (new Runnable () {
#Override public void run () {
new Window ().setVisible (true);
}
};
}
}
class Window extends JFrame
{
// ...
Window () {
// ...
setContentPane(new Panel1 (this));
}
}
class Panel1 extends JPanel
{
// ...
Panel1 (JFrame parent) {
// ...
ActionListener changePanel = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
parent.setContentPane (new Panel2 ());
}
};
// ...
}
Also note the SwingUtilities's invokeLater call, which is the best way to initialise your GUI in the EDT context (for more info look at this question).
Finally, you could avoid to create a new Panel2 instance every time you click the button, simply by using a CardLayout.
Take a look at the official tutorial.
This is an old post, but it may be useful to answer it in a simplified way. Thanks to mr mcwolf for the first answer.
If we want to make 1 child jframe interact with a main jframe in order to modify its content, let's consider the following case.
parent.java and child.java.
So, in parent.java, we have something like this:
Parent.java
public class Parent extends JFrame implements ActionListener{
//attributes
//here is the class we want to modify
private some_class_to_modify = new some_class_to_modify();
//here is a container which contains the class to modify
private JPanel container = new JPanel();
private some_class = new some_class();
private int select;
//....etc..etc
//constructor
public Parent(){
this.setTitle("My title");
//etc etc
//etc....etc
container.add(some_class_to_modify,borderLayout.CENTER);
}
//I use for instance actionlisteners on buttons to trigger the new JFrame
public void actionPerformed(ActionEvent arg0){
if((arg0.getSource() == source_button_here)){
//Here we call the child class and send the parent's attributes with "this"
Child child = new Child(this);
}
//... all other cases
}//Here is the class where we want to be able to modify our JFrame. Here ist a JPanel (Setcolor)
public void child_action_on_parent(int selection){
this.select = selection;
System.out.println("Selection is: "+cir_select);
if(select == 0) {
//Do $omething with our class to modify
some_class_to_modify.setcolor(Color.yellow);
}
}
In child.java we would have something like this:
public class Child extends JFrame implements ActionListener {
//Again some attributes here
private blabla;
//Import Parent JFrame class
private Parent owner;
private int select_obj=0;
//Constructor here and via Parent Object Import
public Child(Parent owner){
/*By calling the super() method in the constructor method, we call the parent's
constructor method and gets access to the parent's properties and methods:*/
super();
this.owner = owner;
this.setTitle("Select Method");
this.setSize(400, 400);
this.setContentPane(container);
this.setVisible(true);
}
class OK_Button implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object Selection = select;
if(Selection == something) {
select_obj=0;
valid = JOptionPane.showConfirmDialog(null,"You have chosen option 1. Do you want to continue?","Minimum diameter",2);
}
System.out.println("Option is:"+valid);
if(valid == 0) {
setVisible(false);
//Here we can use our herited object to call the child_action_on_parent public class of the Parent JFrame. So it can modify directly the Panel
owner.child_action_on_parent(select_obj);
}
}
}
I'm building a program that requires swapping out the current, visible JPanel with another. Unfortunately there seems to be multiple to go about this and all of my attempts have ended in failure. I can successfully get the first JPanel to appear in my JFrame, but swapping JPanels results in a blank JFrame.
My Main JFrame:
public class ShellFrame {
static CardLayout cl = new CardLayout(); //handles panel switching
static JFrame frame; //init swing on EDT
static MainMenu mm;
static Panel2 p2;
static Panel3 p3;
public static void main(String[] args) {
initFrame();
}
public static void initFrame() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(3);
frame.setLayout(cl);
mm = new MainMenu();
pp = new PlacementPanel();
//first panel added to frame will always show first
frame.add(mm, "MainMenu");
frame.pack(); //sizes frame to fit the panel being shown
frame.setVisible(true);
}
});
}
public static void switchPanel(String name) {
cl.show(frame.getContentPane(), name);
frame.pack();
}
public static void updatePanel2(/* args */) {
frame.removeAll();
p2 = new Panel2(/* args */);
frame.add(pp, "PlacementPanel");
frame.pack();
frame.validate();
frame.repaint();
}
I'm trying to use updatePanel2 to swap out the existing panel with a new Panel2 but It doesn't seem to be working. Panel2 works fine on it's own but trying to use it in conjunction with my program simply yields a blank window. Any help would be greatly appreciated!
that requires swapping out the current, visible JPanel with another
Have a look at CardLayout for a complete example of how to do it properly.
I have a Swing app which 'swaps' Panels when the user press the 'SPACE' key, showing a live plot of a running simulation. What i did goes like this:
public class MainPanel extends JPanel implements Runnable {
// Called when the JPanel is added to the JFrame
public void addNotify() {
super.addNotify();
animator = new ScheduledThreadPoolExecutor(1);
animator.scheduleAtFixedRate(this, 0, 1000L/60L, TimeUnit.MILLISECONDS);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (spacePressed)
plot.render(g);
else
simulation.render(g);
}
public void run() {
simulation.update();
repaint();
}
}
public class PlotView {
public void render(Graphics g) {
//draw the plot here
}
}
public class SimulationView {
public void render(Graphics g) {
//draw simulation here
}
}
This works very well for my 'show live plot' problem. And there's also the CardLayout approach, which you may turn into a new separate question if you having trouble. Good luck!
You should do .setVisible(false); to the panel which you want to be replaced.
Here is a working example, it switches the panels when you press "ENTER";
If you copy this in an IDE, automatically get the imports (shift+o in Eclipse);
public class MyFrame extends JFrame implements KeyListener {
private JButton button = new JButton("Change Panels");
private JPanel panelOnFrame = new JPanel();
private JPanel panel1 = new JPanel();
public MyFrame() {
// adding labels to panels, to distinguish them
panelOnFrame.add(new JLabel("panel on frame"));
panel1.add(new JLabel("panel 1"));
setSize(new Dimension(250,250));
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(button);
add(panelOnFrame);
setVisible(true);
addKeyListener(this);
addKeyListener(this);
setFocusable(true);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
}
#Override
public void keyPressed(KeyEvent k) {
if(k.getKeyCode() == KeyEvent.VK_ENTER){
//+-------------here is the replacement:
panelOnFrame.setVisible(false);
this.add(panel1);
}
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
i'd like this button to (on click) draw an Oval. Problem is that eclipse says something about missing semicolons (in the action listener definition) and i dont understand why. Whats the proper way of passing methods (bulid in or custom) to the action listeners?
public class figury implements ActionListener {
public figury() {
frame();
}
public void frame() {
JFrame f = new JFrame();
f.setVisible(true);
f.setSize(480, 480);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
JButton kolo = new JButton("Rysuj kolo");
JButton kolo = new JButton("Rysuj kwadrat");
kwadrat.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
public void paintComponent(Graphics g){
g.fillOval(50,50,100,100);
g.setColor(Color.RED);
}
}
});
p.add(kolo);
f.add(p);
}
public static void main(String[] args) {
new figury();
}
}
You are trying to define a method inside another method there. In your case, the problem is in the line containing
public void paintComponent(Graphics g) {
...
This cannot be defined inside another method in java. There are good ideas for painting in java in these official documentation links and stackoverflow questions:
How to make canvas with Swing?
http://www.oracle.com/technetwork/java/painting-140037.html
If your figury class implements ActionListener, it should implement public void actionPerformed(ActionEvent e) method.
Also you are trying to declare a method paintComponent() inside another actionPerformed() method.
I think your code should look something like this:
public class figury implements ActionListener {
public figury() {
frame();
}
public void frame() {
JFrame f = new JFrame();
f.setVisible(true);
f.setSize(480, 480);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
JButton kolo = new JButton("Rysuj kolo");
JButton kwadrat = new JButton("Rysuj kwadrat");
kwadrat.addActionListener(this);
p.add(kolo);
p.add(kwadrat);
f.add(p);
}
#Override
public void actionPerformed(ActionEvent e) {
paintComponent(/*pass here a Graphics object*/);
}
public void paintComponent(Graphics g) {
g.fillOval(50,50,100,100);
g.setColor(Color.RED);
}
public static void main(String[] args) {
new figury();
}
}
i have a question , i have this timer code in java that when its executed it displays a count down timer on its own JFrame label, what i want to do is to display this timer on another JFrame form label without having to move the code to other classes.
I hope you can help me with this thanks lot guys .
this is the code for the Timer class:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TimerExample extends JFrame {
final JLabel label;
Timer countdownTimer;
int timeRemaining = 10;
public TimerExample() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
label = new JLabel(String.valueOf(timeRemaining), JLabel.CENTER);
getContentPane().add(label);
countdownTimer = new Timer(1000, new CountdownTimerListener());
setVisible(true);
countdownTimer.start();
}
class CountdownTimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (--timeRemaining > 0) {
label.setText(String.valueOf(timeRemaining));
} else {
label.setText("Time's up!");
countdownTimer.stop();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TimerExample();
}
});
}
}
thanks
Here it is,
Following is my TestTimer class which accepts a JLabel as input
public class TestTimer {
private JLabel label;
Timer countdownTimer;
int timeRemaining = 10;
public TestTimer(JLabel passedLabel) {
countdownTimer = new Timer(1000, new CountdownTimerListener());
this.label = passedLabel;
countdownTimer.start();
}
class CountdownTimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (--timeRemaining > 0) {
label.setText(String.valueOf(timeRemaining));
} else {
label.setText("Time's up!");
countdownTimer.stop();
}
}
}
}
And here is another Main class which is actually extending a JFrame and showing a label in it,
public class TimerJFrame extends JFrame{
private static final long serialVersionUID = 1L;
private JLabel label;
public TimerJFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
label = new JLabel("10", JLabel.CENTER);
getContentPane().add(label);
new TestTimer(label);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TimerJFrame();
}
});
}
}
Second Code passes a created JLabel to first class and first class uses it to show timer.
You need to follow following steps,
Modify TimerExample constructor to accept JLabel. And initialize JLabel of TimerExample class with passwd JLabel
Pass JLabel from other JFrame class.
Remove main method from this as it will not be required.
Bu first step here, constructor will accept predefined JLabel from other classes and use those to display timer.