JApplet contain a frame, or JApplet alone? - java

I have this project that I need to publish, but don't know which way will be best. Can somebody help me please.
I have a Gui application(Jframe). In there I have a Jpanel that contains some animations (implement runnable). So in my main method I would call the constructor first, so everything display nicely, then called Runner.start(). (Thread)
So basically the gui pop up and then the animation happens, to be specific the animation is just the title of my program that slides in.
Now I want to put this on the website so my students can use.
I do not want to use java web start, i want this to act as an applet.
So do i put this jframe into my applet?
or should I convert this whole thing from jframe to japplet? and is this applet need to implement Runnable?
The thing that bug me is that Japplet has no main method, so how can I specified when my Jpanel can execute its animation? I want the animation to occur after everything has load up on the screen, not before.
I guess put it as the last statement of init() method? Correct me if I am wrong.
Thanks,

I have a Gui application(Jframe). .. I want to put this on the website so my students can use.
While it is possible to convert the frame to an applet, a better option is to launch the frame from a link using Java Web Start.

you can do both:
MainGui
import java.awt.BorderLayout;
import javax.swing.*;
public class MainGui extends JPanel {
public MainGui() {
this(null);
}
public MainGui(MyJApplet applet) {
this.applet = applet;
if (!isApplet()) {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} else
frame = null;
setLayout(new BorderLayout());
// setPreferredSize(new Dimension(640, 480));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainGui.this.run();
}
});
}
String title() {
return "Title";
}
public void addContent() {
add(new JLabel("add content! top"));
}
void run() {
if (isApplet()) addContent();
else {
frame.setTitle(title());
frame.getContentPane().add(this, BorderLayout.CENTER);
addContent();
frame.pack();
System.out.println(getSize());
frame.setVisible(true);
}
}
boolean isApplet() {
return applet != null;
}
public static void main(String[] args) {
new MainGui(null);
}
protected final JFrame frame;
protected final MyJApplet applet;
private static final long serialVersionUID = 1;
}
MyJApplet
import java.awt.BorderLayout;
import javax.swing.JApplet;
public class MyJApplet extends JApplet {
public void start() {
}
public void init() {
getContentPane().setLayout(new BorderLayout());
addContent();
}
public void addContent() {
getContentPane().add(new MainGui(this), BorderLayout.CENTER);
}
public static void main(String[] args) {
new MainGui(null);
}
private static final long serialVersionUID = 1;
}

Related

How can I call a method on a parent panel from an action listener

I had a problem and found a solution, but I can't understand why this following code is not working.
What I want to do is, that the tab is switching when a button gets pressed in the "Administration.class".
I got a JTabbedPane which is added in the "Main.class". It is declared as a private variable.
private JTabbedPane JPT;
then I have a simple method, which shall change the tab, when called:
public void SetPane() {
JTP.setSelectedIndex(2);
}
Then I am creating a object of the Main.class in the Administration.class and calling this method, when the button is pressed:
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Main m = new Main();
m.SetPane();
}
});
But this is not working. Nothing happens, when the button gets clicked, I even get not error.
This works:
Main.class
public static JTabbedPane JTP;
Administration.class
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Main.JTP.setSelectedIndex(2);
}
});
Why example first is not working, and maybe you guys have a link, where I could have a look to a content which is describing this problem. If you just wanna handle a variable and their methods, what is the better way?
Thanks in advance!
Main.class:
public class Main extends JDialog {
private static final long serialVersionUID = 1L;
private Home home = new Home();
private Insertation insertation = new Insertation();
private Edit edit = new Edit();
private Administration administration = new Administration();
private Addition addition = new Addition();
public static JTabbedPane JTP;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Main dialog = new Main();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the dialog.
*/
public Main() {
super(null, java.awt.Dialog.ModalityType.TOOLKIT_MODAL);
setResizable(false);
setSize(1030, 720);
getContentPane().setLayout(new BorderLayout());
setTitle("Ebay Manager");
JTP = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
JTP.addTab("Home", home);
JTP.addTab("Inserat", insertation);
JTP.addTab("Bearbeitung", edit);
JTP.addTab("Verwaltung", administration);
JTP.addTab("Zusatz", addition);
getContentPane().add(JTP);
}
}
Administration.class:
public class Administration extends JPanel {
private static final long serialVersionUID = 1L;
private JButton btnRework;
private Main main;
/**
* Create the panel.
*/
public Administration() {
setLayout(null);
setSize(1000, 650);
setDoubleBuffered(true);
btnRework = new JButton("Bearbeiten");
btnRework.setBounds(42, 571, 116, 32);
add(btnRework);
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.SetPane();
}
});
}
}
You are switching panes in a new undrawn frame that you create and throw away inside your action listener. You need to switch panes in the frame that you have (presumably) packed and drawn in your application.
So instead of
Main m = new Main();
m.SetPane();
you need
myMainFrame.SetPane();
Exactly how you create and remember myMainFrame is beyond the scope of this answer (unless you add more code to your question).
Main m = new Main();
m.SetPane();
Here, you are creating an instance of Main but you are not adding to it anywhere.
Edit:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class Administrator extends JFrame {
private Main main;
public Administrator() {
main = new Main();
add(main);
JButton button = new JButton("Set");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
main.setPane();
}
});
add(button, BorderLayout.SOUTH);
}
public static void main(String[] args) {
Administrator adminFrame = new Administrator();
adminFrame.setSize(400, 400);
adminFrame.setVisible(true);
}
}
class Main extends JPanel {
private JTabbedPane jtp;
public Main() {
super(new BorderLayout());
jtp = new JTabbedPane();
jtp.add("tab1", new JLabel("Content1"));
jtp.add("tab2", new JLabel("Content2"));
add(jtp);
}
public void setPane() {
jtp.setSelectedIndex(1);
}
}
I found my own solution because of the answer of rdonuk. Since I can't make another instance of the Main.class I set the JTabbedPane as variable in the Administration.class when creating the Main.class. Just a easy setter method. Thanks for all answers!

Is there a way to halt a method until a button is pressed?

I have been coding for a card game and cannot get my method to wait for a button to be pressed.
The general code goes like this. When I run the code, doTask() has a segment where it needs to wait for a button to be pressed. However, the method does not wait for the button and just loops through.
I am currently thinking to have a while loop with a boolean (buttonIsPressed) which will be triggered true in actionPerformed(e). However, is there a simpler way to do this?
Any help would be appreciated.
Thank you.
public class Test {
public Test()
{
// all vars instantiated
while (!(taskLeft==0))
{
doTask();
taskLeft--;
}
}
private class Handler implements ActionListener
{
public void actionPerformed(ActionEvent arg0) {
// update information in doTask()
}
}
}
Yours is a classic XY Problem where you ask how to solve a specific code problem when the best solution is to use a completely different approach. You're thinking of how do I code this event-driven GUI program to work as a linear console program, and that's not how you should approach this. Instead look at changing object state and basing response of the object to events based on its state.
So get rid of the while loop, and instead do your task when the button is pushed based on the state of the GUI. The details of any solution will depend on the details of your problem, something you may wish to share with us.
So for instance, here taskLeft represents a "state" of the TaskEx object, and your Handler's response will depend on the state of this variable.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class TaskEx extends JPanel {
private int taskLeft = 10;
public void doTask() {
//
}
private class Handler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (taskLeft > 0) {
doTask();
taskLeft--;
}
}
}
}
An actually functioning example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class TaskEx extends JPanel {
private int taskLeft = 10;
private JLabel taskCountLabel = new JLabel(String.valueOf(taskLeft));
public TaskEx() {
JPanel northPanel = new JPanel();
northPanel.add(new JLabel("Tasks Left:"));
northPanel.add(taskCountLabel);
JPanel centerPanel = new JPanel();
centerPanel.add(new JButton(new Handler("Push Me")));
setLayout(new BorderLayout());
add(northPanel, BorderLayout.PAGE_START);
add(centerPanel, BorderLayout.CENTER);
}
public void doTask() {
taskCountLabel.setText(String.valueOf(taskLeft));
}
private static void createAndShowGui() {
TaskEx mainPanel = new TaskEx();
JFrame frame = new JFrame("Task Example");
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(() -> {
createAndShowGui();
});
}
private class Handler extends AbstractAction {
public Handler(String name) {
super(name);
putValue(MNEMONIC_KEY, (int) name.charAt(0));
}
#Override
public void actionPerformed(ActionEvent e) {
if (taskLeft > 0) {
taskLeft--;
doTask();
}
}
}
}

Running a method after switching cards in cardlayout

I'm sure someone has asked this question before, but my google-fu is not strong today.
I have a JFrame that uses a CardLayout as its manager. How do I run a "Start" method when I switch to each JPanel without using a switch?
The code I use to add the frames to the layout is:
/**
* Adds JPanels to the Card Layout.
* #param panel is the JPanel to add to the layout.
* #param windowName is the identifier used to recognise the Panel.
*/
public final void addToCards(final JPanel panel, final WindowNames windowName) {
view.getBasePanel().add(panel, windowName.getValue());
}
The code I use to switch the layout is:
/**
* Method to change the JPanel currently visible on the BasePanel.
* #param windowName is the name of the JPanel to change to.
*/
public final void changePanel(final WindowNames windowName) {
view.getCardLayout().show(view.getBasePanel(), windowName.getValue());
}
Currently I have an ActionListener set that will call the switch code, but I can't work out how to call the "Start" method within the screen that it will be switching to.
I have an interface setup for each of the JPanels so that the method name will be identical in each.
You can just use a ComponentListener for the panel(s). When the panel becomes the view of the CardLayout, it will fire a component event and handled by componentShown in your listener (as well as the panel taken out of view, handling the componentHidden). Call your start() method there. This way you don't have to explicitly call the start() when the panel changes, as it be called for you.
See How to Write Component Listeners for more details.
Here is a simple example.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main {
private static final String PANEL_A = "panelA";
private static final String PANEL_B = "panelB";
CardLayout layout = new CardLayout();
JPanel panel = new JPanel(layout);
ComponentListenerPanel p1 = new ComponentListenerPanel(PANEL_A);
ComponentListenerPanel p2 = new ComponentListenerPanel(PANEL_B);
JButton b1 = new JButton(PANEL_A);
JButton b2 = new JButton(PANEL_B);
public Main() {
panel.add(p1, PANEL_A);
panel.add(p2, PANEL_B);
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
show(PANEL_A);
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
show(PANEL_B);
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(b1);
buttonPanel.add(b2);
JFrame frame = new JFrame();
frame.add(panel);
frame.add(buttonPanel, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void show(String panelName) {
layout.show(panel, panelName);
}
private class ComponentListenerPanel extends JPanel {
private String panelName;
public ComponentListenerPanel(String panelName) {
this.panelName = panelName;
addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent evt) {
stop();
}
#Override
public void componentShown(ComponentEvent evt) {
start();
}
});
}
public void start() {
System.out.println(panelName + " started");
}
public void stop() {
System.out.println(panelName + " stopped");
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main();
}
});
}
}
Note you haven't actually said where the start method is, so this code/answer is just assuming you have some start method in custom panel. Hope I guessed right. In the future, or even now, you should always post an MCVE so that we don't have to do all this guessing.
I have an interface setup for each of the JPanels so that the method name will be identical in each
So then the problem is getting the current panel that is visible when the panels are swapped so you can invoke the method.
Check out Card Layout Focus for a class that extends CardLayout to provide a few helper methods to add additional functionality for the CardLayout. You would use the getCurrentCard() method.
So your changePane(...) method might be something like:
public final void changePanel(final WindowNames windowName) {
//view.getCardLayout().show(view.getBasePanel(), windowName.getValue());
RXCardLayout layout = view.getCardLayout();
layout.show(view.getBasePanel(), windowName.getValue());
MyInterface panel = (MyInterface)layout.getCurrentCard();
panel.someMethod(...);
}
Of course you would also need to use the RXCardLayout as the layout manager for your main panel.

What am I doing wrong? Java Drawing an Image to JPanel

This is for an assignment, so I'd rather not ask for help, but I can't seem to see what I'm doing wrong. The code will eventually create a window, with an image as the background, and then using information in a text file, place other images at specific points, and the user can zoom in.
At the moment I'm just trying to get an image displayed onto a JPanel inside a JFrame, and I can't seem to get it to work. Could somebody please point out what exactly I'm doing that's leading to the image not displaying?
Code for Map class:
import javax.swing.*;
public class Map extends JPanel
{
static final long serialVersionUID = 1;
public Map()
{
}
public JPanel createContentPane()
{
//Creating a base JPanel to place everything on
JPanel rootGUI = new JPanel();
//Setting the Layout Manager to null to place everything manually
rootGUI.setLayout(null);
rootGUI.setOpaque(true);
return rootGUI;
}
private static void createAndShowGUI()
{
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Test for image");
//Create and set up the content pane
Map demo = new Map();
frame.setContentPane(demo.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setResizable(false);
Hospital hDemo = new Hospital();
frame.add(hDemo);
frame.setVisible(true);
}
public static void main(String[] Args)
{
//Schedule a job for the event-dispatching thread
//Creating and showing this applications GUI
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
And Code for the hospital class:
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
public class Hospital extends JPanel
{
static final long serialVersionUID = 2;
public static BufferedImage hospitalImage;
public Hospital()
{
super();
try
{
hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
}
catch (IOException ex)
{
//Not handled
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(hospitalImage, 50, 50, this);
repaint();
}
}
You haven't defined the size of your Hospital Panel.
update to:
public Hospital()
{
super();
setSize( /* size */ );
try
{
hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
}
catch (IOException ex)
{
//Not handled
}
}
or use a different layoutManager in your JFrame/ContentPane like Borderlayout
in that case you could add the Hospital to your Frame as
frame.add(hDemo, BorderLayout.CENTER);
visual guide to layoutmanagers
Problem is in path you are passing here: hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
Easy solution would be to load your image as a stream:
InputStream stream = getClass().getResourceAsStream("hospital.jpg");
hospitalImage = ImageIO.read(stream);
stream.close();

JPanel appearing to be two times bigger than set resolution

I must say I tried everything and I can't understand what's wrong with my code.
In my SIView class I create MainFrame which extends JFrame with specified resolution (let's say X,Y).
Then I create gamePanel which extends JPanel whith the same resolution as MainFrame, and add it to MainFrame. The problem is that effective resolution of the panel is twice as big (x*2, y*2). It's like the panel is being streched to be twice as big.
Frame will display only a quarter (upper left quarter) of the panel either with pack() or mannualy setting the size, unless I set it to double the resolution in which case It's ok, but that's not a proper way to do that(When calculating positions in the game I have to double everything or divide it by 2 to keep proper proportions). I even tried different Layout managers wthout any succes.
Here's the code of the main view class:
public class SIView implements Runnable {
private final MainFrame mainFrame;
private final GamePanel gamePanel;
public SIView(BlockingQueue<SIEvent> eventQueue) {
this.eventsQueue = eventQueue;
mainFrame = new MainFrame();
gamePanel = new GamePanel();
gamePanel.setVisible(true);
mainFrame.getContentPane().add(gamePanel);
// mainFrame.pack();
#Override
public void run() {
mainFrame.setVisible(true);
}
public void init() {
SwingUtilities.invokeLater(this);
}
//some code not related
}
the frame class:
public class MainFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 6513420589842315661L;
public MainFrame() {
setTitle("Space Intruders");
setSize(new Dimension(SIParams.RES_X, SIParams.RES_Y));
setResizable(false);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
panel class:
public class GamePanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 8112087715257989968L;
private final PlayerShipView playerShip;
private final ArrayList<SmallEnemyShipView> smallEnemyShip;
private final ArrayList<LightMissleView> lightMissle;
public GamePanel() {
setPreferredSize(new Dimension(SIParams.RES_X, SIParams.RES_Y));
setMaximumSize(new Dimension(SIParams.RES_X, SIParams.RES_Y));
setBounds(0, 0, SIParams.RES_X, SIParams.RES_Y);
setBackground(new Color(0, 0, 0));
setLayout(new OverlayLayout(this));
setDoubleBuffered(true);
// TODO
playerShip = new PlayerShipView();
smallEnemyShip = new ArrayList<SmallEnemyShipView>();
lightMissle = new ArrayList<LightMissleView>();
this.add(playerShip);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
//some code not related
}
If I use LayoutManager and properly override getPreferredSize() in GamePanel, the code seems to work as expected:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jfree.ui.OverlayLayout;
public class SIView implements Runnable {
public static interface SIParams {
int RES_X = 500;
int RES_Y = 400;
}
public static class GamePanel extends JPanel {
public GamePanel() {
setBackground(new Color(0, 0, 0));
setLayout(new OverlayLayout());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIParams.RES_X, SIParams.RES_Y);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
// some code not related
}
private JFrame mainFrame;
private GamePanel gamePanel;
#Override
public void run() {
mainFrame = createMainFrame();
gamePanel = new GamePanel();
mainFrame.getContentPane().add(gamePanel);
mainFrame.pack();
mainFrame.setVisible(true);
}
private JFrame createMainFrame() {
JFrame frame = new JFrame();
frame.setTitle("Space Intruders");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
return frame;
}
public void init() {
SwingUtilities.invokeLater(this);
}
// some code not related
public static void main(String[] args) {
new SIView().init();
}
}
I also dropped the MainFrame class since it is not needed to extend JFrame in this context.
I just solved everything :D But I must say I feel stupid. The problem was with painting my components, in paintcomponent() method I painted rectangle on a relative position while changing component position also relatively. That gave the effect of 2xtimes movement etc. because while the component was moving the rectangle was moving inside of it too. I guess I have a lot to learn about Swing ;) Sorry for all this trouble ;)
PS. I didn't have to change anything in Panel/Frame classes except for using pack() method after everything.

Categories